diff --git a/utils/structs/codec.go b/utils/structs/codec.go index 6fc615e6..d421e863 100644 --- a/utils/structs/codec.go +++ b/utils/structs/codec.go @@ -6,15 +6,28 @@ import ( "io" ) +type Codec[V any] struct{} + +type CopyNewer[V any] interface { + CopyNew() *V +} + +func (c *Codec[V]) CopynewWrapper(T interface{}) (*V, error) { + + copyer, ok := T.(CopyNewer[V]) + + if !ok { + return nil, fmt.Errorf("cannot CopyNew: type T=%T does not implement CopyNew", T) + } + + return copyer.CopyNew(), nil +} + type BinarySizer interface { BinarySize() int } -type Codec struct{} - -var codec = Codec{} - -func (c *Codec) BinarySizeWrapper(T interface{}) (size int, err error) { +func (c *Codec[V]) BinarySizeWrapper(T interface{}) (size int, err error) { binarysizer, ok := T.(BinarySizer) if !ok { @@ -24,7 +37,7 @@ func (c *Codec) BinarySizeWrapper(T interface{}) (size int, err error) { return binarysizer.BinarySize(), nil } -func (c *Codec) MarshalBinaryWrapper(T interface{}) (p []byte, err error) { +func (c *Codec[V]) MarshalBinaryWrapper(T interface{}) (p []byte, err error) { binarymarshaler, ok := T.(encoding.BinaryMarshaler) if !ok { @@ -34,7 +47,7 @@ func (c *Codec) MarshalBinaryWrapper(T interface{}) (p []byte, err error) { return binarymarshaler.MarshalBinary() } -func (c *Codec) UnmarshalBinaryWrapper(p []byte, T interface{}) (err error) { +func (c *Codec[V]) UnmarshalBinaryWrapper(p []byte, T interface{}) (err error) { binaryunmarshaler, ok := T.(encoding.BinaryUnmarshaler) if !ok { @@ -44,7 +57,7 @@ func (c *Codec) UnmarshalBinaryWrapper(p []byte, T interface{}) (err error) { return binaryunmarshaler.UnmarshalBinary(p) } -func (c *Codec) ReadWrapper(p []byte, T interface{}) (n int, err error) { +func (c *Codec[V]) ReadWrapper(p []byte, T interface{}) (n int, err error) { reader, ok := T.(io.Reader) if !ok { @@ -54,7 +67,7 @@ func (c *Codec) ReadWrapper(p []byte, T interface{}) (n int, err error) { return reader.Read(p) } -func (c *Codec) WriteWrapper(p []byte, T interface{}) (n int, err error) { +func (c *Codec[V]) WriteWrapper(p []byte, T interface{}) (n int, err error) { writer, ok := T.(io.Writer) if !ok { @@ -64,7 +77,7 @@ func (c *Codec) WriteWrapper(p []byte, T interface{}) (n int, err error) { return writer.Write(p) } -func (c *Codec) WriteToWrapper(w io.Writer, T interface{}) (n int64, err error) { +func (c *Codec[V]) WriteToWrapper(w io.Writer, T interface{}) (n int64, err error) { writerto, ok := T.(io.WriterTo) if !ok { @@ -74,7 +87,7 @@ func (c *Codec) WriteToWrapper(w io.Writer, T interface{}) (n int64, err error) return writerto.WriteTo(w) } -func (c *Codec) ReadFromWrapper(r io.Reader, T interface{}) (n int64, err error) { +func (c *Codec[V]) ReadFromWrapper(r io.Reader, T interface{}) (n int64, err error) { readerfrom, ok := T.(io.ReaderFrom) if !ok { diff --git a/utils/structs/map.go b/utils/structs/map.go index 0e504c04..8ff204c8 100644 --- a/utils/structs/map.go +++ b/utils/structs/map.go @@ -14,10 +14,29 @@ import ( // Map is a struct storing a map of any element indexed by an Integer. type Map[V constraints.Integer, T any] map[V]*T +// CopyNew creates a copy of the oject. +func (m Map[V, T]) CopyNew() *Map[V, T] { + + var mcpy = make(Map[V, T]) + + codec := Codec[T]{} + + var err error + for key, object := range m { + if mcpy[key], err = codec.CopynewWrapper(object); err != nil { + panic(err) + } + } + + return &mcpy +} + // BinarySize returns the size in bytes that the object once marshalled into a binary form. func (m Map[V, T]) BinarySize() (size int) { size = 4 // #Ct + codec := Codec[T]{} + var inc int var err error for _, v := range m { @@ -49,6 +68,8 @@ func (m *Map[V, T]) Read(p []byte) (n int, err error) { return n, fmt.Errorf("cannot Read: len(p)=%d < %d", len(p), m.BinarySize()) } + codec := Codec[T]{} + mi := *m binary.LittleEndian.PutUint32(p[n:], uint32(len(mi))) @@ -92,6 +113,8 @@ func (m *Map[V, T]) WriteTo(w io.Writer) (n int64, err error) { n += int64(inc1) + codec := Codec[T]{} + for _, key := range utils.GetSortedKeys(mi) { if inc1, err = buffer.WriteUint64(w, uint64(key)); err != nil { @@ -131,6 +154,8 @@ func (m *Map[V, T]) Write(p []byte) (n int, err error) { size := int(binary.LittleEndian.Uint32(p[n:])) n += 4 + codec := Codec[T]{} + for i := 0; i < size; i++ { idx := V(binary.LittleEndian.Uint64(p[n:])) @@ -173,6 +198,8 @@ func (m *Map[V, T]) ReadFrom(r io.Reader) (n int64, err error) { n += int64(inc1) + codec := Codec[T]{} + for i := 0; i < int(size); i++ { var key uint64 diff --git a/utils/structs/matrix.go b/utils/structs/matrix.go index 45c87c92..066b39ef 100644 --- a/utils/structs/matrix.go +++ b/utils/structs/matrix.go @@ -12,12 +12,36 @@ import ( // Matrix is a struct storing a vector of Vector. type Matrix[T any] [][]*T +func (m Matrix[T]) CopyNew() *Matrix[T] { + mcpy := Matrix[T](make([][]*T, len(m))) + + var err error + + codec := Codec[T]{} + + for i := range m { + + mcpy[i] = make([]*T, len(m[i])) + + for j := range m[i] { + if mcpy[i][j], err = codec.CopynewWrapper(m[i][j]); err != nil { + panic(err) + } + } + } + + return &mcpy +} + // BinarySize returns the size in bytes of the object // when encoded using MarshalBinary, Read or WriteTo. func (m Matrix[T]) BinarySize() (size int) { size += 8 var err error var inc int + + codec := Codec[T]{} + for _, v := range m { size += 8 for _, vi := range v { @@ -46,6 +70,8 @@ func (m Matrix[T]) Read(b []byte) (n int, err error) { binary.LittleEndian.PutUint64(b[n:], uint64(len(m))) n += 8 + codec := Codec[T]{} + var inc int for _, v := range m { @@ -86,6 +112,8 @@ func (m Matrix[T]) WriteTo(w io.Writer) (int64, error) { n += int64(inc) + codec := Codec[T]{} + for _, v := range m { var inc int @@ -132,6 +160,8 @@ func (m *Matrix[T]) Write(p []byte) (n int, err error) { mi := *m + codec := Codec[T]{} + var inc int for i := range mi { @@ -183,6 +213,8 @@ func (m *Matrix[T]) ReadFrom(r io.Reader) (int64, error) { mi := *m + codec := Codec[T]{} + for i := range mi { var inc int diff --git a/utils/structs/vector.go b/utils/structs/vector.go index 56960c0b..14466aef 100644 --- a/utils/structs/vector.go +++ b/utils/structs/vector.go @@ -5,7 +5,6 @@ import ( "fmt" "io" - //"reflect" "encoding/binary" "github.com/tuneinsight/lattigo/v4/utils/buffer" @@ -13,12 +12,31 @@ import ( type Vector[T any] []*T +// CopyNew creates a copy of the oject. +func (v Vector[T]) CopyNew() *Vector[T] { + vcpy := Vector[T](make([]*T, len(v))) + + var err error + + codec := Codec[T]{} + + for i := range v { + if vcpy[i], err = codec.CopynewWrapper(v[i]); err != nil { + panic(err) + } + } + + return &vcpy +} + // BinarySize returns the size in bytes that the object once marshalled into a binary form. func (v Vector[T]) BinarySize() (size int) { var err error var inc int + codec := Codec[T]{} + size += 8 for _, vi := range v { @@ -47,6 +65,8 @@ func (v *Vector[T]) Read(b []byte) (n int, err error) { binary.LittleEndian.PutUint64(b[n:], uint64(len(vi))) n += 8 + codec := Codec[T]{} + var inc int for i := range vi { if inc, err = codec.ReadWrapper(b[n:], vi[i]); err != nil { @@ -82,6 +102,8 @@ func (v *Vector[T]) WriteTo(w io.Writer) (int64, error) { n += int64(inc) + codec := Codec[T]{} + for i := range vi { var inc int64 if inc, err = codec.WriteToWrapper(w, vi[i]); err != nil { @@ -118,6 +140,8 @@ func (v *Vector[T]) Write(p []byte) (n int, err error) { vi := *v + codec := Codec[T]{} + var inc int for i := range vi { @@ -159,6 +183,8 @@ func (v *Vector[T]) ReadFrom(r io.Reader) (int64, error) { vi := *v + codec := Codec[T]{} + for i := range vi { if vi[i] == nil {