github.com/insolar/vanilla@v0.0.0-20201023172447-248fdf805322/longbits/fixed_size.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 longbits 7 8 import ( 9 "bytes" 10 "errors" 11 "io" 12 13 "github.com/insolar/vanilla/throw" 14 ) 15 16 type Foldable interface { 17 FoldToUint64() uint64 18 } 19 20 //go:generate minimock -i github.com/insolar/vanilla/longbits.FixedReader -o . -s _mock.go -g 21 type FixedReader interface { 22 io.WriterTo 23 CopyTo(p []byte) int 24 AsByteString() ByteString 25 26 FixedByteSize() int 27 } 28 29 //go:generate minimock -i github.com/insolar/vanilla/longbits.FoldableReader -o . -s _mock.go -g 30 type FoldableReader interface { 31 FixedReader 32 Foldable 33 } 34 35 func FoldUint64(v uint64) uint32 { 36 return uint32(v) ^ uint32(v>>32) 37 } 38 39 func Equal(t, o FixedReader) bool { 40 switch { 41 case t == nil || o == nil: 42 return false 43 case t.FixedByteSize() == 0: 44 return o.FixedByteSize() == 0 45 } 46 return (&writerToComparer{}).compare(t, o) 47 } 48 49 func EqualToBytes(t FixedReader, o []byte) bool { 50 switch { 51 case t == nil: 52 return false 53 case t.FixedByteSize() == 0: 54 return len(o) == 0 55 case len(o) == 0: 56 return false 57 } 58 return (&writerToComparer{}).compareBytes(o, t) 59 } 60 61 type writerToComparer struct { 62 thisValue *[]byte 63 other io.WriterTo 64 result bool 65 } 66 67 func (c *writerToComparer) compareBytes(this []byte, other FixedReader) bool { 68 if other == nil || len(this) != other.FixedByteSize() { 69 return false 70 } 71 c.thisValue = &this 72 c.other = other 73 _, _ = other.WriteTo(c) 74 return c.other == nil && c.result 75 } 76 77 func (c *writerToComparer) compare(this, other FixedReader) bool { 78 c.thisValue = nil 79 if this == nil || other == nil || this.FixedByteSize() != other.FixedByteSize() { 80 return false 81 } 82 c.other = other 83 _, _ = this.WriteTo(c) 84 return c.other == nil && c.result 85 } 86 87 func (c *writerToComparer) Write(otherValue []byte) (int, error) { 88 if c.other == nil { 89 panic("content of FixedReader must be read/written all at once") 90 } 91 if c.thisValue == nil { 92 c.thisValue = &otherValue 93 _, err := c.other.WriteTo(c) 94 if err != nil { 95 return 0, err 96 } 97 } else { 98 c.other = nil // mark "done" 99 c.result = bytes.Equal(*c.thisValue, otherValue) 100 } 101 return len(otherValue), nil 102 } 103 104 type fixedSize struct { 105 data []byte 106 } 107 108 func (c fixedSize) AsByteString() ByteString { 109 return ByteString(c.data) 110 } 111 112 func (c fixedSize) String() string { 113 return ByteString(c.data).String() 114 } 115 116 func (c fixedSize) WriteTo(w io.Writer) (n int64, err error) { 117 n32, err := w.Write(c.data) 118 return int64(n32), err 119 } 120 121 func (c fixedSize) CopyTo(p []byte) (n int) { 122 return copy(p, c.data) 123 } 124 125 func (c fixedSize) FoldToUint64() uint64 { 126 return FoldToUint64(c.data) 127 } 128 129 func (c fixedSize) CutOutUint64() uint64 { 130 return CutOutUint64(c.data) 131 } 132 133 func (c fixedSize) FixedByteSize() int { 134 return len(c.data) 135 } 136 137 func AsBytes(v FixedReader) []byte { 138 if v == nil { 139 return nil 140 } 141 n := v.FixedByteSize() 142 if n == 0 { 143 return nil 144 } 145 data := make([]byte, n) 146 if v.CopyTo(data) != len(data) { 147 panic(throw.Impossible()) 148 } 149 return data 150 } 151 152 func WrapBytes(data []byte) FoldableReader { 153 return fixedSize{data} 154 } 155 156 func CopyFixed(v FixedReader) FoldableReader { 157 if v == nil { 158 return EmptyByteString 159 } 160 if bs, ok := v.(ByteString); ok { 161 return bs 162 } 163 switch n := v.FixedByteSize(); n*8 { 164 case 0: 165 return EmptyByteString 166 case 64: 167 dst := Bits64{} 168 v.CopyTo(dst[:]) 169 return dst 170 case 128: 171 dst := Bits128{} 172 v.CopyTo(dst[:]) 173 return dst 174 case 224: 175 dst := Bits224{} 176 v.CopyTo(dst[:]) 177 return dst 178 case 256: 179 dst := Bits256{} 180 v.CopyTo(dst[:]) 181 return dst 182 case 512: 183 dst := Bits512{} 184 v.CopyTo(dst[:]) 185 return dst 186 default: 187 data := make([]byte, n) 188 if v.CopyTo(data) != n { 189 panic(throw.Impossible()) 190 } 191 return WrapBytes(data) 192 } 193 } 194 195 func Copy(to []byte, from FixedReader) error { 196 if n := from.FixedByteSize(); n != len(to) { 197 if n < len(to) { 198 return io.ErrShortBuffer 199 } 200 return io.ErrShortWrite 201 } 202 from.CopyTo(to) 203 return nil 204 } 205 206 func VerifyReadAt(b []byte, off int64, max int) (n int, err error) { 207 switch { 208 case off < 0: 209 return 0, errors.New("negative offset") 210 case off > int64(max): 211 return 0, io.ErrUnexpectedEOF 212 case len(b) == 0: 213 return 0, nil 214 case max == int(off): 215 return 0, io.EOF 216 } 217 return len(b), nil 218 }