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)},
	})
}
Int8 encodes int8 data into an Attribute specified by typ.
package netlink
import (
	"encoding/binary"
	"errors"
	"fmt"
	"github.com/josharian/native"
	"github.com/mdlayher/netlink/nlenc"
)
var errInvalidAttribute = errors.New("invalid attribute; length too short or too large")
type Attribute struct {
	Length uint16
	Type uint16
	Data []byte
}
func (a *Attribute) marshal(b []byte) (int, error) {
	if int(a.Length) < nlaHeaderLen {
		return 0, errInvalidAttribute
	}
	nlenc.PutUint16(b[0:2], a.Length)
	nlenc.PutUint16(b[2:4], a.Type)
	n := copy(b[nlaHeaderLen:], a.Data)
	return nlaHeaderLen + nlaAlign(n), nil
}
func (a *Attribute) unmarshal(b []byte) error {
	if len(b) < nlaHeaderLen {
		return errInvalidAttribute
	}
	a.Length = nlenc.Uint16(b[0:2])
	a.Type = nlenc.Uint16(b[2:4])
	if int(a.Length) > len(b) {
		return errInvalidAttribute
	}
	switch {
	case a.Length == 0:
		a.Data = make([]byte, 0)
	case int(a.Length) < nlaHeaderLen:
		return errInvalidAttribute
	case int(a.Length) >= nlaHeaderLen:
		a.Data = make([]byte, len(b[nlaHeaderLen:a.Length]))
		copy(a.Data, b[nlaHeaderLen:a.Length])
	}
	return nil
}
func MarshalAttributes(attrs []Attribute) ([]byte, error) {
	var c int
	for _, a := range attrs {
		c += nlaHeaderLen + nlaAlign(len(a.Data))
	}
	var idx int
	b := make([]byte, c)
	for _, a := range attrs {
		if a.Length == 0 {
			a.Length = uint16(nlaHeaderLen + len(a.Data))
		}
		n, err := a.marshal(b[idx:])
		if err != nil {
			return nil, err
		}
		idx += n
	}
	return b, nil
}
func UnmarshalAttributes(b []byte) ([]Attribute, error) {
	ad, err := NewAttributeDecoder(b)
	if err != nil {
		return nil, err
	}
	if ad.Len() == 0 {
		return nil, nil
	}
	attrs := make([]Attribute, 0, ad.Len())
	for ad.Next() {
		if ad.attr().Length != 0 {
			attrs = append(attrs, ad.attr())
		}
	}
	if err := ad.Err(); err != nil {
		return nil, err
	}
	return attrs, nil
}
type AttributeDecoder struct {
	ByteOrder binary.ByteOrder
	a Attribute
	b []byte
	i int
	length int
	err error
}
func NewAttributeDecoder(b []byte) (*AttributeDecoder, error) {
	ad := &AttributeDecoder{
		ByteOrder: native.Endian,
		b: b,
	}
	var err error
	ad.length, err = ad.available()
	if err != nil {
		return nil, err
	}
	return ad, nil
}
func (ad *AttributeDecoder) Next() bool {
	if ad.err != nil {
		return false
	}
	if ad.i >= len(ad.b) {
		return false
	}
	if err := ad.a.unmarshal(ad.b[ad.i:]); err != nil {
		ad.err = err
		return false
	}
	if int(ad.a.Length) < nlaHeaderLen {
		ad.i += nlaHeaderLen
	} else {
		ad.i += nlaAlign(int(ad.a.Length))
	}
	return true
}
func (ad *AttributeDecoder) Type() uint16 {
	return ad.a.Type & attrTypeMask
}
func (ad *AttributeDecoder) TypeFlags() uint16 {
	return ad.a.Type & ^attrTypeMask
}
func (ad *AttributeDecoder) Len() int { return ad.length }
func (ad *AttributeDecoder) available() (int, error) {
	var i, count int
	for {
		if i >= len(ad.b) {
			break
		}
		if len(ad.b[i:]) < nlaHeaderLen {
			return 0, errInvalidAttribute
		}
		l := int(nlenc.Uint16(ad.b[i : i+2]))
		if l != 0 {
			count++
		}
		if l < nlaHeaderLen {
			l = nlaHeaderLen
		}
		i += nlaAlign(l)
	}
	return count, nil
}
func (ad *AttributeDecoder) attr() Attribute {
	return ad.a
}
func (ad *AttributeDecoder) data() []byte {
	return ad.a.Data
}
func (ad *AttributeDecoder) Err() error {
	return ad.err
}
func (ad *AttributeDecoder) Bytes() []byte {
	src := ad.data()
	dest := make([]byte, len(src))
	copy(dest, src)
	return dest
}
func (ad *AttributeDecoder) String() string {
	if ad.err != nil {
		return ""
	}
	return nlenc.String(ad.data())
}
func (ad *AttributeDecoder) Uint8() uint8 {
	if ad.err != nil {
		return 0
	}
	b := ad.data()
	if len(b) != 1 {
		ad.err = fmt.Errorf("netlink: attribute %d is not a uint8; length: %d", ad.Type(), len(b))
		return 0
	}
	return uint8(b[0])
}
func (ad *AttributeDecoder) Uint16() uint16 {
	if ad.err != nil {
		return 0
	}
	b := ad.data()
	if len(b) != 2 {
		ad.err = fmt.Errorf("netlink: attribute %d is not a uint16; length: %d", ad.Type(), len(b))
		return 0
	}
	return ad.ByteOrder.Uint16(b)
}
func (ad *AttributeDecoder) Uint32() uint32 {
	if ad.err != nil {
		return 0
	}
	b := ad.data()
	if len(b) != 4 {
		ad.err = fmt.Errorf("netlink: attribute %d is not a uint32; length: %d", ad.Type(), len(b))
		return 0
	}
	return ad.ByteOrder.Uint32(b)
}
func (ad *AttributeDecoder) Uint64() uint64 {
	if ad.err != nil {
		return 0
	}
	b := ad.data()
	if len(b) != 8 {
		ad.err = fmt.Errorf("netlink: attribute %d is not a uint64; length: %d", ad.Type(), len(b))
		return 0
	}
	return ad.ByteOrder.Uint64(b)
}
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])
}
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))
}
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))
}
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))
}
func (ad *AttributeDecoder) Flag() bool {
	if ad.err != nil {
		return false
	}
	b := ad.data()
	if len(b) != 0 {
		ad.err = fmt.Errorf("netlink: attribute %d is not a flag; length: %d", ad.Type(), len(b))
		return false
	}
	return true
}
func (ad *AttributeDecoder) Do(fn func(b []byte) error) {
	if ad.err != nil {
		return
	}
	b := ad.data()
	if err := fn(b); err != nil {
		ad.err = err
	}
}
func (ad *AttributeDecoder) Nested(fn func(nad *AttributeDecoder) error) {
	ad.Do(func(b []byte) error {
		nad, err := NewAttributeDecoder(b)
		if err != nil {
			return err
		}
		nad.ByteOrder = ad.ByteOrder
		if err := fn(nad); err != nil {
			return err
		}
		return nad.Err()
	})
}
type AttributeEncoder struct {
	ByteOrder binary.ByteOrder
	attrs []Attribute
	err   error
}
func NewAttributeEncoder() *AttributeEncoder {
	return &AttributeEncoder{
		ByteOrder: native.Endian,
	}
}
func (ae *AttributeEncoder) Uint8(typ uint16, v uint8) {
	if ae.err != nil {
		return
	}
	ae.attrs = append(ae.attrs, Attribute{
		Type: typ,
		Data: []byte{v},
	})
}
func (ae *AttributeEncoder) Uint16(typ uint16, v uint16) {
	if ae.err != nil {
		return
	}
	b := make([]byte, 2)
	ae.ByteOrder.PutUint16(b, v)
	ae.attrs = append(ae.attrs, Attribute{
		Type: typ,
		Data: b,
	})
}
func (ae *AttributeEncoder) Uint32(typ uint16, v uint32) {
	if ae.err != nil {
		return
	}
	b := make([]byte, 4)
	ae.ByteOrder.PutUint32(b, v)
	ae.attrs = append(ae.attrs, Attribute{
		Type: typ,
		Data: b,
	})
}
func (ae *AttributeEncoder) Uint64(typ uint16, v uint64) {
	if ae.err != nil {
		return
	}
	b := make([]byte, 8)
	ae.ByteOrder.PutUint64(b, v)
	ae.attrs = append(ae.attrs, Attribute{
		Type: typ,
		Data: b,
	})
}