diff --git a/CHANGELOG.md b/CHANGELOG.md index f4b3d8f5..b9cf65e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,8 +10,8 @@ All notable changes to this library are documented in this file. - `BinarySize() int`: size in bytes when written to an `io.Writer` or to a slice of bytes using `Read`. - `WriteTo(io.Writer) (int64, error)`: efficient writing on any `io.Writer`. - `ReadFrom(io.Reader) (int64, error)`: efficient reading from any `io.Reader`. - - `Read([]byte) (int, error)`: highly efficient encoding on preallocated slice of bytes. - - `Write([]byte) (int, error)`: highly efficient decoding from a slice of bytes. + - `Encode([]byte) (int, error)`: highly efficient encoding on preallocated slice of bytes. + - `Decode([]byte) (int, error)`: highly efficient decoding from a slice of bytes. Streamlined and simplified all test related this interface. They can now be implemented with a single line of code. - All: all tests and benchmarks in package other than the `RLWE` and `DRLWE` package that were merely wrapper of methods of the `RLWE` or `DRLWE` have been removed and/or moved to the `RLWE` and `DRLWE` packages. - All: polynomials, ciphertext and keys now all implement the method V Equal(V) bool. diff --git a/bfv/power_basis.go b/bfv/power_basis.go index 1e84dda5..b3aacb92 100644 --- a/bfv/power_basis.go +++ b/bfv/power_basis.go @@ -28,9 +28,9 @@ func (p *PowerBasis) ReadFrom(r io.Reader) (n int64, err error) { return p.PowerBasis.ReadFrom(r) } -func (p *PowerBasis) Write(data []byte) (n int, err error) { +func (p *PowerBasis) Decode(data []byte) (n int, err error) { p.PowerBasis = &rlwe.PowerBasis{} - return p.PowerBasis.Write(data) + return p.PowerBasis.Decode(data) } // GenPower generates the n-th power of the power basis, diff --git a/bgv/power_basis.go b/bgv/power_basis.go index 64ba7872..e688e07c 100644 --- a/bgv/power_basis.go +++ b/bgv/power_basis.go @@ -28,9 +28,9 @@ func (p *PowerBasis) ReadFrom(r io.Reader) (n int64, err error) { return p.PowerBasis.ReadFrom(r) } -func (p *PowerBasis) Write(data []byte) (n int, err error) { +func (p *PowerBasis) Decode(data []byte) (n int, err error) { p.PowerBasis = &rlwe.PowerBasis{} - return p.PowerBasis.Write(data) + return p.PowerBasis.Decode(data) } // GenPower generates the n-th power of the power basis, diff --git a/ckks/power_basis.go b/ckks/power_basis.go index b75fbcaa..23baf4ed 100644 --- a/ckks/power_basis.go +++ b/ckks/power_basis.go @@ -27,9 +27,9 @@ func (p *PowerBasis) ReadFrom(r io.Reader) (n int64, err error) { return p.PowerBasis.ReadFrom(r) } -func (p *PowerBasis) Write(data []byte) (n int, err error) { +func (p *PowerBasis) Decode(data []byte) (n int, err error) { p.PowerBasis = &rlwe.PowerBasis{} - return p.PowerBasis.Write(data) + return p.PowerBasis.Decode(data) } // GenPower recursively computes X^{n}. diff --git a/drlwe/keygen_cpk.go b/drlwe/keygen_cpk.go index 81d4b0fe..b8b657e8 100644 --- a/drlwe/keygen_cpk.go +++ b/drlwe/keygen_cpk.go @@ -37,7 +37,8 @@ type CKGCRP struct { Value ringqp.Poly } -// BinarySize returns the size in bytes that the object once marshalled into a binary form. +// BinarySize returns the size in bytes of the object +// when encoded using Encode. func (share *CKGShare) BinarySize() int { return share.Value.BinarySize() } @@ -47,10 +48,10 @@ func (share *CKGShare) MarshalBinary() (p []byte, err error) { return share.Value.MarshalBinary() } -// Read encodes the object into a binary form on a preallocated slice of bytes +// Encode encodes the object into a binary form on a preallocated slice of bytes // and returns the number of bytes written. -func (share *CKGShare) Read(p []byte) (ptr int, err error) { - return share.Value.Read(p) +func (share *CKGShare) Encode(p []byte) (ptr int, err error) { + return share.Value.Encode(p) } // WriteTo writes the object on an io.Writer. @@ -64,17 +65,16 @@ func (share *CKGShare) WriteTo(w io.Writer) (n int64, err error) { return share.Value.WriteTo(w) } -// UnmarshalBinary decodes a slice of bytes generated by MarshalBinary, -// WriteTo or Read on the object. +// UnmarshalBinary decodes a slice of bytes generated by +// MarshalBinary or WriteTo on the object. func (share *CKGShare) UnmarshalBinary(p []byte) (err error) { - _, err = share.Write(p) - return + return share.Value.UnmarshalBinary(p) } -// Write decodes a slice of bytes generated by MarshalBinary or -// Read on the object and returns the number of bytes read. -func (share *CKGShare) Write(p []byte) (n int, err error) { - return share.Value.Write(p) +// Decode decodes a slice of bytes generated by Encode +// on the object and returns the number of bytes read. +func (share *CKGShare) Decode(p []byte) (n int, err error) { + return share.Value.Decode(p) } // ReadFrom reads on the object from an io.Writer. diff --git a/drlwe/keygen_gal.go b/drlwe/keygen_gal.go index 7f940ea7..2b1465f3 100644 --- a/drlwe/keygen_gal.go +++ b/drlwe/keygen_gal.go @@ -2,6 +2,7 @@ package drlwe import ( "bufio" + "bytes" "encoding/binary" "fmt" "io" @@ -239,23 +240,24 @@ type GKGShare struct { Value structs.Matrix[ringqp.Poly] } -// BinarySize returns the size in bytes that the object once marshalled into a binary form. +// BinarySize returns the size in bytes of the object +// when encoded using Encode. func (share *GKGShare) BinarySize() int { return 8 + share.Value.BinarySize() } // MarshalBinary encodes the object into a binary form on a newly allocated slice of bytes. -func (share *GKGShare) MarshalBinary() (data []byte, err error) { - data = make([]byte, share.BinarySize()) - _, err = share.Read(data) - return +func (share *GKGShare) MarshalBinary() (p []byte, err error) { + buf := bytes.NewBuffer([]byte{}) + _, err = share.WriteTo(buf) + return buf.Bytes(), nil } -// Read encodes the object into a binary form on a preallocated slice of bytes +// Encode encodes the object into a binary form on a preallocated slice of bytes // and returns the number of bytes written. -func (share *GKGShare) Read(data []byte) (n int, err error) { - binary.LittleEndian.PutUint64(data, share.GaloisElement) - n, err = share.Value.Read(data[8:]) +func (share *GKGShare) Encode(p []byte) (n int, err error) { + binary.LittleEndian.PutUint64(p, share.GaloisElement) + n, err = share.Value.Encode(p[8:]) return n + 8, err } @@ -291,18 +293,18 @@ func (share *GKGShare) WriteTo(w io.Writer) (n int64, err error) { } } -// UnmarshalBinary decodes a slice of bytes generated by MarshalBinary, -// WriteTo or Read on the object. -func (share *GKGShare) UnmarshalBinary(data []byte) (err error) { - _, err = share.Write(data) +// UnmarshalBinary decodes a slice of bytes generated by +// MarshalBinary or WriteTo on the object. +func (share *GKGShare) UnmarshalBinary(p []byte) (err error) { + _, err = share.ReadFrom(bytes.NewBuffer(p)) return } -// Write decodes a slice of bytes generated by MarshalBinary or -// Read on the object and returns the number of bytes read. -func (share *GKGShare) Write(data []byte) (n int, err error) { - share.GaloisElement = binary.LittleEndian.Uint64(data) - n, err = share.Value.Write(data[8:]) +// Decode decodes a slice of bytes generated by Encode +// on the object and returns the number of bytes read. +func (share *GKGShare) Decode(p []byte) (n int, err error) { + share.GaloisElement = binary.LittleEndian.Uint64(p) + n, err = share.Value.Decode(p[8:]) return n + 8, err } diff --git a/drlwe/keygen_relin.go b/drlwe/keygen_relin.go index 6f159311..ac350309 100644 --- a/drlwe/keygen_relin.go +++ b/drlwe/keygen_relin.go @@ -308,7 +308,8 @@ func (ekg *RKGProtocol) AllocateShare() (ephSk *rlwe.SecretKey, r1 *RKGShare, r2 return } -// BinarySize returns the size in bytes that the object once marshalled into a binary form. +// BinarySize returns the size in bytes of the object +// when encoded using Encode. func (share *RKGShare) BinarySize() int { return share.GadgetCiphertext.BinarySize() } @@ -318,10 +319,10 @@ func (share *RKGShare) MarshalBinary() (data []byte, err error) { return share.GadgetCiphertext.MarshalBinary() } -// Read encodes the object into a binary form on a preallocated slice of bytes +// Encode encodes the object into a binary form on a preallocated slice of bytes // and returns the number of bytes written. -func (share *RKGShare) Read(data []byte) (n int, err error) { - return share.GadgetCiphertext.Read(data) +func (share *RKGShare) Encode(data []byte) (n int, err error) { + return share.GadgetCiphertext.Encode(data) } // WriteTo writes the object on an io.Writer. @@ -335,16 +336,16 @@ func (share *RKGShare) WriteTo(w io.Writer) (n int64, err error) { return share.GadgetCiphertext.WriteTo(w) } -// UnmarshalBinary decodes a slice of bytes generated by MarshalBinary, -// WriteTo or Read on the object. +// UnmarshalBinary decodes a slice of bytes generated by +// MarshalBinary or WriteTo on the object. func (share *RKGShare) UnmarshalBinary(data []byte) (err error) { return share.GadgetCiphertext.UnmarshalBinary(data) } -// Write decodes a slice of bytes generated by MarshalBinary or -// Read on the object and returns the number of bytes read. -func (share *RKGShare) Write(data []byte) (n int, err error) { - return share.GadgetCiphertext.Write(data) +// Decode decodes a slice of bytes generated by Encode +// on the object and returns the number of bytes read. +func (share *RKGShare) Decode(data []byte) (n int, err error) { + return share.GadgetCiphertext.Decode(data) } // ReadFrom reads on the object from an io.Writer. diff --git a/drlwe/keyswitch_pk.go b/drlwe/keyswitch_pk.go index c2c574be..24c72c96 100644 --- a/drlwe/keyswitch_pk.go +++ b/drlwe/keyswitch_pk.go @@ -136,7 +136,8 @@ type PCKSShare struct { rlwe.OperandQ } -// BinarySize returns the size in bytes that the object once marshalled into a binary form. +// BinarySize returns the size in bytes of the object +// when encoded using Encode. func (share *PCKSShare) BinarySize() int { return share.OperandQ.BinarySize() } @@ -146,10 +147,10 @@ func (share *PCKSShare) MarshalBinary() (p []byte, err error) { return share.OperandQ.MarshalBinary() } -// Read encodes the object into a binary form on a preallocated slice of bytes +// Encode encodes the object into a binary form on a preallocated slice of bytes // and returns the number of bytes written. -func (share *PCKSShare) Read(p []byte) (n int, err error) { - return share.OperandQ.Read(p) +func (share *PCKSShare) Encode(p []byte) (n int, err error) { + return share.OperandQ.Encode(p) } // WriteTo writes the object on an io.Writer. @@ -163,16 +164,16 @@ func (share *PCKSShare) WriteTo(w io.Writer) (n int64, err error) { return share.OperandQ.WriteTo(w) } -// UnmarshalBinary decodes a slice of bytes generated by MarshalBinary, -// WriteTo or Read on the object. +// UnmarshalBinary decodes a slice of bytes generated by +// MarshalBinary or WriteTo on the object. func (share *PCKSShare) UnmarshalBinary(p []byte) (err error) { return share.OperandQ.UnmarshalBinary(p) } -// Write decodes a slice of bytes generated by MarshalBinary or -// Read on the object and returns the number of bytes read. -func (share *PCKSShare) Write(p []byte) (n int, err error) { - return share.OperandQ.Write(p) +// Decode decodes a slice of bytes generated by Encode +// on the object and returns the number of bytes read. +func (share *PCKSShare) Decode(p []byte) (n int, err error) { + return share.OperandQ.Decode(p) } // ReadFrom reads on the object from an io.Writer. diff --git a/drlwe/keyswitch_sk.go b/drlwe/keyswitch_sk.go index b58bbf7d..bc19be50 100644 --- a/drlwe/keyswitch_sk.go +++ b/drlwe/keyswitch_sk.go @@ -1,6 +1,7 @@ package drlwe import ( + "bytes" "io" "math" @@ -158,22 +159,23 @@ func (ckss *CKSShare) Level() int { return ckss.Value.Level() } -// BinarySize returns the size in bytes that the object once marshalled into a binary form. +// BinarySize returns the size in bytes of the object +// when encoded using Encode. func (ckss *CKSShare) BinarySize() int { return ckss.Value.BinarySize() } // MarshalBinary encodes a CKS share on a slice of bytes. func (ckss *CKSShare) MarshalBinary() (p []byte, err error) { - p = make([]byte, ckss.BinarySize()) - _, err = ckss.Read(p) - return + buf := bytes.NewBuffer([]byte{}) + _, err = ckss.WriteTo(buf) + return buf.Bytes(), nil } -// Read encodes the object into a binary form on a preallocated slice of bytes +// Encode encodes the object into a binary form on a preallocated slice of bytes // and returns the number of bytes written. -func (ckss *CKSShare) Read(p []byte) (ptr int, err error) { - return ckss.Value.Read(p) +func (ckss *CKSShare) Encode(p []byte) (ptr int, err error) { + return ckss.Value.Encode(p) } // WriteTo writes the object on an io.Writer. @@ -187,21 +189,21 @@ func (ckss *CKSShare) WriteTo(w io.Writer) (n int64, err error) { return ckss.Value.WriteTo(w) } -// UnmarshalBinary decodes a slice of bytes generated by MarshalBinary, -// WriteTo or Read on the object. +// UnmarshalBinary decodes a slice of bytes generated by +// MarshalBinary or WriteTo on the object. func (ckss *CKSShare) UnmarshalBinary(p []byte) (err error) { - _, err = ckss.Write(p) + _, err = ckss.ReadFrom(bytes.NewBuffer(p)) return } -// Write decodes a slice of bytes generated by MarshalBinary or -// Read on the object and returns the number of bytes read. -func (ckss *CKSShare) Write(p []byte) (ptr int, err error) { +// Decode decodes a slice of bytes generated by Encode +// on the object and returns the number of bytes read. +func (ckss *CKSShare) Decode(p []byte) (ptr int, err error) { if ckss.Value == nil { ckss.Value = new(ring.Poly) } - return ckss.Value.Write(p) + return ckss.Value.Decode(p) } // ReadFrom reads on the object from an io.Writer. diff --git a/drlwe/refresh.go b/drlwe/refresh.go index d5fc532f..78640861 100644 --- a/drlwe/refresh.go +++ b/drlwe/refresh.go @@ -2,6 +2,7 @@ package drlwe import ( "bufio" + "bytes" "io" "github.com/tuneinsight/lattigo/v4/utils/buffer" @@ -13,26 +14,27 @@ type RefreshShare struct { S2EShare CKSShare } -// BinarySize returns the size in bytes that the object once marshalled into a binary form. +// BinarySize returns the size in bytes of the object +// when encoded using Encode. func (share *RefreshShare) BinarySize() int { return share.E2SShare.BinarySize() + share.S2EShare.BinarySize() } // MarshalBinary encodes the object into a binary form on a newly allocated slice of bytes. func (share *RefreshShare) MarshalBinary() (p []byte, err error) { - p = make([]byte, share.BinarySize()) - _, err = share.Read(p) - return + buf := bytes.NewBuffer([]byte{}) + _, err = share.WriteTo(buf) + return buf.Bytes(), nil } -// Read encodes the object into a binary form on a preallocated slice of bytes +// Encode encodes the object into a binary form on a preallocated slice of bytes // and returns the number of bytes written. -func (share *RefreshShare) Read(p []byte) (n int, err error) { - if n, err = share.E2SShare.Read(p[n:]); err != nil { +func (share *RefreshShare) Encode(p []byte) (n int, err error) { + if n, err = share.E2SShare.Encode(p[n:]); err != nil { return } var inc int - inc, err = share.S2EShare.Read(p[n:]) + inc, err = share.S2EShare.Encode(p[n:]) return n + inc, err } @@ -57,21 +59,21 @@ func (share *RefreshShare) WriteTo(w io.Writer) (n int64, err error) { } } -// UnmarshalBinary decodes a slice of bytes generated by MarshalBinary, -// WriteTo or Read on the object. +// UnmarshalBinary decodes a slice of bytes generated by +// MarshalBinary or WriteTo on the object. func (share *RefreshShare) UnmarshalBinary(p []byte) (err error) { - _, err = share.Write(p) + _, err = share.ReadFrom(bytes.NewBuffer(p)) return } -// Write decodes a slice of bytes generated by MarshalBinary or -// Read on the object and returns the number of bytes read. -func (share *RefreshShare) Write(p []byte) (n int, err error) { - if n, err = share.E2SShare.Write(p[n:]); err != nil { +// Decode decodes a slice of bytes generated by Encode +// on the object and returns the number of bytes read. +func (share *RefreshShare) Decode(p []byte) (n int, err error) { + if n, err = share.E2SShare.Decode(p[n:]); err != nil { return } var inc int - inc, err = share.S2EShare.Write(p[n:]) + inc, err = share.S2EShare.Decode(p[n:]) return n + inc, err } diff --git a/drlwe/threshold.go b/drlwe/threshold.go index aebd714d..e88b5342 100644 --- a/drlwe/threshold.go +++ b/drlwe/threshold.go @@ -174,7 +174,8 @@ func (cmb *Combiner) lagrangeCoeff(thisKey ShamirPublicPoint, thatKey ShamirPubl cmb.ringQP.MulRNSScalar(lagCoeff, that, lagCoeff) } -// BinarySize returns the size in bytes that the object once marshalled into a binary form. +// BinarySize returns the size in bytes of the object +// when encoded using Encode. func (s *ShamirSecretShare) BinarySize() int { return s.Poly.BinarySize() } @@ -184,10 +185,10 @@ func (s *ShamirSecretShare) MarshalBinary() (p []byte, err error) { return s.Poly.MarshalBinary() } -// Read encodes the object into a binary form on a preallocated slice of bytes +// Encode encodes the object into a binary form on a preallocated slice of bytes // and returns the number of bytes written. -func (s *ShamirSecretShare) Read(p []byte) (n int, err error) { - return s.Poly.Read(p) +func (s *ShamirSecretShare) Encode(p []byte) (n int, err error) { + return s.Poly.Encode(p) } // WriteTo writes the object on an io.Writer. @@ -201,16 +202,16 @@ func (s *ShamirSecretShare) WriteTo(w io.Writer) (n int64, err error) { return s.Poly.WriteTo(w) } -// UnmarshalBinary decodes a slice of bytes generated by MarshalBinary, -// WriteTo or Read on the object. +// UnmarshalBinary decodes a slice of bytes generated by +// MarshalBinary or WriteTo on the object. func (s *ShamirSecretShare) UnmarshalBinary(p []byte) (err error) { return s.Poly.UnmarshalBinary(p) } -// Write decodes a slice of bytes generated by MarshalBinary or -// Read on the object and returns the number of bytes read. -func (s *ShamirSecretShare) Write(p []byte) (n int, err error) { - return s.Poly.Write(p) +// Decode decodes a slice of bytes generated by Encode +// on the object and returns the number of bytes read. +func (s *ShamirSecretShare) Decode(p []byte) (n int, err error) { + return s.Poly.Decode(p) } // ReadFrom reads on the object from an io.Writer. diff --git a/examples/main_test.go b/examples/main_test.go deleted file mode 100644 index f67d0593..00000000 --- a/examples/main_test.go +++ /dev/null @@ -1,151 +0,0 @@ -package main_test - -import ( - "bufio" - "fmt" - "testing" - - "github.com/tuneinsight/lattigo/v4/ring" - "github.com/tuneinsight/lattigo/v4/utils/sampling" -) - -func Benchmark(b *testing.B) { - - LogN := 15 - Qi := []uint64{0x1fffffffffe00001, 0x1fffffffffc80001, 0x1fffffffffb40001, 0x1fffffffff500001, - 0x1fffffffff380001, 0x1fffffffff000001, 0x1ffffffffef00001, 0x1ffffffffee80001, - 0x1ffffffffeb40001, 0x1ffffffffe780001, 0x1ffffffffe600001, 0x1ffffffffe4c0001} - - r, err := ring.NewRing(1< len(r.buff[r.n:]) { - return 0, fmt.Errorf("cannot read: len(b)=%d > %d", len(b), len(r.buff[r.n:])) - } - - copy(b, r.buff[r.n:]) - - r.n += len(b) - - return len(b), nil -} - -type Writer struct { - buff []byte - n int -} - -func NewWriter(size int) *Writer { - return &Writer{ - buff: make([]byte, size), - n: 0, - } -} - -func (w *Writer) Write(b []byte) (n int, err error) { - - if len(b) > len(w.buff[w.n:]) { - return 0, fmt.Errorf("cannot write len(b)=%d > %d", len(b), len(w.buff[w.n:])) - } - - copy(w.buff[w.n:], b) - - w.n += len(b) - - return len(b), nil -} diff --git a/ring/poly.go b/ring/poly.go index 895dd3ae..a1c55bb0 100644 --- a/ring/poly.go +++ b/ring/poly.go @@ -2,6 +2,7 @@ package ring import ( "bufio" + "bytes" "encoding/binary" "fmt" "io" @@ -117,26 +118,26 @@ func (pol *Poly) Equal(other *Poly) bool { } // BinarySize returns the size in bytes of the object -// when encoded using MarshalBinary, Read or WriteTo. +// when encoded using Encode. func BinarySize(N, Level int) (size int) { return 16 + N*(Level+1)<<3 } // BinarySize returns the size in bytes of the object -// when encoded using MarshalBinary, Read or WriteTo. +// when encoded using Encode. func (pol *Poly) BinarySize() (size int) { return BinarySize(pol.N(), pol.Level()) } // MarshalBinary encodes the object into a binary form on a newly allocated slice of bytes. func (pol *Poly) MarshalBinary() (p []byte, err error) { - p = make([]byte, pol.BinarySize()) - _, err = pol.Read(p) - return + buf := bytes.NewBuffer([]byte{}) + _, err = pol.WriteTo(buf) + return buf.Bytes(), nil } -// UnmarshalBinary decodes a slice of bytes generated by MarshalBinary, -// WriteTo or Read on the object. +// UnmarshalBinary decodes a slice of bytes generated by +// MarshalBinary or WriteTo on the object. func (pol *Poly) UnmarshalBinary(p []byte) (err error) { N := int(binary.LittleEndian.Uint64(p)) @@ -146,7 +147,7 @@ func (pol *Poly) UnmarshalBinary(p []byte) (err error) { return fmt.Errorf("cannot UnmarshalBinary: len(p)=%d != %d", len(p), size) } - if _, err = pol.Write(p); err != nil { + if _, err = pol.ReadFrom(bytes.NewBuffer(p)); err != nil { return } @@ -163,7 +164,7 @@ func (pol *Poly) UnmarshalBinary(p []byte) (err error) { func (pol *Poly) WriteTo(w io.Writer) (int64, error) { switch w := w.(type) { - case buffer.Writer: + case *bufio.Writer: var err error @@ -200,7 +201,7 @@ func (pol *Poly) WriteTo(w io.Writer) (int64, error) { func (pol *Poly) ReadFrom(r io.Reader) (int64, error) { switch r := r.(type) { - case buffer.Reader: + case *bufio.Reader: var err error var n, inc int @@ -253,15 +254,15 @@ func (pol *Poly) ReadFrom(r io.Reader) (int64, error) { } } -// Read encodes the object into a binary form on a preallocated slice of bytes +// Encode encodes the object into a binary form on a preallocated slice of bytes // and returns the number of bytes written. -func (pol *Poly) Read(p []byte) (n int, err error) { +func (pol *Poly) Encode(p []byte) (n int, err error) { N := pol.N() Level := pol.Level() if len(p) < pol.BinarySize() { - return n, fmt.Errorf("cannot Read: len(p)=%d < %d", len(p), pol.BinarySize()) + return n, fmt.Errorf("cannot Encode: len(p)=%d < %d", len(p), pol.BinarySize()) } binary.LittleEndian.PutUint64(p[n:], uint64(N)) @@ -282,9 +283,9 @@ func (pol *Poly) Read(p []byte) (n int, err error) { return } -// Write decodes a slice of bytes generated by MarshalBinary, WriteTo or -// Read on the object and returns the number of bytes read. -func (pol *Poly) Write(p []byte) (n int, err error) { +// Decode decodes a slice of bytes generated by Encode +// on the object and returns the number of bytes read. +func (pol *Poly) Decode(p []byte) (n int, err error) { N := int(binary.LittleEndian.Uint64(p[n:])) n += 8 @@ -292,7 +293,7 @@ func (pol *Poly) Write(p []byte) (n int, err error) { n += 8 if size := BinarySize(N, Level); len(p) < size { - return n, fmt.Errorf("cannot Read: len(p)=%d < ", size) + return n, fmt.Errorf("cannot Decode: len(p)=%d < ", size) } if pol.Buff == nil || len(pol.Buff) != N*(Level+1) { diff --git a/rlwe/evaluationkeyset.go b/rlwe/evaluationkeyset.go index 3d750889..e924c5d7 100644 --- a/rlwe/evaluationkeyset.go +++ b/rlwe/evaluationkeyset.go @@ -2,6 +2,7 @@ package rlwe import ( "bufio" + "bytes" "fmt" "io" @@ -79,61 +80,27 @@ func (evk *EvaluationKeySet) GetRelinearizationKey() (rk *RelinearizationKey, er return nil, fmt.Errorf("RelinearizationKey is nil") } -func (evk *EvaluationKeySet) BinarySize() (size int) { - - size++ - if evk.RelinearizationKey != nil { - size += evk.RelinearizationKey.BinarySize() - } - - size++ - if evk.GaloisKeys != nil { - size += evk.GaloisKeys.BinarySize() - } - - return -} - +// MarshalBinary encodes the object into a binary form on a newly allocated slice of bytes. func (evk *EvaluationKeySet) MarshalBinary() (p []byte, err error) { - p = make([]byte, evk.BinarySize()) - _, err = evk.Read(p) - return -} - -func (evk *EvaluationKeySet) Read(p []byte) (n int, err error) { - var inc int - if evk.RelinearizationKey != nil { - p[n] = 1 - n++ - - if inc, err = evk.RelinearizationKey.Read(p[n:]); err != nil { - return n + inc, err - } - - n += inc - - } else { - n++ - } - - if evk.GaloisKeys != nil { - p[n] = 1 - n++ - - if inc, err = evk.GaloisKeys.Read(p[n:]); err != nil { - - return n + inc, err - } - - n += inc - - } else { - n++ - } - + buf := bytes.NewBuffer([]byte{}) + _, err = evk.WriteTo(buf) + return buf.Bytes(), nil +} + +// UnmarshalBinary decodes a slice of bytes generated by +// MarshalBinary or WriteTo on the object. +func (evk *EvaluationKeySet) UnmarshalBinary(p []byte) (err error) { + _, err = evk.ReadFrom(bytes.NewBuffer(p)) return } +// WriteTo writes the object on an io.Writer. +// To ensure optimal efficiency and minimal allocations, the user is encouraged +// to provide a struct implementing the interface buffer.Writer, which defines +// a subset of the method of the bufio.Writer. +// If w is not compliant to the buffer.Writer interface, it will be wrapped in +// a new bufio.Writer. +// For additional information, see lattigo/utils/buffer/writer.go. func (evk *EvaluationKeySet) WriteTo(w io.Writer) (int64, error) { switch w := w.(type) { case buffer.Writer: @@ -189,50 +156,13 @@ func (evk *EvaluationKeySet) WriteTo(w io.Writer) (int64, error) { } } -func (evk *EvaluationKeySet) UnmarshalBinary(p []byte) (err error) { - _, err = evk.Write(p) - return -} - -func (evk *EvaluationKeySet) Write(p []byte) (n int, err error) { - var inc int - if p[n] == 1 { - n++ - - if evk.RelinearizationKey == nil { - evk.RelinearizationKey = new(RelinearizationKey) - } - - if inc, err = evk.RelinearizationKey.Write(p[n:]); err != nil { - return n + inc, err - } - - n += inc - - } else { - n++ - } - - if p[n] == 1 { - n++ - - if evk.GaloisKeys == nil { - evk.GaloisKeys = structs.Map[uint64, GaloisKey]{} - } - - if inc, err = evk.GaloisKeys.Write(p[n:]); err != nil { - return n + inc, err - } - - n += inc - - } else { - n++ - } - - return -} - +// ReadFrom reads on the object from an io.Writer. +// To ensure optimal efficiency and minimal allocations, the user is encouraged +// to provide a struct implementing the interface buffer.Reader, which defines +// a subset of the method of the bufio.Reader. +// If r is not compliant to the buffer.Reader interface, it will be wrapped in +// a new bufio.Reader. +// For additional information, see lattigo/utils/buffer/reader.go. func (evk *EvaluationKeySet) ReadFrom(r io.Reader) (n int64, err error) { switch r := r.(type) { case buffer.Reader: @@ -286,3 +216,95 @@ func (evk *EvaluationKeySet) ReadFrom(r io.Reader) (n int64, err error) { return evk.ReadFrom(bufio.NewReader(r)) } } + +func (evk *EvaluationKeySet) BinarySize() (size int) { + + size++ + if evk.RelinearizationKey != nil { + size += evk.RelinearizationKey.BinarySize() + } + + size++ + if evk.GaloisKeys != nil { + size += evk.GaloisKeys.BinarySize() + } + + return +} + +// Encode encodes the object into a binary form on a preallocated slice of bytes +// and returns the number of bytes written. +func (evk *EvaluationKeySet) Encode(p []byte) (n int, err error) { + var inc int + if evk.RelinearizationKey != nil { + p[n] = 1 + n++ + + if inc, err = evk.RelinearizationKey.Encode(p[n:]); err != nil { + return n + inc, err + } + + n += inc + + } else { + n++ + } + + if evk.GaloisKeys != nil { + p[n] = 1 + n++ + + if inc, err = evk.GaloisKeys.Encode(p[n:]); err != nil { + + return n + inc, err + } + + n += inc + + } else { + n++ + } + + return +} + +// Decode decodes a slice of bytes generated by Encode +// on the object and returns the number of bytes read. +func (evk *EvaluationKeySet) Decode(p []byte) (n int, err error) { + var inc int + if p[n] == 1 { + n++ + + if evk.RelinearizationKey == nil { + evk.RelinearizationKey = new(RelinearizationKey) + } + + if inc, err = evk.RelinearizationKey.Decode(p[n:]); err != nil { + return n + inc, err + } + + n += inc + + } else { + n++ + } + + if p[n] == 1 { + n++ + + if evk.GaloisKeys == nil { + evk.GaloisKeys = structs.Map[uint64, GaloisKey]{} + } + + if inc, err = evk.GaloisKeys.Decode(p[n:]); err != nil { + return n + inc, err + } + + n += inc + + } else { + n++ + } + + return +} diff --git a/rlwe/gadgetciphertext.go b/rlwe/gadgetciphertext.go index abbd006d..e02bdb53 100644 --- a/rlwe/gadgetciphertext.go +++ b/rlwe/gadgetciphertext.go @@ -1,6 +1,7 @@ package rlwe import ( + "bytes" "io" "github.com/google/go-cmp/cmp" @@ -65,15 +66,17 @@ func (ct *GadgetCiphertext) CopyNew() (ctCopy *GadgetCiphertext) { return &GadgetCiphertext{Value: v} } -// BinarySize returns the size in bytes that the object once marshalled into a binary form. -func (ct *GadgetCiphertext) BinarySize() (dataLen int) { - return ct.Value.BinarySize() -} - // MarshalBinary encodes the object into a binary form on a newly allocated slice of bytes. func (ct *GadgetCiphertext) MarshalBinary() (data []byte, err error) { - data = make([]byte, ct.BinarySize()) - _, err = ct.Value.Read(data) + buf := bytes.NewBuffer([]byte{}) + _, err = ct.WriteTo(buf) + return buf.Bytes(), nil +} + +// UnmarshalBinary decodes a slice of bytes generated by +// MarshalBinary or WriteTo on the object. +func (ct *GadgetCiphertext) UnmarshalBinary(p []byte) (err error) { + _, err = ct.ReadFrom(bytes.NewBuffer(p)) return } @@ -88,12 +91,6 @@ func (ct *GadgetCiphertext) WriteTo(w io.Writer) (n int64, err error) { return ct.Value.WriteTo(w) } -// Read encodes the object into a binary form on a preallocated slice of bytes -// and returns the number of bytes written. -func (ct *GadgetCiphertext) Read(p []byte) (n int, err error) { - return ct.Value.Read(p) -} - // ReadFrom reads on the object from an io.Writer. // To ensure optimal efficiency and minimal allocations, the user is encouraged // to provide a struct implementing the interface buffer.Reader, which defines @@ -105,17 +102,22 @@ func (ct *GadgetCiphertext) ReadFrom(r io.Reader) (n int64, err error) { return ct.Value.ReadFrom(r) } -// UnmarshalBinary decodes a slice of bytes generated by MarshalBinary, -// WriteTo or Read on the object. -func (ct *GadgetCiphertext) UnmarshalBinary(p []byte) (err error) { - _, err = ct.Value.Write(p) - return +// BinarySize returns the size in bytes of the object +// when encoded using Encode. +func (ct *GadgetCiphertext) BinarySize() (dataLen int) { + return ct.Value.BinarySize() } -// Write decodes a slice of bytes generated by MarshalBinary or -// Read on the object and returns the number of bytes read. -func (ct *GadgetCiphertext) Write(p []byte) (n int, err error) { - return ct.Value.Write(p) +// Encode encodes the object into a binary form on a preallocated slice of bytes +// and returns the number of bytes written. +func (ct *GadgetCiphertext) Encode(p []byte) (n int, err error) { + return ct.Value.Encode(p) +} + +// Decode decodes a slice of bytes generated by Encode +// on the object and returns the number of bytes read. +func (ct *GadgetCiphertext) Decode(p []byte) (n int, err error) { + return ct.Value.Decode(p) } // AddPolyTimesGadgetVectorToGadgetCiphertext takes a plaintext polynomial and a list of Ciphertexts and adds the diff --git a/rlwe/galoiskey.go b/rlwe/galoiskey.go index f17a2f3b..009c9497 100644 --- a/rlwe/galoiskey.go +++ b/rlwe/galoiskey.go @@ -2,6 +2,7 @@ package rlwe import ( "bufio" + "bytes" "encoding/binary" "fmt" "io" @@ -46,40 +47,11 @@ func (gk *GaloisKey) CopyNew() *GaloisKey { } } -// BinarySize returns the size in bytes that the object once marshalled into a binary form. -func (gk *GaloisKey) BinarySize() (size int) { - return gk.EvaluationKey.BinarySize() + 16 -} - // MarshalBinary encodes the object into a binary form on a newly allocated slice of bytes. func (gk *GaloisKey) MarshalBinary() (p []byte, err error) { - p = make([]byte, gk.BinarySize()) - _, err = gk.Read(p) - return -} - -// Read encodes the object into a binary form on a preallocated slice of bytes -// and returns the number of bytes written. -func (gk *GaloisKey) Read(p []byte) (n int, err error) { - - if len(p) < 16 { - return n, fmt.Errorf("cannot read: len(p) < 16") - } - - binary.LittleEndian.PutUint64(p[n:], gk.GaloisElement) - n += 8 - - binary.LittleEndian.PutUint64(p[n:], gk.NthRoot) - n += 8 - - var inc int - if inc, err = gk.EvaluationKey.Read(p[n:]); err != nil { - return - } - - n += inc - - return + buf := bytes.NewBuffer([]byte{}) + _, err = gk.WriteTo(buf) + return buf.Bytes(), nil } // WriteTo writes the object on an io.Writer. @@ -121,10 +93,10 @@ func (gk *GaloisKey) WriteTo(w io.Writer) (n int64, err error) { } } -// UnmarshalBinary decodes a slice of bytes generated by MarshalBinary, -// WriteTo or Read on the object. +// UnmarshalBinary decodes a slice of bytes generated by +// MarshalBinary or WriteTo on the object. func (gk *GaloisKey) UnmarshalBinary(p []byte) (err error) { - _, err = gk.Write(p) + _, err = gk.ReadFrom(bytes.NewBuffer(p)) return } @@ -166,12 +138,42 @@ func (gk *GaloisKey) ReadFrom(r io.Reader) (n int64, err error) { } } -// Write decodes a slice of bytes generated by MarshalBinary or -// Read on the object and returns the number of bytes read. -func (gk *GaloisKey) Write(p []byte) (n int, err error) { +// BinarySize returns the size in bytes of the object +// when encoded using Encode. +func (gk *GaloisKey) BinarySize() (size int) { + return gk.EvaluationKey.BinarySize() + 16 +} + +// Encode encodes the object into a binary form on a preallocated slice of bytes +// and returns the number of bytes written. +func (gk *GaloisKey) Encode(p []byte) (n int, err error) { if len(p) < 16 { - return n, fmt.Errorf("cannot read: len(p) < 16") + return n, fmt.Errorf("cannot Encode: len(p) < 16") + } + + binary.LittleEndian.PutUint64(p[n:], gk.GaloisElement) + n += 8 + + binary.LittleEndian.PutUint64(p[n:], gk.NthRoot) + n += 8 + + var inc int + if inc, err = gk.EvaluationKey.Encode(p[n:]); err != nil { + return + } + + n += inc + + return +} + +// Decode decodes a slice of bytes generated by Encode +// on the object and returns the number of bytes read. +func (gk *GaloisKey) Decode(p []byte) (n int, err error) { + + if len(p) < 16 { + return n, fmt.Errorf("cannot Decode: len(p) < 16") } gk.GaloisElement = binary.LittleEndian.Uint64(p[n:]) @@ -181,7 +183,7 @@ func (gk *GaloisKey) Write(p []byte) (n int, err error) { n += 8 var inc int - if inc, err = gk.EvaluationKey.Write(p[n:]); err != nil { + if inc, err = gk.EvaluationKey.Decode(p[n:]); err != nil { return } diff --git a/rlwe/metadata.go b/rlwe/metadata.go index 9529a102..a0a6b75c 100644 --- a/rlwe/metadata.go +++ b/rlwe/metadata.go @@ -25,25 +25,25 @@ func (m *MetaData) BinarySize() int { } // MarshalBinary encodes the object into a binary form on a newly allocated slice of bytes. -func (m *MetaData) MarshalBinary() (data []byte, err error) { - data = make([]byte, m.BinarySize()) - _, err = m.Read(data) +func (m *MetaData) MarshalBinary() (p []byte, err error) { + p = make([]byte, m.BinarySize()) + _, err = m.Encode(p) return } -// UnmarshalBinary decodes a slice of bytes generated by MarshalBinary, -// WriteTo or Read on the object. -func (m *MetaData) UnmarshalBinary(data []byte) (err error) { - _, err = m.Write(data) +// UnmarshalBinary decodes a slice of bytes generated by +// MarshalBinary or WriteTo on the object. +func (m *MetaData) UnmarshalBinary(p []byte) (err error) { + _, err = m.Decode(p) return } // WriteTo writes the object on an io.Writer. func (m *MetaData) WriteTo(w io.Writer) (int64, error) { - if data, err := m.MarshalBinary(); err != nil { + if p, err := m.MarshalBinary(); err != nil { return 0, err } else { - if n, err := w.Write(data); err != nil { + if n, err := w.Write(p); err != nil { return int64(n), err } else { return int64(n), nil @@ -52,58 +52,58 @@ func (m *MetaData) WriteTo(w io.Writer) (int64, error) { } func (m *MetaData) ReadFrom(r io.Reader) (int64, error) { - data := make([]byte, m.BinarySize()) - if n, err := r.Read(data); err != nil { - return int64(n), err + p := make([]byte, m.BinarySize()) + if n, err := r.Read(p); err != nil { + return int64(n), nil } else { - return int64(n), m.UnmarshalBinary(data) + return int64(n), m.UnmarshalBinary(p) } } -// Read encodes the object into a binary form on a preallocated slice of bytes +// Encode encodes the object into a binary form on a preallocated slice of bytes // and returns the number of bytes written. -func (m *MetaData) Read(data []byte) (ptr int, err error) { +func (m *MetaData) Encode(p []byte) (n int, err error) { - if len(data) < m.BinarySize() { - return 0, fmt.Errorf("cannot write: len(data) is too small") + if len(p) < m.BinarySize() { + return 0, fmt.Errorf("cannot Encode: len(p) is too small") } - if ptr, err = m.Scale.Read(data[ptr:]); err != nil { + if n, err = m.Scale.Encode(p[n:]); err != nil { return 0, err } if m.IsNTT { - data[ptr] = 1 + p[n] = 1 } - ptr++ + n++ if m.IsMontgomery { - data[ptr] = 1 + p[n] = 1 } - ptr++ + n++ return } -// Write decodes a slice of bytes generated by MarshalBinary or -// Read on the object and returns the number of bytes read. -func (m *MetaData) Write(data []byte) (ptr int, err error) { +// Decode decodes a slice of bytes generated by Encode +// on the object and returns the number of bytes read. +func (m *MetaData) Decode(p []byte) (n int, err error) { - if len(data) < m.BinarySize() { - return 0, fmt.Errorf("canoot read: len(data) is too small") + if len(p) < m.BinarySize() { + return 0, fmt.Errorf("canoot Decode: len(p) is too small") } - if ptr, err = m.Scale.Write(data[ptr:]); err != nil { + if n, err = m.Scale.Decode(p[n:]); err != nil { return } - m.IsNTT = data[ptr] == 1 - ptr++ + m.IsNTT = p[n] == 1 + n++ - m.IsMontgomery = data[ptr] == 1 - ptr++ + m.IsMontgomery = p[n] == 1 + n++ return } diff --git a/rlwe/operand.go b/rlwe/operand.go index bb9e50f1..1a31b122 100644 --- a/rlwe/operand.go +++ b/rlwe/operand.go @@ -1,6 +1,7 @@ package rlwe import ( + "bytes" "fmt" "io" @@ -224,15 +225,17 @@ func SwitchCiphertextRingDegree(ctIn, ctOut *OperandQ) { ctOut.MetaData = ctIn.MetaData } -// BinarySize returns the size in bytes that the object once marshalled into a binary form. -func (op *OperandQ) BinarySize() int { - return op.MetaData.BinarySize() + op.Value.BinarySize() -} - // MarshalBinary encodes the object into a binary form on a newly allocated slice of bytes. func (op *OperandQ) MarshalBinary() (data []byte, err error) { - data = make([]byte, op.BinarySize()) - _, err = op.Read(data) + buf := bytes.NewBuffer([]byte{}) + _, err = op.WriteTo(buf) + return buf.Bytes(), nil +} + +// UnmarshalBinary decodes a slice of bytes generated by MarshalBinary +// or Read on the objeop. +func (op *OperandQ) UnmarshalBinary(p []byte) (err error) { + _, err = op.ReadFrom(bytes.NewBuffer(p)) return } @@ -276,39 +279,38 @@ func (op *OperandQ) ReadFrom(r io.Reader) (n int64, err error) { return n + inc, err } -// Read encodes the object into a binary form on a preallocated slice of bytes +// BinarySize returns the size in bytes of the object +// when encoded using Encode. +func (op *OperandQ) BinarySize() int { + return op.MetaData.BinarySize() + op.Value.BinarySize() +} + +// Encode encodes the object into a binary form on a preallocated slice of bytes // and returns the number of bytes written. -func (op *OperandQ) Read(p []byte) (n int, err error) { +func (op *OperandQ) Encode(p []byte) (n int, err error) { if len(p) < op.BinarySize() { - return 0, fmt.Errorf("cannote write: len(p) is too small") + return 0, fmt.Errorf("cannot Encode: len(p) is too small") } - if n, err = op.MetaData.Read(p); err != nil { + if n, err = op.MetaData.Encode(p); err != nil { return } - inc, err := op.Value.Read(p[n:]) + inc, err := op.Value.Encode(p[n:]) return n + inc, err } -// UnmarshalBinary decodes a slice of bytes generated by MarshalBinary -// or Read on the objeop. -func (op *OperandQ) UnmarshalBinary(p []byte) (err error) { - _, err = op.Write(p) - return -} +// Decode decodes a slice of bytes generated by Encode +// on the object and returns the number of bytes read. +func (op *OperandQ) Decode(p []byte) (n int, err error) { -// Write decodes a slice of bytes generated by MarshalBinary or -// Read on the object and returns the number of bytes read. -func (op *OperandQ) Write(p []byte) (n int, err error) { - - if n, err = op.MetaData.Write(p); err != nil { + if n, err = op.MetaData.Decode(p); err != nil { return } - inc, err := op.Value.Write(p[n:]) + inc, err := op.Value.Decode(p[n:]) return n + inc, err } @@ -371,15 +373,17 @@ func (op *OperandQP) CopyNew() *OperandQP { return &OperandQP{Value: Value, MetaData: op.MetaData} } -// BinarySize returns the size in bytes that the object once marshalled into a binary form. -func (op *OperandQP) BinarySize() int { - return op.MetaData.BinarySize() + op.Value.BinarySize() -} - // MarshalBinary encodes the object into a binary form on a newly allocated slice of bytes. func (op *OperandQP) MarshalBinary() (data []byte, err error) { - data = make([]byte, op.BinarySize()) - _, err = op.Read(data) + buf := bytes.NewBuffer([]byte{}) + _, err = op.WriteTo(buf) + return buf.Bytes(), nil +} + +// UnmarshalBinary decodes a slice of bytes generated by MarshalBinary +// or Read on the objeop. +func (op *OperandQP) UnmarshalBinary(p []byte) (err error) { + _, err = op.ReadFrom(bytes.NewBuffer(p)) return } @@ -423,39 +427,38 @@ func (op *OperandQP) ReadFrom(r io.Reader) (n int64, err error) { return n + inc, err } -// Read encodes the object into a binary form on a preallocated slice of bytes +// BinarySize returns the size in bytes of the object +// when encoded using Encode. +func (op *OperandQP) BinarySize() int { + return op.MetaData.BinarySize() + op.Value.BinarySize() +} + +// Encode encodes the object into a binary form on a preallocated slice of bytes // and returns the number of bytes written. -func (op *OperandQP) Read(p []byte) (n int, err error) { +func (op *OperandQP) Encode(p []byte) (n int, err error) { if len(p) < op.BinarySize() { - return 0, fmt.Errorf("cannote write: len(p) is too small") + return 0, fmt.Errorf("cannote Encode: len(p) is too small") } - if n, err = op.MetaData.Read(p); err != nil { + if n, err = op.MetaData.Encode(p); err != nil { return } - inc, err := op.Value.Read(p[n:]) + inc, err := op.Value.Encode(p[n:]) return n + inc, err } -// UnmarshalBinary decodes a slice of bytes generated by MarshalBinary -// or Read on the objeop. -func (op *OperandQP) UnmarshalBinary(p []byte) (err error) { - _, err = op.Write(p) - return -} +// Decode decodes a slice of bytes generated by Encode +// on the object and returns the number of bytes read. +func (op *OperandQP) Decode(p []byte) (n int, err error) { -// Write decodes a slice of bytes generated by MarshalBinary or -// Read on the object and returns the number of bytes read. -func (op *OperandQP) Write(p []byte) (n int, err error) { - - if n, err = op.MetaData.Write(p); err != nil { + if n, err = op.MetaData.Decode(p); err != nil { return } - inc, err := op.Value.Write(p[n:]) + inc, err := op.Value.Decode(p[n:]) return n + inc, err } diff --git a/rlwe/plaintext.go b/rlwe/plaintext.go index c11ddffc..4d424c8e 100644 --- a/rlwe/plaintext.go +++ b/rlwe/plaintext.go @@ -57,10 +57,10 @@ func (pt *Plaintext) UnmarshalBinary(p []byte) (err error) { return } -// Write decodes a slice of bytes generated by MarshalBinary or -// Read on the object and returns the number of bytes read. -func (pt *Plaintext) Write(p []byte) (n int, err error) { - if n, err = pt.OperandQ.Write(p); err != nil { +// Decode decodes a slice of bytes generated by Encode +// on the object and returns the number of bytes read. +func (pt *Plaintext) Decode(p []byte) (n int, err error) { + if n, err = pt.OperandQ.Decode(p); err != nil { return } pt.Value = pt.OperandQ.Value[0] diff --git a/rlwe/power_basis.go b/rlwe/power_basis.go index 94571525..18efd254 100644 --- a/rlwe/power_basis.go +++ b/rlwe/power_basis.go @@ -2,6 +2,7 @@ package rlwe import ( "bufio" + "bytes" "fmt" "io" @@ -27,16 +28,17 @@ func NewPowerBasis(ct *Ciphertext, basis polynomial.Basis) (p *PowerBasis) { return } -// BinarySize returns the size in bytes of the object -// when encoded using MarshalBinary, Read or WriteTo. -func (p *PowerBasis) BinarySize() (size int) { - return 1 + p.Value.BinarySize() -} - // MarshalBinary encodes the object into a binary form on a newly allocated slice of bytes. func (p *PowerBasis) MarshalBinary() (data []byte, err error) { - data = make([]byte, p.BinarySize()) - _, err = p.Read(data) + buf := bytes.NewBuffer([]byte{}) + _, err = p.WriteTo(buf) + return buf.Bytes(), nil +} + +// UnmarshalBinary decodes a slice of bytes generated by +// MarshalBinary or WriteTo on the object. +func (p *PowerBasis) UnmarshalBinary(data []byte) (err error) { + _, err = p.ReadFrom(bytes.NewBuffer(data)) return } @@ -69,29 +71,6 @@ func (p *PowerBasis) WriteTo(w io.Writer) (n int64, err error) { } } -// Read encodes the object into a binary form on a preallocated slice of bytes -// and returns the number of bytes written. -func (p *PowerBasis) Read(data []byte) (n int, err error) { - - if len(data) < p.BinarySize() { - return n, fmt.Errorf("cannot Read: len(data)=%d < %d", len(data), p.BinarySize()) - } - - data[n] = uint8(p.Basis) - n++ - - inc, err := p.Value.Read(data[n:]) - - return n + inc, err -} - -// UnmarshalBinary decodes a slice of bytes generated by MarshalBinary, -// WriteTo or Read on the object. -func (p *PowerBasis) UnmarshalBinary(data []byte) (err error) { - _, err = p.Write(data) - return -} - // ReadFrom reads on the object from an io.Writer. // To ensure optimal efficiency and minimal allocations, the user is encouraged // to provide a struct implementing the interface buffer.Reader, which defines @@ -127,9 +106,31 @@ func (p *PowerBasis) ReadFrom(r io.Reader) (n int64, err error) { } } -// Write decodes a slice of bytes generated by MarshalBinary, WriteTo or -// Read on the object and returns the number of bytes read. -func (p *PowerBasis) Write(data []byte) (n int, err error) { +// BinarySize returns the size in bytes of the object +// when encoded using Encode. +func (p *PowerBasis) BinarySize() (size int) { + return 1 + p.Value.BinarySize() +} + +// Encode encodes the object into a binary form on a preallocated slice of bytes +// and returns the number of bytes written. +func (p *PowerBasis) Encode(data []byte) (n int, err error) { + + if len(data) < p.BinarySize() { + return n, fmt.Errorf("cannot Encode: len(data)=%d < %d", len(data), p.BinarySize()) + } + + data[n] = uint8(p.Basis) + n++ + + inc, err := p.Value.Encode(data[n:]) + + return n + inc, err +} + +// Decode decodes a slice of bytes generated by Encode +// on the object and returns the number of bytes read. +func (p *PowerBasis) Decode(data []byte) (n int, err error) { p.Basis = polynomial.Basis(data[n]) n++ @@ -138,7 +139,7 @@ func (p *PowerBasis) Write(data []byte) (n int, err error) { p.Value = map[int]*Ciphertext{} } - inc, err := p.Value.Write(data[n:]) + inc, err := p.Value.Decode(data[n:]) return n + inc, err } diff --git a/rlwe/ringqp/poly.go b/rlwe/ringqp/poly.go index 16189355..dc3abf5a 100644 --- a/rlwe/ringqp/poly.go +++ b/rlwe/ringqp/poly.go @@ -2,6 +2,7 @@ package ringqp import ( "bufio" + "bytes" "io" "github.com/google/go-cmp/cmp" @@ -115,7 +116,8 @@ func (p *Poly) Resize(levelQ, levelP int) { } } -// BinarySize returns the size in bytes that the object once marshalled into a binary form. +// BinarySize returns the size in bytes of the object +// when encoded using Encode. // Assumes that each coefficient takes 8 bytes. func (p *Poly) BinarySize() (dataLen int) { @@ -263,9 +265,9 @@ func (p *Poly) ReadFrom(r io.Reader) (n int64, err error) { } } -// Read encodes the object into a binary form on a preallocated slice of bytes +// Encode encodes the object into a binary form on a preallocated slice of bytes // and returns the number of bytes written. -func (p *Poly) Read(data []byte) (n int, err error) { +func (p *Poly) Encode(data []byte) (n int, err error) { var inc int if p.Q != nil { @@ -279,14 +281,14 @@ func (p *Poly) Read(data []byte) (n int, err error) { n = 2 if data[0] == 1 { - if inc, err = p.Q.Read(data[n:]); err != nil { + if inc, err = p.Q.Encode(data[n:]); err != nil { return } n += inc } if data[1] == 1 { - if inc, err = p.P.Read(data[n:]); err != nil { + if inc, err = p.P.Encode(data[n:]); err != nil { return } n += inc @@ -295,9 +297,9 @@ func (p *Poly) Read(data []byte) (n int, err error) { return } -// Write decodes a slice of bytes generated by MarshalBinary or -// Read on the object and returns the number of bytes read. -func (p *Poly) Write(data []byte) (n int, err error) { +// Decode decodes a slice of bytes generated by Encode +// on the object and returns the number of bytes read. +func (p *Poly) Decode(data []byte) (n int, err error) { var inc int n = 2 @@ -308,7 +310,7 @@ func (p *Poly) Write(data []byte) (n int, err error) { p.Q = new(ring.Poly) } - if inc, err = p.Q.Write(data[n:]); err != nil { + if inc, err = p.Q.Decode(data[n:]); err != nil { return } n += inc @@ -320,7 +322,7 @@ func (p *Poly) Write(data []byte) (n int, err error) { p.P = new(ring.Poly) } - if inc, err = p.P.Write(data[n:]); err != nil { + if inc, err = p.P.Decode(data[n:]); err != nil { return } n += inc @@ -331,14 +333,14 @@ func (p *Poly) Write(data []byte) (n int, err error) { // MarshalBinary encodes the object into a binary form on a newly allocated slice of bytes. func (p *Poly) MarshalBinary() (data []byte, err error) { - data = make([]byte, p.BinarySize()) - _, err = p.Read(data) - return + buf := bytes.NewBuffer([]byte{}) + _, err = p.WriteTo(buf) + return buf.Bytes(), nil } -// UnmarshalBinary decodes a slice of bytes generated by MarshalBinary, -// WriteTo or Read on the object. +// UnmarshalBinary decodes a slice of bytes generated by +// MarshalBinary or WriteTo on the object. func (p *Poly) UnmarshalBinary(data []byte) (err error) { - _, err = p.Write(data) + _, err = p.ReadFrom(bytes.NewBuffer(data)) return err } diff --git a/rlwe/scale.go b/rlwe/scale.go index 5f8dc1dc..d5dee4d8 100644 --- a/rlwe/scale.go +++ b/rlwe/scale.go @@ -134,20 +134,22 @@ func (s Scale) Min(s1 Scale) (max Scale) { return s } -// BinarySize returns the size in bytes that the object once marshalled into a binary form. -func (s Scale) BinarySize() int { - return 48 +// MarshalBinary encodes the object into a binary form on a newly allocated slice of bytes. +func (s Scale) MarshalBinary() (p []byte, err error) { + p = make([]byte, s.BinarySize()) + _, err = s.Encode(p) + return } -// MarshalBinary encodes the object into a binary form on a newly allocated slice of bytes. -func (s Scale) MarshalBinary() (data []byte, err error) { - data = make([]byte, s.BinarySize()) - _, err = s.Read(data) +// UnmarshalBinary decodes a slice of bytes generated by +// MarshalBinary or WriteTo on the object. +func (s Scale) UnmarshalBinary(p []byte) (err error) { + _, err = s.Decode(p) return } // MarshalJSON encodes the object into a binary form on a newly allocated slice of bytes. -func (s Scale) MarshalJSON() (data []byte, err error) { +func (s Scale) MarshalJSON() (p []byte, err error) { aux := &struct { Value *big.Float Mod *big.Int @@ -158,39 +160,7 @@ func (s Scale) MarshalJSON() (data []byte, err error) { return json.Marshal(aux) } -// Read encodes the object into a binary form on a preallocated slice of bytes -// and returns the number of bytes written. -func (s Scale) Read(data []byte) (ptr int, err error) { - var sBytes []byte - if sBytes, err = s.Value.MarshalText(); err != nil { - return - } - - b := make([]byte, s.BinarySize()) - - if len(data) < len(b) { - return 0, fmt.Errorf("cannot write: len(data) < %d", len(b)) - } - - b[0] = uint8(len(sBytes)) - copy(b[1:], sBytes) - copy(data, b) - - if s.Mod != nil { - binary.LittleEndian.PutUint64(data[40:], s.Mod.Uint64()) - } - - return s.BinarySize(), nil -} - -// UnmarshalBinary decodes a slice of bytes generated by MarshalBinary, -// WriteTo or Read on the object. -func (s Scale) UnmarshalBinary(data []byte) (err error) { - _, err = s.Write(data) - return -} - -func (s *Scale) UnmarshalJSON(data []byte) (err error) { +func (s *Scale) UnmarshalJSON(p []byte) (err error) { aux := &struct { Value *big.Float @@ -200,7 +170,7 @@ func (s *Scale) UnmarshalJSON(data []byte) (err error) { Mod: s.Mod, } - if err = json.Unmarshal(data, aux); err != nil { + if err = json.Unmarshal(p, aux); err != nil { return } @@ -210,27 +180,58 @@ func (s *Scale) UnmarshalJSON(data []byte) (err error) { return } -// Write decodes a slice of bytes generated by MarshalBinary or -// Read on the object and returns the number of bytes read. -func (s *Scale) Write(data []byte) (ptr int, err error) { +// BinarySize returns the size in bytes of the object +// when encoded using Encode. +func (s Scale) BinarySize() int { + return 48 +} - if dLen := s.BinarySize(); len(data) < dLen { - return 0, fmt.Errorf("cannot read: len(data) < %d", dLen) +// Encode encodes the object into a binary form on a preallocated slice of bytes +// and returns the number of bytes written. +func (s Scale) Encode(p []byte) (ptr int, err error) { + var sBytes []byte + if sBytes, err = s.Value.MarshalText(); err != nil { + return } - bLen := data[0] + b := make([]byte, s.BinarySize()) + + if len(p) < len(b) { + return 0, fmt.Errorf("cannot Encode: len(p) < %d", len(b)) + } + + b[0] = uint8(len(sBytes)) + copy(b[1:], sBytes) + copy(p, b) + + if s.Mod != nil { + binary.LittleEndian.PutUint64(p[40:], s.Mod.Uint64()) + } + + return s.BinarySize(), nil +} + +// Decode decodes a slice of bytes generated by Encode +// on the object and returns the number of bytes read. +func (s *Scale) Decode(p []byte) (ptr int, err error) { + + if dLen := s.BinarySize(); len(p) < dLen { + return 0, fmt.Errorf("cannot Decode: len(p) < %d", dLen) + } + + bLen := p[0] v := new(big.Float) - if data[1] != 0x30 || bLen > 1 { // 0x30 indicates an empty big.Float - if err = v.UnmarshalText(data[1 : bLen+1]); err != nil { + if p[1] != 0x30 || bLen > 1 { // 0x30 indicates an empty big.Float + if err = v.UnmarshalText(p[1 : bLen+1]); err != nil { return 0, err } v.SetPrec(ScalePrecision) } - mod := binary.LittleEndian.Uint64(data[40:]) + mod := binary.LittleEndian.Uint64(p[40:]) s.Value = *v diff --git a/rlwe/secretkey.go b/rlwe/secretkey.go index 81aa8d68..09d1161e 100644 --- a/rlwe/secretkey.go +++ b/rlwe/secretkey.go @@ -1,6 +1,7 @@ package rlwe import ( + "bytes" "io" "github.com/google/go-cmp/cmp" @@ -45,18 +46,11 @@ func (sk *SecretKey) CopyNew() *SecretKey { return &SecretKey{*sk.Value.CopyNew()} } -// BinarySize returns the size in bytes that the object once marshalled into a binary form. -func (sk *SecretKey) BinarySize() (dataLen int) { - return sk.Value.BinarySize() -} - // MarshalBinary encodes the object into a binary form on a newly allocated slice of bytes. -func (sk *SecretKey) MarshalBinary() (data []byte, err error) { - data = make([]byte, sk.BinarySize()) - if _, err = sk.Read(data); err != nil { - return nil, err - } - return +func (sk *SecretKey) MarshalBinary() (p []byte, err error) { + buf := bytes.NewBuffer([]byte{}) + _, err = sk.WriteTo(buf) + return buf.Bytes(), nil } // WriteTo writes the object on an io.Writer. @@ -70,16 +64,10 @@ func (sk *SecretKey) WriteTo(w io.Writer) (n int64, err error) { return sk.Value.WriteTo(w) } -// Read encodes the object into a binary form on a preallocated slice of bytes -// and returns the number of bytes written. -func (sk *SecretKey) Read(data []byte) (ptr int, err error) { - return sk.Value.Read(data) -} - -// UnmarshalBinary decodes a slice of bytes generated by MarshalBinary, -// WriteTo or Read on the object. -func (sk *SecretKey) UnmarshalBinary(data []byte) (err error) { - _, err = sk.Write(data) +// UnmarshalBinary decodes a slice of bytes generated by +// MarshalBinary or WriteTo on the object. +func (sk *SecretKey) UnmarshalBinary(p []byte) (err error) { + _, err = sk.ReadFrom(bytes.NewBuffer(p)) return } @@ -94,8 +82,20 @@ func (sk *SecretKey) ReadFrom(r io.Reader) (n int64, err error) { return sk.Value.ReadFrom(r) } -// Write decodes a slice of bytes generated by MarshalBinary or -// Read on the object and returns the number of bytes read. -func (sk *SecretKey) Write(data []byte) (ptr int, err error) { - return sk.Value.Write(data) +// BinarySize returns the size in bytes of the object +// when encoded using Encode. +func (sk *SecretKey) BinarySize() (dataLen int) { + return sk.Value.BinarySize() +} + +// Encode encodes the object into a binary form on a preallocated slice of bytes +// and returns the number of bytes written. +func (sk *SecretKey) Encode(p []byte) (ptr int, err error) { + return sk.Value.Encode(p) +} + +// Decode decodes a slice of bytes generated by Encode +// on the object and returns the number of bytes read. +func (sk *SecretKey) Decode(p []byte) (ptr int, err error) { + return sk.Value.Decode(p) } diff --git a/utils/structs/codec.go b/utils/structs/codec.go index d421e863..c8953c05 100644 --- a/utils/structs/codec.go +++ b/utils/structs/codec.go @@ -57,31 +57,39 @@ func (c *Codec[V]) UnmarshalBinaryWrapper(p []byte, T interface{}) (err error) { return binaryunmarshaler.UnmarshalBinary(p) } -func (c *Codec[V]) ReadWrapper(p []byte, T interface{}) (n int, err error) { - reader, ok := T.(io.Reader) - - if !ok { - return 0, fmt.Errorf("cannot Read: type T=%T does not implement io.Reader", T) - } - - return reader.Read(p) +type Encoder interface { + Encode(p []byte) (n int, err error) } -func (c *Codec[V]) WriteWrapper(p []byte, T interface{}) (n int, err error) { - writer, ok := T.(io.Writer) +func (c *Codec[V]) EncodeWrapper(p []byte, T interface{}) (n int, err error) { + encoder, ok := T.(Encoder) if !ok { - return 0, fmt.Errorf("cannot Read: type T=%T does not implement io.Writer", T) + return 0, fmt.Errorf("cannot Encode: type T=%T does not implement Encoder", T) } - return writer.Write(p) + return encoder.Encode(p) +} + +type Decoder interface { + Decode(p []byte) (n int, err error) +} + +func (c *Codec[V]) DecodeWrapper(p []byte, T interface{}) (n int, err error) { + decoder, ok := T.(Decoder) + + if !ok { + return 0, fmt.Errorf("cannot Decode: type T=%T does not implement Decoder", T) + } + + return decoder.Decode(p) } func (c *Codec[V]) WriteToWrapper(w io.Writer, T interface{}) (n int64, err error) { writerto, ok := T.(io.WriterTo) if !ok { - return 0, fmt.Errorf("cannot Read: type T=%T does not implement io.WriterTo", T) + return 0, fmt.Errorf("cannot WriteTo: type T=%T does not implement io.WriterTo", T) } return writerto.WriteTo(w) @@ -91,7 +99,7 @@ func (c *Codec[V]) ReadFromWrapper(r io.Reader, T interface{}) (n int64, err err readerfrom, ok := T.(io.ReaderFrom) if !ok { - return 0, fmt.Errorf("cannot Read: type T=%T does not implement io.ReaderFrom", T) + return 0, fmt.Errorf("cannot ReadFrom: type T=%T does not implement io.ReaderFrom", T) } return readerfrom.ReadFrom(r) diff --git a/utils/structs/map.go b/utils/structs/map.go index 8ff204c8..84e876a8 100644 --- a/utils/structs/map.go +++ b/utils/structs/map.go @@ -2,6 +2,7 @@ package structs import ( "bufio" + "bytes" "encoding/binary" "fmt" "io" @@ -31,63 +32,17 @@ func (m Map[V, T]) CopyNew() *Map[V, T] { 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 { - - size += 8 - - if inc, err = codec.BinarySizeWrapper(v); err != nil { - panic(err) - } - - size += inc - } - - return -} - // MarshalBinary encodes the object into a binary form on a newly allocated slice of bytes. func (m *Map[V, T]) MarshalBinary() (p []byte, err error) { - p = make([]byte, m.BinarySize()) - _, err = m.Read(p) - return + buf := bytes.NewBuffer([]byte{}) + _, err = m.WriteTo(buf) + return buf.Bytes(), nil } -// Read encodes the object into a binary form on a preallocated slice of bytes -// and returns the number of bytes written. -func (m *Map[V, T]) Read(p []byte) (n int, err error) { - - if len(p) < m.BinarySize() { - 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))) - n += 4 - - for _, key := range utils.GetSortedKeys(mi) { - - binary.LittleEndian.PutUint64(p[n:], uint64(key)) - n += 8 - - var inc int - if inc, err = codec.ReadWrapper(p[n:], mi[key]); err != nil { - return n + inc, err - } - - n += inc - } - +// UnmarshalBinary decodes a slice of bytes generated by +// MarshalBinary or WriteTo on the object. +func (m *Map[V, T]) UnmarshalBinary(p []byte) (err error) { + _, err = m.ReadFrom(bytes.NewBuffer(p)) return } @@ -138,44 +93,6 @@ func (m *Map[V, T]) WriteTo(w io.Writer) (n int64, err error) { } } -// UnmarshalBinary decodes a slice of bytes generated by MarshalBinary, -// WriteTo or Read on the object. -func (m *Map[V, T]) UnmarshalBinary(p []byte) (err error) { - _, err = m.Write(p) - return -} - -// Write decodes a slice of bytes generated by MarshalBinary, WriteTo or -// Read on the object and returns the number of bytes read. -func (m *Map[V, T]) Write(p []byte) (n int, err error) { - - mi := *m - - 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:])) - n += 8 - - if mi[idx] == nil { - mi[idx] = new(T) - } - - var inc int - if inc, err = codec.WriteWrapper(p[n:], mi[idx]); err != nil { - return n + inc, err - } - - n += inc - } - - return -} - // ReadFrom reads on the object from an io.Writer. // To ensure optimal efficiency and minimal allocations, the user is encouraged // to provide a struct implementing the interface buffer.Reader, which defines @@ -228,3 +145,88 @@ func (m *Map[V, T]) ReadFrom(r io.Reader) (n int64, err error) { return m.ReadFrom(bufio.NewReader(r)) } } + +// BinarySize returns the size in bytes of the object +// when encoded using Encode. +func (m Map[V, T]) BinarySize() (size int) { + size = 4 // #Ct + + codec := Codec[T]{} + + var inc int + var err error + for _, v := range m { + + size += 8 + + if inc, err = codec.BinarySizeWrapper(v); err != nil { + panic(err) + } + + size += inc + } + + return +} + +// Encode encodes the object into a binary form on a preallocated slice of bytes +// and returns the number of bytes written. +func (m *Map[V, T]) Encode(p []byte) (n int, err error) { + + if len(p) < m.BinarySize() { + return n, fmt.Errorf("cannot Encode: len(p)=%d < %d", len(p), m.BinarySize()) + } + + codec := Codec[T]{} + + mi := *m + + binary.LittleEndian.PutUint32(p[n:], uint32(len(mi))) + n += 4 + + for _, key := range utils.GetSortedKeys(mi) { + + binary.LittleEndian.PutUint64(p[n:], uint64(key)) + n += 8 + + var inc int + if inc, err = codec.EncodeWrapper(p[n:], mi[key]); err != nil { + return n + inc, err + } + + n += inc + } + + return +} + +// Decode decodes a slice of bytes generated by Encode +// on the object and returns the number of bytes read. +func (m *Map[V, T]) Decode(p []byte) (n int, err error) { + + mi := *m + + 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:])) + n += 8 + + if mi[idx] == nil { + mi[idx] = new(T) + } + + var inc int + if inc, err = codec.DecodeWrapper(p[n:], mi[idx]); err != nil { + return n + inc, err + } + + n += inc + } + + return +} diff --git a/utils/structs/matrix.go b/utils/structs/matrix.go index 066b39ef..ba88c010 100644 --- a/utils/structs/matrix.go +++ b/utils/structs/matrix.go @@ -2,6 +2,7 @@ package structs import ( "bufio" + "bytes" "encoding/binary" "fmt" "io" @@ -33,61 +34,17 @@ func (m Matrix[T]) CopyNew() *Matrix[T] { 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 { - if inc, err = codec.BinarySizeWrapper(vi); err != nil { - panic(err) - } - - size += inc - } - - } - return -} - // MarshalBinary encodes the object into a binary form on a newly allocated slice of bytes. func (m *Matrix[T]) MarshalBinary() (p []byte, err error) { - p = make([]byte, m.BinarySize()) - _, err = m.Read(p) - return + buf := bytes.NewBuffer([]byte{}) + _, err = m.WriteTo(buf) + return buf.Bytes(), nil } -// Read encodes the object into a binary form on a preallocated slice of bytes -// and returns the number of bytes written. -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 { - - binary.LittleEndian.PutUint64(b[n:], uint64(len(v))) - n += 8 - - for _, vi := range v { - - if inc, err = codec.ReadWrapper(b[n:], vi); err != nil { - return n + inc, err - } - - n += inc - } - } - +// UnmarshalBinary decodes a slice of bytes generated by +// MarshalBinary or WriteTo on the object. +func (m *Matrix[T]) UnmarshalBinary(p []byte) (err error) { + _, err = m.ReadFrom(bytes.NewBuffer(p)) return } @@ -140,55 +97,6 @@ func (m Matrix[T]) WriteTo(w io.Writer) (int64, error) { } } -// UnmarshalBinary decodes a slice of bytes generated by MarshalBinary, -// WriteTo or Read on the object. -func (m *Matrix[T]) UnmarshalBinary(p []byte) (err error) { - _, err = m.Write(p) - return -} - -// Write decodes a slice of bytes generated by MarshalBinary, WriteTo or -// Read on the object and returns the number of bytes read. -func (m *Matrix[T]) Write(p []byte) (n int, err error) { - - size := int(binary.LittleEndian.Uint64(p[n:])) - n += 8 - - if len(*m) != size { - *m = make([][]*T, size) - } - - mi := *m - - codec := Codec[T]{} - - var inc int - for i := range mi { - - size := int(binary.LittleEndian.Uint64(p[n:])) - n += 8 - - if len(mi[i]) != size { - mi[i] = make([]*T, size) - } - - for j := range mi[i] { - - if mi[i][j] == nil { - mi[i][j] = new(T) - } - - if inc, err = codec.WriteWrapper(p[n:], mi[i][j]); err != nil { - return n + inc, err - } - - n += inc - } - } - - return -} - // ReadFrom reads on the object from an io.Writer. // To ensure optimal efficiency and minimal allocations, the user is encouraged // to provide a struct implementing the interface buffer.Reader, which defines @@ -249,3 +157,96 @@ func (m *Matrix[T]) ReadFrom(r io.Reader) (int64, error) { return m.ReadFrom(bufio.NewReader(r)) } } + +// BinarySize returns the size in bytes of the object +// when encoded using Encode. +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 { + if inc, err = codec.BinarySizeWrapper(vi); err != nil { + panic(err) + } + + size += inc + } + + } + return +} + +// Encode encodes the object into a binary form on a preallocated slice of bytes +// and returns the number of bytes written. +func (m Matrix[T]) Encode(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 { + + binary.LittleEndian.PutUint64(b[n:], uint64(len(v))) + n += 8 + + for _, vi := range v { + + if inc, err = codec.EncodeWrapper(b[n:], vi); err != nil { + return n + inc, err + } + + n += inc + } + } + + return +} + +// Decode decodes a slice of bytes generated by Encode +// on the object and returns the number of bytes read. +func (m *Matrix[T]) Decode(p []byte) (n int, err error) { + + size := int(binary.LittleEndian.Uint64(p[n:])) + n += 8 + + if len(*m) != size { + *m = make([][]*T, size) + } + + mi := *m + + codec := Codec[T]{} + + var inc int + for i := range mi { + + size := int(binary.LittleEndian.Uint64(p[n:])) + n += 8 + + if len(mi[i]) != size { + mi[i] = make([]*T, size) + } + + for j := range mi[i] { + + if mi[i][j] == nil { + mi[i][j] = new(T) + } + + if inc, err = codec.DecodeWrapper(p[n:], mi[i][j]); err != nil { + return n + inc, err + } + + n += inc + } + } + + return +} diff --git a/utils/structs/vector.go b/utils/structs/vector.go index 14466aef..aad8fab3 100644 --- a/utils/structs/vector.go +++ b/utils/structs/vector.go @@ -2,6 +2,7 @@ package structs import ( "bufio" + "bytes" "fmt" "io" @@ -29,53 +30,17 @@ func (v Vector[T]) CopyNew() *Vector[T] { 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 { - - if inc, err = codec.BinarySizeWrapper(vi); err != nil { - panic(err) - } - - size += inc - } - return -} - // MarshalBinary encodes the object into a binary form on a newly allocated slice of bytes. func (v *Vector[T]) MarshalBinary() (p []byte, err error) { - p = make([]byte, v.BinarySize()) - _, err = v.Read(p) - return + buf := bytes.NewBuffer([]byte{}) + _, err = v.WriteTo(buf) + return buf.Bytes(), nil } -// Read encodes the object into a binary form on a preallocated slice of bytes -// and returns the number of bytes written. -func (v *Vector[T]) Read(b []byte) (n int, err error) { - - vi := *v - - 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 { - return n + inc, err - } - - n += inc - } - +// UnmarshalBinary decodes a slice of bytes generated by +// MarshalBinary or WriteTo on the object. +func (v *Vector[T]) UnmarshalBinary(p []byte) (err error) { + _, err = v.ReadFrom(bytes.NewBuffer(p)) return } @@ -120,45 +85,6 @@ func (v *Vector[T]) WriteTo(w io.Writer) (int64, error) { } } -// UnmarshalBinary decodes a slice of bytes generated by MarshalBinary, -// WriteTo or Read on the object. -func (v *Vector[T]) UnmarshalBinary(p []byte) (err error) { - _, err = v.Write(p) - return -} - -// Write decodes a slice of bytes generated by MarshalBinary, WriteTo or -// Read on the object and returns the number of bytes read. -func (v *Vector[T]) Write(p []byte) (n int, err error) { - - size := int(binary.LittleEndian.Uint64(p[n:])) - n += 8 - - if len(*v) != size { - *v = make([]*T, size) - } - - vi := *v - - codec := Codec[T]{} - - var inc int - for i := range vi { - - if vi[i] == nil { - vi[i] = new(T) - } - - if inc, err = codec.WriteWrapper(p[n:], vi[i]); err != nil { - return n + inc, err - } - - n += inc - } - - return -} - // ReadFrom reads on the object from an io.Writer. // To ensure optimal efficiency and minimal allocations, the user is encouraged // to provide a struct implementing the interface buffer.Reader, which defines @@ -205,3 +131,79 @@ func (v *Vector[T]) ReadFrom(r io.Reader) (int64, error) { return v.ReadFrom(bufio.NewReader(r)) } } + +// BinarySize returns the size in bytes of the object +// when encoded using Encode. +func (v Vector[T]) BinarySize() (size int) { + + var err error + var inc int + + codec := Codec[T]{} + + size += 8 + for _, vi := range v { + + if inc, err = codec.BinarySizeWrapper(vi); err != nil { + panic(err) + } + + size += inc + } + return +} + +// Encode encodes the object into a binary form on a preallocated slice of bytes +// and returns the number of bytes written. +func (v *Vector[T]) Encode(b []byte) (n int, err error) { + + vi := *v + + binary.LittleEndian.PutUint64(b[n:], uint64(len(vi))) + n += 8 + + codec := Codec[T]{} + + var inc int + for i := range vi { + if inc, err = codec.EncodeWrapper(b[n:], vi[i]); err != nil { + return n + inc, err + } + + n += inc + } + + return +} + +// Decode decodes a slice of bytes generated by Encode +// on the object and returns the number of bytes read. +func (v *Vector[T]) Decode(p []byte) (n int, err error) { + + size := int(binary.LittleEndian.Uint64(p[n:])) + n += 8 + + if len(*v) != size { + *v = make([]*T, size) + } + + vi := *v + + codec := Codec[T]{} + + var inc int + for i := range vi { + + if vi[i] == nil { + vi[i] = new(T) + } + + if inc, err = codec.DecodeWrapper(p[n:], vi[i]); err != nil { + return n + inc, err + } + + n += inc + } + + return +}