github.com/insolar/vanilla@v0.0.0-20201023172447-248fdf805322/protokit/wire_tag.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  	"fmt"
    10  	"io"
    11  	"math"
    12  )
    13  
    14  type WireTag uint32
    15  
    16  func SafeWireTag(v uint64) (WireTag, error) {
    17  	if v > math.MaxUint32 {
    18  		return 0, fmt.Errorf("invalid wire tag, overflow, %x", v)
    19  	}
    20  	wt := WireTag(v)
    21  	if wt.IsValid() {
    22  		return wt, nil
    23  	}
    24  	return 0, fmt.Errorf("invalid wire tag: %v", v)
    25  }
    26  
    27  func (v WireTag) IsZero() bool {
    28  	return v != 0
    29  }
    30  
    31  func (v WireTag) IsValid() bool {
    32  	return v.FieldID() > 0 && v.Type().IsValid()
    33  }
    34  
    35  func (v WireTag) Type() WireType {
    36  	return WireType(v & maskWireType)
    37  }
    38  
    39  func (v WireTag) FieldID() int {
    40  	return int(v >> WireTypeBits)
    41  }
    42  
    43  func (v WireTag) TagSize() int {
    44  	return SizeVarint32(uint32(v))
    45  }
    46  
    47  func (v WireTag) MaxFieldSize() (isFixed bool, max int) {
    48  	switch minSize, maxSize := v.Type().DataSize(); {
    49  	case minSize == maxSize:
    50  		return true, maxSize + v.TagSize()
    51  	case maxSize > 0:
    52  		maxSize += v.TagSize()
    53  		return false, maxSize
    54  	default:
    55  		return false, int(math.MaxInt64)
    56  	}
    57  }
    58  
    59  func (v WireTag) FieldSize(u uint64) uint64 {
    60  	return v.Type().FieldSize(v.TagSize(), u)
    61  }
    62  
    63  func (v WireTag) FixedFieldSize() int {
    64  	if isFixed, maxSize := v.MaxFieldSize(); !isFixed {
    65  		panic("illegal state - not fixed size")
    66  	} else {
    67  		return maxSize
    68  	}
    69  }
    70  
    71  func (v WireTag) EnsureFixedFieldSize(sz int) WireTag {
    72  	if v.FixedFieldSize() != sz {
    73  		panic("illegal value - size mismatched")
    74  	}
    75  	return v
    76  }
    77  
    78  func (v WireTag) _checkTag(expected WireTag) error {
    79  	if v == expected {
    80  		return nil
    81  	}
    82  	return fmt.Errorf("tag mismatch: actual=%v, expected=%v", expected, v)
    83  }
    84  
    85  func (v WireTag) CheckType(t WireType) error {
    86  	switch {
    87  	case !t.IsValid():
    88  		panic("illegal value")
    89  	case t != v.Type():
    90  		return fmt.Errorf("type mismatch: actual=%v, expectedType=%v", v, t)
    91  	}
    92  	return nil
    93  }
    94  
    95  func (v WireTag) CheckTag(expected WireTag) error {
    96  	if !expected.IsValid() {
    97  		panic("illegal value")
    98  	}
    99  	return v._checkTag(expected)
   100  }
   101  
   102  func (v WireTag) CheckActualTagValue(actual uint64) error {
   103  	wt, err := SafeWireTag(actual)
   104  	if err != nil {
   105  		return err
   106  	}
   107  	return wt._checkTag(v)
   108  }
   109  
   110  func (v WireTag) Check(expectedType WireType, expectedID int) error {
   111  	return v._checkTag(expectedType.Tag(expectedID))
   112  }
   113  
   114  func (v WireTag) ReadValue(r io.ByteReader) (uint64, error) {
   115  	return v.Type().ReadValue(r)
   116  }
   117  
   118  func (v WireTag) WriteValue(w io.ByteWriter, u uint64) error {
   119  	return v.Type().WriteValue(w, u)
   120  }
   121  
   122  func (v WireTag) ReadValueFromBytes(b []byte) (uint64, int, error) {
   123  	return v.Type().ReadValueFromBytes(b)
   124  }
   125  
   126  func (v WireTag) WriteValueToBytes(b []byte, u uint64) (int, error) {
   127  	return v.Type().WriteValueToBytes(b, u)
   128  }
   129  
   130  func (v WireTag) WriteTagValue(w io.ByteWriter, u uint64) error {
   131  	if err := EncodeVarint(w, uint64(v)); err != nil {
   132  		return err
   133  	}
   134  	return v.Type().WriteValue(w, u)
   135  }
   136  
   137  func (v WireTag) WriteTagValueToBytes(b []byte, u uint64) (int, error) {
   138  	n, err := EncodeVarintToBytesWithError(b, uint64(v))
   139  	if err != nil {
   140  		return 0, err
   141  	}
   142  	n2 := n
   143  	n, err = v.Type().WriteValueToBytes(b[n:], u)
   144  	if err != nil {
   145  		return 0, err
   146  	}
   147  	return n + n2, nil
   148  }
   149  
   150  func (v WireTag) EnsureType(expectedType WireType) {
   151  	if err := v.CheckType(expectedType); err != nil {
   152  		panic(err)
   153  	}
   154  }
   155  
   156  func (v WireTag) EnsureTag(expected WireTag) {
   157  	if err := v.CheckTag(expected); err != nil {
   158  		panic(err)
   159  	}
   160  }
   161  
   162  func (v WireTag) Ensure(expectedType WireType, expectedID int) {
   163  	if err := v.Check(expectedType, expectedID); err != nil {
   164  		panic(err)
   165  	}
   166  }
   167  
   168  func (v WireTag) MustWrite(w io.ByteWriter, u uint64) {
   169  	if err := v.WriteTagValue(w, u); err != nil {
   170  		panic(err)
   171  	}
   172  }
   173  
   174  func (v WireTag) MustRead(r io.ByteReader) uint64 {
   175  	if u, err := v.ReadTagValue(r); err != nil {
   176  		panic(err)
   177  	} else {
   178  		return u
   179  	}
   180  }
   181  
   182  func (v WireTag) String() string {
   183  	if v == 0 {
   184  		return "zeroTag"
   185  	}
   186  	return fmt.Sprintf("%d:%v", v.FieldID(), v.Type())
   187  }