diff --git a/ring/poly.go b/ring/poly.go index 3e9fba26..5497020b 100644 --- a/ring/poly.go +++ b/ring/poly.go @@ -147,11 +147,11 @@ func (pol Poly) WriteTo(w io.Writer) (n int64, err error) { var inc int64 - if n, err = buffer.WriteInt(w, pol.N()); err != nil { + if n, err = buffer.WriteAsUint64(w, pol.N()); err != nil { return n, err } - if inc, err = buffer.WriteInt(w, pol.Level()); err != nil { + if inc, err = buffer.WriteAsUint64(w, pol.Level()); err != nil { return n + inc, err } @@ -187,7 +187,7 @@ func (pol *Poly) ReadFrom(r io.Reader) (n int64, err error) { var inc int64 var N int - if n, err = buffer.ReadInt(r, &N); err != nil { + if n, err = buffer.ReadAsUint64[int](r, &N); err != nil { return n, fmt.Errorf("cannot ReadFrom: N: %w", err) } @@ -198,7 +198,7 @@ func (pol *Poly) ReadFrom(r io.Reader) (n int64, err error) { } var Level int - if inc, err = buffer.ReadInt(r, &Level); err != nil { + if inc, err = buffer.ReadAsUint64[int](r, &Level); err != nil { return n + inc, fmt.Errorf("cannot ReadFrom: Level: %w", err) } diff --git a/rlwe/gadgetciphertext.go b/rlwe/gadgetciphertext.go index 22dd9454..cd1b8a8e 100644 --- a/rlwe/gadgetciphertext.go +++ b/rlwe/gadgetciphertext.go @@ -99,7 +99,7 @@ func (ct GadgetCiphertext) WriteTo(w io.Writer) (n int64, err error) { var inc int64 - if inc, err = buffer.WriteInt(w, ct.BaseTwoDecomposition); err != nil { + if inc, err = buffer.WriteAsUint64[int](w, ct.BaseTwoDecomposition); err != nil { return n + inc, err } @@ -131,7 +131,7 @@ func (ct *GadgetCiphertext) ReadFrom(r io.Reader) (n int64, err error) { var inc int64 - if inc, err = buffer.ReadInt(r, &ct.BaseTwoDecomposition); err != nil { + if inc, err = buffer.ReadAsUint64[int](r, &ct.BaseTwoDecomposition); err != nil { return n + inc, err } diff --git a/utils/buffer/reader.go b/utils/buffer/reader.go index f82c0e8b..eac37dc1 100644 --- a/utils/buffer/reader.go +++ b/utils/buffer/reader.go @@ -5,9 +5,57 @@ import ( "fmt" "unsafe" - "github.com/tuneinsight/lattigo/v4/utils" + "golang.org/x/exp/constraints" ) +// ReadAsUint64 reads an uint64 from r and stores the result into c with pointer type casting into type T. +func ReadAsUint64[T constraints.Float | constraints.Integer](r Reader, c *T) (n int64, err error) { + /* #nosec G103 -- behavior and consequences well understood */ + return ReadUint64(r, (*uint64)(unsafe.Pointer(c))) +} + +// ReadAsUint32 reads an uint32 from r and stores the result into c with pointer type casting into type T. +func ReadAsUint32[T constraints.Float | constraints.Integer](r Reader, c *T) (n int64, err error) { + /* #nosec G103 -- behavior and consequences well understood */ + return ReadUint32(r, (*uint32)(unsafe.Pointer(c))) +} + +// ReadAsUint16 reads an uint16 from r and stores the result into c with pointer type casting into type T. +func ReadAsUint16[T constraints.Float | constraints.Integer](r Reader, c *T) (n int64, err error) { + /* #nosec G103 -- behavior and consequences well understood */ + return ReadUint16(r, (*uint16)(unsafe.Pointer(c))) +} + +// ReadAsUint8 reads an uint8 from r and stores the result into c with pointer type casting into type T. +func ReadAsUint8[T constraints.Float | constraints.Integer](r Reader, c *T) (n int64, err error) { + /* #nosec G103 -- behavior and consequences well understood */ + return ReadUint8(r, (*uint8)(unsafe.Pointer(c))) +} + +// ReadAsuint64Slice reads a slice of uint64 from r and stores the result into c with pointer type casting into type T. +func ReadAsuint64Slice[T constraints.Float | constraints.Integer](r Reader, c []T) (n int64, err error) { + /* #nosec G103 -- behavior and consequences well understood */ + return ReadUint64Slice(r, *(*[]uint64)(unsafe.Pointer(&c))) +} + +// ReadAsuint32Slice reads a slice of uint32 from r and stores the result into c with pointer type casting into type T. +func ReadAsuint32Slice[T constraints.Float | constraints.Integer](r Reader, c []T) (n int64, err error) { + /* #nosec G103 -- behavior and consequences well understood */ + return ReadUint32Slice(r, *(*[]uint32)(unsafe.Pointer(&c))) +} + +// ReadAsuint16Slice reads a slice of uint16 from r and stores the result into c with pointer type casting into type T. +func ReadAsuint16Slice[T constraints.Float | constraints.Integer](r Reader, c []T) (n int64, err error) { + /* #nosec G103 -- behavior and consequences well understood */ + return ReadUint16Slice(r, *(*[]uint16)(unsafe.Pointer(&c))) +} + +// ReadAsuint8Slice reads a slice of uint8 from r and stores the result into c with pointer type casting into type T. +func ReadAsuint8Slice[T constraints.Float | constraints.Integer](r Reader, c []T) (n int64, err error) { + /* #nosec G103 -- behavior and consequences well understood */ + return ReadUint8Slice(r, *(*[]uint8)(unsafe.Pointer(&c))) +} + // Read reads a slice of bytes from r and copies it on c. func Read(r Reader, c []byte) (n int64, err error) { slice, err := r.Peek(len(c)) @@ -19,18 +67,6 @@ func Read(r Reader, c []byte) (n int64, err error) { return int64(nint), err } -// ReadInt reads an int values from r and stores the result into *c. -func ReadInt(r Reader, c *int) (n int64, err error) { - - if c == nil { - return 0, fmt.Errorf("cannot ReadInt: c is nil") - } - - nint, err := ReadUint64(r, utils.PointyIntToPointUint64(c)) - - return int64(nint), err -} - // ReadUint8 reads a byte from r and stores the result into *c. func ReadUint8(r Reader, c *uint8) (n int64, err error) { @@ -280,27 +316,3 @@ func ReadUint64Slice(r Reader, c []uint64) (n int64, err error) { return n + inc64, err } - -// ReadFloat32 reads a float64 from r and stores the result into c. -func ReadFloat32(r Reader, c *float32) (n int64, err error) { - /* #nosec G103 -- behavior and consequences well understood */ - return ReadUint32(r, (*uint32)(unsafe.Pointer(c))) -} - -// ReadFloat32Slice reads a slice of float32 from r and stores the result into c. -func ReadFloat32Slice(r Reader, c []float32) (n int64, err error) { - /* #nosec G103 -- behavior and consequences well understood */ - return ReadUint32Slice(r, *(*[]uint32)(unsafe.Pointer(&c))) -} - -// ReadFloat64 reads a float64 from r and stores the result into c. -func ReadFloat64(r Reader, c *float64) (n int64, err error) { - /* #nosec G103 -- behavior and consequences well understood */ - return ReadUint64(r, (*uint64)(unsafe.Pointer(c))) -} - -// ReadFloat64Slice reads a slice of float64 from r and stores the result into c. -func ReadFloat64Slice(r Reader, c []float64) (n int64, err error) { - /* #nosec G103 -- behavior and consequences well understood */ - return ReadUint64Slice(r, *(*[]uint64)(unsafe.Pointer(&c))) -} diff --git a/utils/buffer/writer.go b/utils/buffer/writer.go index 1769c531..dbe018b8 100644 --- a/utils/buffer/writer.go +++ b/utils/buffer/writer.go @@ -4,20 +4,72 @@ import ( "encoding/binary" "fmt" "unsafe" + + "golang.org/x/exp/constraints" ) +// WriteAsUint64 casts &T to an *uint64 and writes it to w. +// User must ensure that T can be stored in an uint64. +func WriteAsUint64[T constraints.Float | constraints.Integer](w Writer, c T) (n int64, err error) { + /* #nosec G103 -- behavior and consequences well understood */ + return WriteUint64(w, *(*uint64)(unsafe.Pointer(&c))) +} + +// WriteAsUint32 casts &T to an *uint32 and writes it to w. +// User must ensure that T can be stored in an uint32. +func WriteAsUint32[T constraints.Float | constraints.Integer](w Writer, c T) (n int64, err error) { + /* #nosec G103 -- behavior and consequences well understood */ + return WriteUint32(w, *(*uint32)(unsafe.Pointer(&c))) +} + +// WriteAsUint16 casts &T to an *uint16 and writes it to w. +// User must ensure that T can be stored in an uint16. +func WriteAsUint16[T constraints.Float | constraints.Integer](w Writer, c T) (n int64, err error) { + /* #nosec G103 -- behavior and consequences well understood */ + return WriteUint16(w, *(*uint16)(unsafe.Pointer(&c))) +} + +// WriteAsUint8 casts &T to an *uint8 and writes it to w. +// User must ensure that T can be stored in an uint8. +func WriteAsUint8[T constraints.Float | constraints.Integer](w Writer, c T) (n int64, err error) { + /* #nosec G103 -- behavior and consequences well understood */ + return WriteUint8(w, *(*uint8)(unsafe.Pointer(&c))) +} + +// WriteAsUint64Slice casts &[]T into *[]uint64 and writes it to w. +// User must ensure that T can be stored in an uint64. +func WriteAsUint64Slice[T constraints.Float | constraints.Integer](w Writer, c []T) (n int64, err error) { + /* #nosec G103 -- behavior and consequences well understood */ + return WriteUint64Slice(w, *(*[]uint64)(unsafe.Pointer(&c))) +} + +// WriteAsUint32Slice casts &[]T into *[]uint32 and writes it to w. +// User must ensure that T can be stored in an uint32. +func WriteAsUint32Slice[T constraints.Float | constraints.Integer](w Writer, c []T) (n int64, err error) { + /* #nosec G103 -- behavior and consequences well understood */ + return WriteUint32Slice(w, *(*[]uint32)(unsafe.Pointer(&c))) +} + +// WriteAsUint16Slice casts &[]T into *[]uint16 and writes it to w. +// User must ensure that T can be stored in an uint16. +func WriteAsUint16Slice[T constraints.Float | constraints.Integer](w Writer, c []T) (n int64, err error) { + /* #nosec G103 -- behavior and consequences well understood */ + return WriteUint16Slice(w, *(*[]uint16)(unsafe.Pointer(&c))) +} + +// WriteAsUint8Slice casts &[]T into *[]uint8 and writes it to w. +// User must ensure that T can be stored in an uint8. +func WriteAsUint8Slice[T constraints.Float | constraints.Integer](w Writer, c []T) (n int64, err error) { + /* #nosec G103 -- behavior and consequences well understood */ + return WriteUint8Slice(w, *(*[]uint8)(unsafe.Pointer(&c))) +} + // Write writes a slice of bytes to w. func Write(w Writer, c []byte) (n int64, err error) { nint, err := w.Write(c) return int64(nint), err } -// WriteInt writes an int c to w. -func WriteInt(w Writer, c int) (n int64, err error) { - nint, err := WriteUint64(w, uint64(c)) - return int64(nint), err -} - // WriteUint8 writes a byte c to w. func WriteUint8(w Writer, c uint8) (n int64, err error) { @@ -338,27 +390,3 @@ func WriteUint64Slice(w Writer, c []uint64) (n int64, err error) { return n + inc64, err } - -// WriteFloat32 writes a float32 c into w. -func WriteFloat32(w Writer, c float32) (n int64, err error) { - /* #nosec G103 -- behavior and consequences well understood */ - return WriteUint32(w, *(*uint32)(unsafe.Pointer(&c))) -} - -// WriteFloat32Slice writes a slice of float32 c into w. -func WriteFloat32Slice(w Writer, c []float32) (n int64, err error) { - /* #nosec G103 -- behavior and consequences well understood */ - return WriteUint32Slice(w, *(*[]uint32)(unsafe.Pointer(&c))) -} - -// WriteFloat64 writes a float64 c into w. -func WriteFloat64(w Writer, c float64) (n int64, err error) { - /* #nosec G103 -- behavior and consequences well understood */ - return WriteUint64(w, *(*uint64)(unsafe.Pointer(&c))) -} - -// WriteFloat64Slice writes a slice of float64 into w. -func WriteFloat64Slice(w Writer, c []float64) (n int64, err error) { - /* #nosec G103 -- behavior and consequences well understood */ - return WriteUint64Slice(w, *(*[]uint64)(unsafe.Pointer(&c))) -} diff --git a/utils/structs/matrix.go b/utils/structs/matrix.go index a84ff65b..b388b6e7 100644 --- a/utils/structs/matrix.go +++ b/utils/structs/matrix.go @@ -68,7 +68,7 @@ func (m Matrix[T]) WriteTo(w io.Writer) (n int64, err error) { case buffer.Writer: var inc int64 - if inc, err = buffer.WriteInt(w, len(m)); err != nil { + if inc, err = buffer.WriteAsUint64[int](w, len(m)); err != nil { return inc, err } n += inc @@ -111,7 +111,7 @@ func (m *Matrix[T]) ReadFrom(r io.Reader) (n int64, err error) { var size int var inc int64 - if n, err = buffer.ReadInt(r, &size); err != nil { + if n, err = buffer.ReadAsUint64[int](r, &size); err != nil { return int64(n), fmt.Errorf("cannot read matrix size: %w", err) } diff --git a/utils/structs/vector.go b/utils/structs/vector.go index 9af682eb..5c270969 100644 --- a/utils/structs/vector.go +++ b/utils/structs/vector.go @@ -61,7 +61,7 @@ func (v Vector[T]) WriteTo(w io.Writer) (n int64, err error) { case buffer.Writer: var inc int64 - if inc, err = buffer.WriteInt(w, len(v)); err != nil { + if inc, err = buffer.WriteAsUint64[int](w, len(v)); err != nil { return inc, err } n += inc @@ -103,7 +103,7 @@ func (v *Vector[T]) ReadFrom(r io.Reader) (n int64, err error) { var size int var inc int64 - if inc, err = buffer.ReadInt(r, &size); err != nil { + if inc, err = buffer.ReadAsUint64[int](r, &size); err != nil { return inc, fmt.Errorf("cannot read vector size: %w", err) } n += inc