123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346 |
- package tlv
- import (
- "bytes"
- "encoding/binary"
- "errors"
- "fmt"
- "io"
- )
- const (
- TLV_FLOAT64 = 1
- TLV_FLOAT32 = 2
- TLV_INT8 = 3
- TLV_INT16 = 4
- TLV_INT32 = 5
- TLV_INT64 = 6
- TLV_UINT8 = 7
- TLV_UINT16 = 8
- TLV_UINT32 = 9
- TLV_UINT64 = 10
- TLV_BYTES = 11
- TLV_STRING = 12
- TLV_BOOL = 13
- )
- type TLV struct {
- Tag uint16
- Value []byte
- }
- func Uint16ToByte(value uint16) []byte {
- buf := bytes.NewBuffer([]byte{})
- binary.Write(buf, binary.BigEndian, value)
- return buf.Bytes()
- }
- func ByteToUint16(buf []byte) uint16 {
- tmpBuf := bytes.NewBuffer(buf)
- var value uint16
- binary.Read(tmpBuf, binary.BigEndian, &value)
- return value
- }
- func (tlv *TLV) ToBinary() []byte {
- buf := new(bytes.Buffer)
- binary.Write(buf, binary.BigEndian, &tlv.Tag)
- binary.Write(buf, binary.BigEndian, &tlv.Value)
- return buf.Bytes()
- }
- func (tlv *TLV) Length() int {
- length := int(0)
- switch tlv.Tag {
- case TLV_FLOAT64:
- length = 8
- case TLV_INT64:
- length = 8
- case TLV_UINT64:
- length = 8
- case TLV_FLOAT32:
- length = 4
- case TLV_INT32:
- length = 4
- case TLV_UINT32:
- length = 4
- case TLV_INT16:
- length = 2
- case TLV_UINT16:
- length = 2
- case TLV_INT8:
- length = 1
- case TLV_UINT8:
- length = 1
- case TLV_BYTES:
- length = int(ByteToUint16(tlv.Value[0:2]))
- length += 2
- case TLV_STRING:
- length = int(ByteToUint16(tlv.Value[0:2]))
- length += 2
- default:
- length = 0
- }
- length += 2
- return length
- }
- func (tlv *TLV) FromBinary(r io.Reader) error {
- binary.Read(r, binary.BigEndian, &tlv.Tag)
- length := uint16(0)
- switch tlv.Tag {
- case TLV_FLOAT64:
- length = 8
- tlv.Value = make([]byte, length)
- binary.Read(r, binary.BigEndian, &tlv.Value)
- case TLV_INT64:
- length = 8
- tlv.Value = make([]byte, length)
- binary.Read(r, binary.BigEndian, &tlv.Value)
- case TLV_UINT64:
- length = 8
- tlv.Value = make([]byte, length)
- binary.Read(r, binary.BigEndian, &tlv.Value)
- case TLV_FLOAT32:
- length = 4
- tlv.Value = make([]byte, length)
- binary.Read(r, binary.BigEndian, &tlv.Value)
- case TLV_INT32:
- length = 4
- tlv.Value = make([]byte, length)
- binary.Read(r, binary.BigEndian, &tlv.Value)
- case TLV_UINT32:
- length = 4
- tlv.Value = make([]byte, length)
- binary.Read(r, binary.BigEndian, &tlv.Value)
- case TLV_INT16:
- length = 2
- tlv.Value = make([]byte, length)
- binary.Read(r, binary.BigEndian, &tlv.Value)
- case TLV_UINT16:
- length = 2
- tlv.Value = make([]byte, length)
- binary.Read(r, binary.BigEndian, &tlv.Value)
- case TLV_INT8:
- length = 1
- tlv.Value = make([]byte, length)
- binary.Read(r, binary.BigEndian, &tlv.Value)
- case TLV_UINT8:
- length = 1
- tlv.Value = make([]byte, length)
- binary.Read(r, binary.BigEndian, &tlv.Value)
- case TLV_BYTES:
- binary.Read(r, binary.BigEndian, &length)
- tlv.Value = make([]byte, length+2)
- copy(tlv.Value[0:2], Uint16ToByte(length))
- binary.Read(r, binary.BigEndian, tlv.Value[2:])
- case TLV_STRING:
- binary.Read(r, binary.BigEndian, &length)
- tlv.Value = make([]byte, length+2)
- copy(tlv.Value[0:2], Uint16ToByte(length))
- binary.Read(r, binary.BigEndian, tlv.Value[2:])
- default:
- return errors.New(fmt.Sprintf("unsuport value: %d", tlv.Tag))
- }
- return nil
- }
- func MakeTLV(a interface{}) (*TLV, error) {
- var tag uint16
- var length uint16
- buf := new(bytes.Buffer)
- switch a.(type) {
- case float64:
- tag = TLV_FLOAT64
- length = 8
- binary.Write(buf, binary.BigEndian, a.(float64))
- case float32:
- tag = TLV_FLOAT32
- length = 4
- binary.Write(buf, binary.BigEndian, a.(float32))
- case int8:
- tag = TLV_INT8
- length = 1
- binary.Write(buf, binary.BigEndian, a.(int8))
- case int16:
- tag = TLV_INT16
- length = 2
- binary.Write(buf, binary.BigEndian, a.(int16))
- case int32:
- tag = TLV_INT32
- length = 4
- binary.Write(buf, binary.BigEndian, a.(int32))
- case int64:
- tag = TLV_INT64
- length = 8
- binary.Write(buf, binary.BigEndian, a.(int64))
- case uint8:
- tag = TLV_UINT8
- length = 1
- binary.Write(buf, binary.BigEndian, a.(uint8))
- case uint16:
- tag = TLV_UINT16
- length = 2
- binary.Write(buf, binary.BigEndian, a.(uint16))
- case uint32:
- tag = TLV_UINT32
- length = 4
- binary.Write(buf, binary.BigEndian, a.(uint32))
- case uint64:
- tag = TLV_UINT64
- length = 8
- binary.Write(buf, binary.BigEndian, a.(uint64))
- case []byte:
- tag = TLV_BYTES
- length = uint16(len(a.([]byte)))
- binary.Write(buf, binary.BigEndian, length)
- binary.Write(buf, binary.BigEndian, a.([]byte))
- case string:
- tag = TLV_STRING
- length = uint16(len(a.(string)))
- binary.Write(buf, binary.BigEndian, length)
- binary.Write(buf, binary.BigEndian, []byte(a.(string)))
- default:
- return nil, errors.New(fmt.Sprintf("unsuport value: %v", a))
- }
- tlv := TLV{
- Tag: tag,
- Value: buf.Bytes(),
- }
- if length == 0 {
- tlv.Value = []byte{}
- }
- return &tlv, nil
- }
- func ReadTLV(tlv *TLV) (interface{}, error) {
- tag := tlv.Tag
- length := uint16(0)
- value := tlv.Value
- buffer := bytes.NewReader(value)
- switch tag {
- case TLV_FLOAT64:
- retvar := float64(0.0)
- err := binary.Read(buffer, binary.BigEndian, &retvar)
- return retvar, err
- case TLV_FLOAT32:
- retvar := float32(0.0)
- err := binary.Read(buffer, binary.BigEndian, &retvar)
- return retvar, err
- case TLV_INT8:
- retvar := int8(0)
- err := binary.Read(buffer, binary.BigEndian, &retvar)
- return retvar, err
- case TLV_INT16:
- retvar := int16(0)
- err := binary.Read(buffer, binary.BigEndian, &retvar)
- return retvar, err
- case TLV_INT32:
- retvar := int32(0)
- err := binary.Read(buffer, binary.BigEndian, &retvar)
- return retvar, err
- case TLV_INT64:
- retvar := int64(0)
- err := binary.Read(buffer, binary.BigEndian, &retvar)
- return retvar, err
- case TLV_UINT8:
- retvar := uint8(0)
- err := binary.Read(buffer, binary.BigEndian, &retvar)
- return retvar, err
- case TLV_UINT16:
- retvar := uint16(0)
- err := binary.Read(buffer, binary.BigEndian, &retvar)
- return retvar, err
- case TLV_UINT32:
- retvar := uint32(0)
- err := binary.Read(buffer, binary.BigEndian, &retvar)
- return retvar, err
- case TLV_UINT64:
- retvar := uint64(0)
- err := binary.Read(buffer, binary.BigEndian, &retvar)
- return retvar, err
- case TLV_BYTES:
- err := binary.Read(buffer, binary.BigEndian, &length)
- if err != nil {
- return []byte{}, err
- }
- retvar := make([]byte, length)
- err = binary.Read(buffer, binary.BigEndian, &retvar)
- return retvar, err
- case TLV_STRING:
- err := binary.Read(buffer, binary.BigEndian, &length)
- if err != nil {
- return string([]byte{}), err
- }
- retvar := make([]byte, length)
- err = binary.Read(buffer, binary.BigEndian, &retvar)
- return string(retvar), err
- default:
- return nil, errors.New("Reading TLV error ,Unkown TLV type: " + string(tag))
- }
- }
- func MakeTLVs(a []interface{}) ([]TLV, error) {
- tlvs := []TLV{}
- for _, one := range a {
- tlv, err := MakeTLV(one)
- if err != nil {
- return nil, err
- }
- tlvs = append(tlvs, *tlv)
- }
- return tlvs, nil
- }
- func ReadTLVs(tlvs []TLV) ([]interface{}, error) {
- values := []interface{}{}
- for _, tlv := range tlvs {
- one, err := ReadTLV(&tlv)
- if err != nil {
- return values, err
- }
- values = append(values, one)
- }
- return values, nil
- }
- func CastTLV(value interface{}, valueType int32) interface{} {
- switch valueType {
- case TLV_FLOAT64:
- return float64(value.(float64))
- case TLV_FLOAT32:
- return float32(value.(float64))
- case TLV_INT8:
- return int8(value.(float64))
- case TLV_INT16:
- return int16(value.(float64))
- case TLV_INT32:
- return int32(value.(float64))
- case TLV_INT64:
- return int64(value.(float64))
- case TLV_UINT8:
- return uint8(value.(float64))
- case TLV_UINT16:
- return uint16(value.(float64))
- case TLV_UINT32:
- return uint32(value.(float64))
- case TLV_UINT64:
- return uint64(value.(float64))
- case TLV_BYTES:
- return []byte(value.(string))
- case TLV_STRING:
- return value.(string)
- default:
- return nil
- }
- }
|