From a0ebaeaa6c2544f98da01eda51339c1754cf6155 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 7 Aug 2019 15:04:08 -0700 Subject: [PATCH] tlv: zero alloc encoding for extended types This commit adds concrete encoding methods for primitive integral types. When external libs need to create custom encoders, this allows them to do so without incurring an extra allocation on the heap. Previously, the need to pass a pointer to the integer using an interface{} would cause the argument to escape, which we avoid by having them copied directly. --- tlv/primitive.go | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tlv/primitive.go b/tlv/primitive.go index 46ccfde9..3d1f0a06 100644 --- a/tlv/primitive.go +++ b/tlv/primitive.go @@ -74,6 +74,15 @@ func EUint8(w io.Writer, val interface{}, buf *[8]byte) error { return ErrTypeForEncoding{val, "uint8"} } +// EUint8T encodes a uint8 val to the provided io.Writer. This method is exposed +// so that encodings for custom uint8-like types can be created without +// incurring an extra heap allocation. +func EUint8T(w io.Writer, val uint8, buf *[8]byte) error { + buf[0] = val + _, err := w.Write(buf[:1]) + return err +} + // EUint16 is an Encoder for uint16 values. An error is returned if val is not a // *uint16. func EUint16(w io.Writer, val interface{}, buf *[8]byte) error { @@ -85,6 +94,15 @@ func EUint16(w io.Writer, val interface{}, buf *[8]byte) error { return ErrTypeForEncoding{val, "uint16"} } +// EUint16T encodes a uint16 val to the provided io.Writer. This method is +// exposed so that encodings for custom uint16-like types can be created without +// incurring an extra heap allocation. +func EUint16T(w io.Writer, val uint16, buf *[8]byte) error { + byteOrder.PutUint16(buf[:2], val) + _, err := w.Write(buf[:2]) + return err +} + // EUint32 is an Encoder for uint32 values. An error is returned if val is not a // *uint32. func EUint32(w io.Writer, val interface{}, buf *[8]byte) error { @@ -96,6 +114,15 @@ func EUint32(w io.Writer, val interface{}, buf *[8]byte) error { return ErrTypeForEncoding{val, "uint32"} } +// EUint32T encodes a uint32 val to the provided io.Writer. This method is +// exposed so that encodings for custom uint32-like types can be created without +// incurring an extra heap allocation. +func EUint32T(w io.Writer, val uint32, buf *[8]byte) error { + byteOrder.PutUint32(buf[:4], val) + _, err := w.Write(buf[:4]) + return err +} + // EUint64 is an Encoder for uint64 values. An error is returned if val is not a // *uint64. func EUint64(w io.Writer, val interface{}, buf *[8]byte) error { @@ -107,6 +134,15 @@ func EUint64(w io.Writer, val interface{}, buf *[8]byte) error { return ErrTypeForEncoding{val, "uint64"} } +// EUint64T encodes a uint64 val to the provided io.Writer. This method is +// exposed so that encodings for custom uint64-like types can be created without +// incurring an extra heap allocation. +func EUint64T(w io.Writer, val uint64, buf *[8]byte) error { + byteOrder.PutUint64(buf[:], val) + _, err := w.Write(buf[:]) + return err +} + // DUint8 is a Decoder for uint8 values. An error is returned if val is not a // *uint8. func DUint8(r io.Reader, val interface{}, buf *[8]byte, l uint64) error {