github.com/insolar/vanilla@v0.0.0-20201023172447-248fdf805322/protokit/wire_type.go (about)

     1  // Copyright 2020 Insolar Network Ltd.
     2  // All rights reserved.
     3  // This material is licensed under the Insolar License version 1.0,
     4  // available at https://github.com/insolar/assured-ledger/blob/master/LICENSE.md.
     5  
     6  package protokit
     7  
     8  import (
     9  	"encoding/binary"
    10  	"fmt"
    11  	"io"
    12  	"math"
    13  )
    14  
    15  const (
    16  	WireTypeBits  = 3
    17  	MaxVarintSize = binary.MaxVarintLen64
    18  	MinVarintSize = 1
    19  	MaxFieldID    = math.MaxUint32 >> WireTypeBits
    20  	maskWireType  = 1<<WireTypeBits - 1
    21  )
    22  
    23  type WireType uint8
    24  
    25  const (
    26  	WireVarint WireType = iota
    27  	WireFixed64
    28  	WireBytes
    29  	WireStartGroup
    30  	WireEndGroup
    31  	WireFixed32
    32  
    33  	MaxWireType = iota - 1
    34  )
    35  
    36  type UintDecoderFunc func(io.ByteReader) (uint64, error)
    37  type UintEncoderFunc func(io.ByteWriter, uint64) error
    38  
    39  type UintByteDecoderFunc func([]byte) (uint64, int, error)
    40  type UintByteEncoderFunc func([]byte, uint64) (int, error)
    41  
    42  var wireTypes = []struct {
    43  	name             string
    44  	decodeFn         UintDecoderFunc
    45  	encodeFn         UintEncoderFunc
    46  	byteDecodeFn     UintByteDecoderFunc
    47  	byteEncodeFn     UintByteEncoderFunc
    48  	fieldSizeFn      func(uint64) uint64
    49  	minSize, maxSize int8
    50  }{
    51  	WireFixed64: {"fixed64", DecodeFixed64, EncodeFixed64,
    52  		DecodeFixed64FromBytesWithError, EncodeFixed64ToBytes,
    53  		nil, 8, 8},
    54  
    55  	WireFixed32: {"fixed32", DecodeFixed32, func(w io.ByteWriter, u uint64) error {
    56  		if u > math.MaxUint32 {
    57  			panic(errOverflow)
    58  		}
    59  		return EncodeFixed32(w, uint32(u))
    60  	}, DecodeFixed32FromBytesWithError, func(b []byte, u uint64) (int, error) {
    61  		if u > math.MaxUint32 {
    62  			panic(errOverflow)
    63  		}
    64  		return EncodeFixed32ToBytes(b, uint32(u))
    65  	},
    66  		nil, 4, 4},
    67  
    68  	WireVarint: {"varint", DecodeVarint, EncodeVarint,
    69  		DecodeVarintFromBytesWithError, EncodeVarintToBytesWithError,
    70  		func(u uint64) uint64 {
    71  			return uint64(SizeVarint64(u))
    72  		},
    73  		1, MaxVarintSize},
    74  
    75  	WireBytes: {"bytes", DecodeVarint, EncodeVarint,
    76  		DecodeVarintFromBytesWithError, EncodeVarintToBytesWithError,
    77  		func(u uint64) uint64 {
    78  			return uint64(SizeVarint64(u)) + u
    79  		},
    80  		1, -1},
    81  
    82  	WireStartGroup: {name: "groupStart"},
    83  	WireEndGroup:   {name: "groupEnd"},
    84  }
    85  
    86  func (v WireType) IsValid() bool {
    87  	return v <= MaxWireType
    88  }
    89  
    90  func (v WireType) Tag(fieldID int) WireTag {
    91  	if fieldID <= 0 || fieldID > MaxFieldID {
    92  		panic("illegal value")
    93  	}
    94  	return WireTag(fieldID<<WireTypeBits | int(v))
    95  }
    96  
    97  const maxMask = int(^uint(0) >> 1)
    98  
    99  func (v WireType) DataSize() (minSize, maxSize int) {
   100  	min, max := int(wireTypes[v].minSize), int(wireTypes[v].maxSize)
   101  	if min <= 0 {
   102  		panic("illegal value")
   103  	}
   104  	return min, max & maxMask /* converts -1 to maxInt */
   105  }
   106  
   107  func (v WireType) FieldSize(tagSize int, u uint64) uint64 {
   108  	sizeFn := wireTypes[v].fieldSizeFn
   109  	if sizeFn != nil {
   110  		return sizeFn(u) + uint64(tagSize)
   111  	}
   112  	if wireTypes[v].minSize == 0 {
   113  		panic("illegal value")
   114  	}
   115  	return uint64(wireTypes[v].minSize) + uint64(tagSize)
   116  }
   117  
   118  func (v WireType) UintDecoder() (UintDecoderFunc, error) {
   119  	if v <= MaxWireType {
   120  		return wireTypes[v].decodeFn, nil
   121  	}
   122  	return nil, fmt.Errorf("unsupported wire type %x", v)
   123  }
   124  
   125  func (v WireType) UintEncoder() (UintEncoderFunc, error) {
   126  	if v <= MaxWireType {
   127  		return wireTypes[v].encodeFn, nil
   128  	}
   129  	return nil, fmt.Errorf("unsupported wire type %x", v)
   130  }
   131  
   132  func (v WireType) UintByteDecoder() (UintByteDecoderFunc, error) {
   133  	if v <= MaxWireType {
   134  		return wireTypes[v].byteDecodeFn, nil
   135  	}
   136  	return nil, fmt.Errorf("unsupported wire type %x", v)
   137  }
   138  
   139  func (v WireType) UintByteEncoder() (UintByteEncoderFunc, error) {
   140  	if v <= MaxWireType {
   141  		return wireTypes[v].byteEncodeFn, nil
   142  	}
   143  	return nil, fmt.Errorf("unsupported wire type %x", v)
   144  }
   145  
   146  func (v WireType) String() string {
   147  	if v <= MaxWireType {
   148  		if s := wireTypes[v].name; s != "" {
   149  			return s
   150  		}
   151  	}
   152  	return fmt.Sprintf("unknown%d", v)
   153  }
   154  
   155  func (v WireType) ReadValue(r io.ByteReader) (uint64, error) {
   156  	decodeFn, err := v.UintDecoder()
   157  	if err != nil {
   158  		return 0, err
   159  	}
   160  	return decodeFn(r)
   161  }
   162  
   163  func (v WireType) WriteValue(w io.ByteWriter, u uint64) error {
   164  	encodeFn, err := v.UintEncoder()
   165  	if err != nil {
   166  		return err
   167  	}
   168  	return encodeFn(w, u)
   169  }
   170  
   171  func (v WireType) WriteValueToBytes(b []byte, u uint64) (int, error) {
   172  	encodeFn, err := v.UintByteEncoder()
   173  	if err != nil {
   174  		return 0, err
   175  	}
   176  	return encodeFn(b, u)
   177  }
   178  
   179  func (v WireType) ReadValueFromBytes(b []byte) (uint64, int, error) {
   180  	decodeFn, err := v.UintByteDecoder()
   181  	if err != nil {
   182  		return 0, 0, err
   183  	}
   184  	return decodeFn(b)
   185  }