Skip to content

Commit

Permalink
netlink: implement signed integer encoding/decoding (#185)
Browse files Browse the repository at this point in the history
  • Loading branch information
fbegyn authored Feb 23, 2021
1 parent 544aeb8 commit 0b57953
Show file tree
Hide file tree
Showing 3 changed files with 215 additions and 6 deletions.
117 changes: 117 additions & 0 deletions attribute.go
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,66 @@ func (ad *AttributeDecoder) Uint64() uint64 {
return ad.ByteOrder.Uint64(b)
}

// Int8 returns the Int8 representation of the current Attribute's data.
func (ad *AttributeDecoder) Int8() int8 {
if ad.err != nil {
return 0
}

b := ad.data()
if len(b) != 1 {
ad.err = fmt.Errorf("netlink: attribute %d is not a int8; length: %d", ad.Type(), len(b))
return 0
}

return int8(b[0])
}

// Int16 returns the Int16 representation of the current Attribute's data.
func (ad *AttributeDecoder) Int16() int16 {
if ad.err != nil {
return 0
}

b := ad.data()
if len(b) != 2 {
ad.err = fmt.Errorf("netlink: attribute %d is not a int16; length: %d", ad.Type(), len(b))
return 0
}

return int16(ad.ByteOrder.Uint16(b))
}

// Int32 returns the Int32 representation of the current Attribute's data.
func (ad *AttributeDecoder) Int32() int32 {
if ad.err != nil {
return 0
}

b := ad.data()
if len(b) != 4 {
ad.err = fmt.Errorf("netlink: attribute %d is not a int32; length: %d", ad.Type(), len(b))
return 0
}

return int32(ad.ByteOrder.Uint32(b))
}

// Int64 returns the Int64 representation of the current Attribute's data.
func (ad *AttributeDecoder) Int64() int64 {
if ad.err != nil {
return 0
}

b := ad.data()
if len(b) != 8 {
ad.err = fmt.Errorf("netlink: attribute %d is not a int64; length: %d", ad.Type(), len(b))
return 0
}

return int64(ad.ByteOrder.Uint64(b))
}

// Flag returns a boolean representing the Attribute.
func (ad *AttributeDecoder) Flag() bool {
if ad.err != nil {
Expand Down Expand Up @@ -501,6 +561,63 @@ func (ae *AttributeEncoder) Uint64(typ uint16, v uint64) {
})
}

// Int8 encodes int8 data into an Attribute specified by typ.
func (ae *AttributeEncoder) Int8(typ uint16, v int8) {
if ae.err != nil {
return
}

ae.attrs = append(ae.attrs, Attribute{
Type: typ,
Data: []byte{uint8(v)},
})
}

// Int16 encodes int16 data into an Attribute specified by typ.
func (ae *AttributeEncoder) Int16(typ uint16, v int16) {
if ae.err != nil {
return
}

b := make([]byte, 2)
ae.ByteOrder.PutUint16(b, uint16(v))

ae.attrs = append(ae.attrs, Attribute{
Type: typ,
Data: b,
})
}

// Int32 encodes int32 data into an Attribute specified by typ.
func (ae *AttributeEncoder) Int32(typ uint16, v int32) {
if ae.err != nil {
return
}

b := make([]byte, 4)
ae.ByteOrder.PutUint32(b, uint32(v))

ae.attrs = append(ae.attrs, Attribute{
Type: typ,
Data: b,
})
}

// Int64 encodes int64 data into an Attribute specified by typ.
func (ae *AttributeEncoder) Int64(typ uint16, v int64) {
if ae.err != nil {
return
}

b := make([]byte, 8)
ae.ByteOrder.PutUint64(b, uint64(v))

ae.attrs = append(ae.attrs, Attribute{
Type: typ,
Data: b,
})
}

// Flag encodes a flag into an Attribute specidied by typ.
func (ae *AttributeEncoder) Flag(typ uint16, v bool) {
// Only set flag on no previous error or v == true.
Expand Down
90 changes: 84 additions & 6 deletions attribute_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,42 @@ func TestAttributeDecoderError(t *testing.T) {
ad.Uint64()
},
},
{
name: "int8",
attrs: bad,
fn: func(ad *AttributeDecoder) {
ad.Int8()
ad.Next()
ad.Int8()
},
},
{
name: "int16",
attrs: bad,
fn: func(ad *AttributeDecoder) {
ad.Int16()
ad.Next()
ad.Int16()
},
},
{
name: "int32",
attrs: bad,
fn: func(ad *AttributeDecoder) {
ad.Int32()
ad.Next()
ad.Int32()
},
},
{
name: "int64",
attrs: bad,
fn: func(ad *AttributeDecoder) {
ad.Int64()
ad.Next()
ad.Int64()
},
},
{
name: "do",
attrs: bad,
Expand Down Expand Up @@ -527,17 +563,17 @@ func TestAttributeDecoderOK(t *testing.T) {
},
},
{
name: "uint native endian",
name: "uint-int native endian",
attrs: adEndianAttrs(native.Endian),
fn: adEndianTest(native.Endian),
},
{
name: "uint little endian",
name: "uint-int little endian",
attrs: adEndianAttrs(binary.LittleEndian),
fn: adEndianTest(binary.LittleEndian),
},
{
name: "uint big endian",
name: "uint-int big endian",
attrs: adEndianAttrs(binary.BigEndian),
fn: adEndianTest(binary.BigEndian),
},
Expand Down Expand Up @@ -832,6 +868,36 @@ func adEndianAttrs(order binary.ByteOrder) []Attribute {
return b
}(),
},
{
Type: 5,
Data: func() []byte {
return []byte{uint8(int8(5))}
}(),
},
{
Type: 6,
Data: func() []byte {
b := make([]byte, 2)
order.PutUint16(b, uint16(int16(6)))
return b
}(),
},
{
Type: 7,
Data: func() []byte {
b := make([]byte, 4)
order.PutUint32(b, uint32(int32(7)))
return b
}(),
},
{
Type: 8,
Data: func() []byte {
b := make([]byte, 8)
order.PutUint64(b, uint64(int64(8)))
return b
}(),
},
}
}

Expand All @@ -853,6 +919,14 @@ func adEndianTest(order binary.ByteOrder) func(ad *AttributeDecoder) {
v = int(ad.Uint32())
case 4:
v = int(ad.Uint64())
case 5:
v = int(ad.Int8())
case 6:
v = int(ad.Int16())
case 7:
v = int(ad.Int32())
case 8:
v = int(ad.Int64())
default:
panicf("unhandled attribute type: %d", t)
}
Expand Down Expand Up @@ -909,18 +983,18 @@ func TestAttributeEncoderOK(t *testing.T) {
},
},
{
name: "uint native endian",
name: "uint-int native endian",
attrs: adEndianAttrs(native.Endian),
fn: aeEndianTest(native.Endian),
},
{
name: "uint little endian",
name: "uint-int little endian",
attrs: adEndianAttrs(binary.LittleEndian),
endian: binary.LittleEndian,
fn: aeEndianTest(binary.LittleEndian),
},
{
name: "uint big endian",
name: "uint-int big endian",
attrs: adEndianAttrs(binary.BigEndian),
endian: binary.BigEndian,
fn: aeEndianTest(binary.BigEndian),
Expand Down Expand Up @@ -1071,5 +1145,9 @@ func aeEndianTest(order binary.ByteOrder) func(ae *AttributeEncoder) {
ae.Uint16(2, uint16(2))
ae.Uint32(3, uint32(3))
ae.Uint64(4, uint64(4))
ae.Int8(5, int8(5))
ae.Int16(6, int16(6))
ae.Int32(7, int32(7))
ae.Int64(8, int64(8))
}
}
14 changes: 14 additions & 0 deletions nlenc/int_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,13 +125,27 @@ func TestUintPanic(t *testing.T) {
Uint64(b)
},
},
{
name: "short put signed 32",
b: make([]byte, 3),
fn: func(b []byte) {
PutInt32(b, 0)
},
},
{
name: "short get signed 32",
b: make([]byte, 3),
fn: func(b []byte) {
Int32(b)
},
},
{
name: "long put signed 32",
b: make([]byte, 5),
fn: func(b []byte) {
PutInt32(b, 0)
},
},
{
name: "long get signed 32",
b: make([]byte, 5),
Expand Down

0 comments on commit 0b57953

Please sign in to comment.