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 }