Skip to content

Commit

Permalink
chore(docs): improve go doc
Browse files Browse the repository at this point in the history
  • Loading branch information
pauloavelar committed Jan 7, 2023
1 parent 9f7d0b3 commit cf34830
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 37 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,25 @@ nodes** found in the payload.

> ⚠️  The decoder works in an all or none strategy when dealing with multiple messages.

### Manually-created nodes use the default decoder configuration

When a `tlv.Node` is created by declaring the struct, all methods that require context, such as `GetNodes`
or `GetUint8` (or any other integer parser), will use the **standard decoder** definitions. See above for
more details on the decoder. To create a node with custom decoder configuration, first create a decoder
and call the `NewNode` method on it.


```go
var node tlv.Node
node = tlv.Node{Tag: Tag(0x1234), Value: []byte{1}}
node.GetNodes() // uses the standard decoder configuration
customDecoder := tlv.MustCreateDecoder(1, 1, binary.LittleEndian)
node = customDecoder.NewNode(Tag(0x1234), []byte{1})
node.GetNodes() // uses the customDecoder configuration
```

## Caveats

### No bit parity or checksum
Expand Down
24 changes: 13 additions & 11 deletions tlv/decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ import (
"github.com/pauloavelar/go-tlv/tlv/internal/utils"
)

// Decoder is a TLV decoder with custom configuration.
// Decoder is a configurable TLV decoder instance.
type Decoder interface {
// DecodeReader decodes the whole reader to a list of TLV nodes
// DecodeReader decodes the entire reader data to a list of TLV [Nodes].
DecodeReader(reader io.Reader) (Nodes, error)
// DecodeBytes decodes a byte array to a list of TLV nodes
// DecodeBytes decodes a byte array to a list of TLV [Nodes].
DecodeBytes(data []byte) (Nodes, error)
// DecodeSingle decodes a byte array to a single TLV node
// DecodeSingle decodes a byte array to a single TLV [Node].
DecodeSingle(data []byte) (res Node, read uint64, err error)
// NewNode creates a new node using the decoder configuration
// NewNode creates a new node using the decoder configuration.
NewNode(tag Tag, value []byte) Node
// GetByteOrder returns the decoder endianness configuration
// GetByteOrder returns the decoder endianness configuration.
GetByteOrder() binary.ByteOrder
}

Expand All @@ -36,7 +36,7 @@ const (
maxLenSize = 8 // 2^8 = 256
)

// MustCreateDecoder creates a decoder using custom configuration or panics in case of any errors.
// MustCreateDecoder creates a [Decoder] using custom configuration or panics in case of any errors.
func MustCreateDecoder(tagSize, lengthSize uint8, byteOrder binary.ByteOrder) Decoder {
res, err := CreateDecoder(tagSize, lengthSize, byteOrder)
if err != nil {
Expand All @@ -46,7 +46,7 @@ func MustCreateDecoder(tagSize, lengthSize uint8, byteOrder binary.ByteOrder) De
return res
}

// CreateDecoder creates a decoder using custom configuration.
// CreateDecoder creates a [Decoder] using custom configuration.
// Hint: tagSize and lengthSize must be numbers between 1 and 8.
func CreateDecoder(tagSize, lengthSize uint8, byteOrder binary.ByteOrder) (Decoder, error) {
if tagSize < minTagSize || tagSize > maxTagSize {
Expand All @@ -67,7 +67,7 @@ func CreateDecoder(tagSize, lengthSize uint8, byteOrder binary.ByteOrder) (Decod
return res, nil
}

// DecodeReader decodes the full contents of a Reader as TLV nodes.
// DecodeReader decodes the full contents of a [io.Reader] as TLV [Nodes].
// Note: the current implementation loads the entire Reader data into memory.
func (d *decoder) DecodeReader(reader io.Reader) (Nodes, error) {
data, err := io.ReadAll(reader)
Expand All @@ -78,7 +78,7 @@ func (d *decoder) DecodeReader(reader io.Reader) (Nodes, error) {
return d.DecodeBytes(data)
}

// DecodeBytes decodes a byte array as TLV nodes.
// DecodeBytes decodes a byte array as TLV [Nodes].
func (d *decoder) DecodeBytes(data []byte) (Nodes, error) {
node, read, err := d.DecodeSingle(data)
if err != nil {
Expand All @@ -97,7 +97,7 @@ func (d *decoder) DecodeBytes(data []byte) (Nodes, error) {
return append(Nodes{node}, next...), nil
}

// DecodeSingle decodes a byte array as a single TLV node.
// DecodeSingle decodes a byte array as a single TLV [Node].
func (d *decoder) DecodeSingle(data []byte) (res Node, read uint64, err error) {
if len(data) < int(d.minNodeSize) {
return res, 0, errors.NewMessageTooShortError(data)
Expand All @@ -122,6 +122,7 @@ func (d *decoder) DecodeSingle(data []byte) (res Node, read uint64, err error) {
return node, messageLength, nil
}

// NewNode creates a new [Node] using the [Decoder] configuration.
func (d *decoder) NewNode(tag Tag, value []byte) Node {
return Node{
Tag: tag,
Expand All @@ -131,6 +132,7 @@ func (d *decoder) NewNode(tag Tag, value []byte) Node {
}
}

// GetByteOrder returns the [Decoder] endianness configuration.
func (d *decoder) GetByteOrder() binary.ByteOrder {
return d.byteOrder
}
32 changes: 13 additions & 19 deletions tlv/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,7 @@ func (n *Node) String() string {

// GetNodes parses the value as decoded TLV nodes
func (n *Node) GetNodes() (Nodes, error) {
if n.decoder != nil {
return n.decoder.DecodeBytes(n.Value)
}

return stdDecoder.DecodeBytes(n.Value)
return n.getSafeDecoder().DecodeBytes(n.Value)
}

// GetBool parses the value as boolean if it has enough bytes
Expand Down Expand Up @@ -93,14 +89,14 @@ func (n *Node) GetUint16() (res uint16, ok bool) {
return 0, false
}

return n.getSafeBinParser().Uint16(n.Value), true
return n.getByteOrder().Uint16(n.Value), true
}

// GetPaddedUint16 parses the value as uint16 regardless of size
func (n *Node) GetPaddedUint16() uint16 {
padding := utils.GetPadding(sizes.Uint16, len(n.Value))

return n.getSafeBinParser().Uint16(append(padding, n.Value...))
return n.getByteOrder().Uint16(append(padding, n.Value...))
}

// GetUint32 parses the value as uint32 if it has enough bytes
Expand All @@ -109,14 +105,14 @@ func (n *Node) GetUint32() (res uint32, exists bool) {
return 0, false
}

return n.getSafeBinParser().Uint32(n.Value), true
return n.getByteOrder().Uint32(n.Value), true
}

// GetPaddedUint32 parses the value as uint32 regardless of size
func (n *Node) GetPaddedUint32() uint32 {
padding := utils.GetPadding(sizes.Uint32, len(n.Value))

return n.getSafeBinParser().Uint32(append(padding, n.Value...))
return n.getByteOrder().Uint32(append(padding, n.Value...))
}

// GetUint64 parses the value as uint64 if it has enough bytes
Expand All @@ -125,26 +121,24 @@ func (n *Node) GetUint64() (res uint64, ok bool) {
return 0, false
}

return n.getSafeBinParser().Uint64(n.Value), true
return n.getByteOrder().Uint64(n.Value), true
}

// GetPaddedUint64 parses the value as uint64 regardless of size
func (n *Node) GetPaddedUint64() uint64 {
padding := utils.GetPadding(sizes.Uint64, len(n.Value))

return n.getSafeBinParser().Uint64(append(padding, n.Value...))
return n.getByteOrder().Uint64(append(padding, n.Value...))
}

func (n *Node) getSafeBinParser() binary.ByteOrder {
var parser binary.ByteOrder

func (n *Node) getSafeDecoder() Decoder {
if n.decoder != nil {
parser = n.decoder.GetByteOrder()
return n.decoder
}

if parser != nil {
return parser
}
return stdDecoder
}

return stdBinParser
func (n *Node) getByteOrder() binary.ByteOrder {
return n.getSafeDecoder().GetByteOrder()
}
5 changes: 5 additions & 0 deletions tlv/node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,11 @@ func TestNode_GetPaddedUint64(t *testing.T) {
}
}

func TestNode_GetUint16_WhenTheNodeIsDeclaredManually(t *testing.T) {
node := &Node{Value: []byte{0x12, 0x34}}
require.Equal(t, uint16(0x1234), node.GetPaddedUint16())
}

func newNode(value []byte) *Node {
node := NewNode(Tag(0x01), value)
return &node
Expand Down
14 changes: 7 additions & 7 deletions tlv/standard.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,28 @@ import (
"github.com/pauloavelar/go-tlv/tlv/internal/sizes"
)

// stdBinParser is the default value parser
var stdBinParser = binary.BigEndian
// stdByteOrder is the default endianness for parsing numbers.
var stdByteOrder = binary.BigEndian

// stdDecoder uses 2 bytes for tags and lengths and parses them as big endian.
var stdDecoder = MustCreateDecoder(sizes.Uint16, sizes.Uint16, stdBinParser)
var stdDecoder = MustCreateDecoder(sizes.Uint16, sizes.Uint16, stdByteOrder)

// DecodeReader decodes the whole reader as a list of TLV nodes.
// DecodeReader decodes the entire [io.Reader] data as a list of TLV nodes.
func DecodeReader(reader io.Reader) (Nodes, error) {
return stdDecoder.DecodeReader(reader)
}

// DecodeBytes decodes a byte array as a list of TLV nodes.
// DecodeBytes decodes a byte array as a list of TLV [Nodes].
func DecodeBytes(data []byte) (Nodes, error) {
return stdDecoder.DecodeBytes(data)
}

// DecodeSingle decodes a byte array as a single TLV node.
// DecodeSingle decodes a byte array as a single TLV [Node].
func DecodeSingle(data []byte) (res Node, read uint64, err error) {
return stdDecoder.DecodeSingle(data)
}

// NewNode creates a node with the standard decoder configuration
// NewNode creates a [Node] with the default [Decoder] configuration.
func NewNode(tag Tag, value []byte) Node {
return stdDecoder.NewNode(tag, value)
}

0 comments on commit cf34830

Please sign in to comment.