github.com/insolar/vanilla@v0.0.0-20201023172447-248fdf805322/longbits/bytestring.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 "encoding/hex" 10 "io" 11 "math/bits" 12 "strings" 13 ) 14 15 const EmptyByteString = ByteString("") 16 17 func WrapStr(s string) ByteString { 18 return ByteString(s) 19 } 20 21 func CopyBytes(v []byte) ByteString { 22 return ByteString(v) 23 } 24 25 func Zero(len int) ByteString { 26 return Fill(len, 0) 27 } 28 29 func Fill(len int, fill byte) ByteString { 30 if len == 0 { 31 return EmptyByteString 32 } 33 b := make([]byte, len) 34 if fill != 0 { 35 for i := len - 1; i >= 0; i-- { 36 b[i] = fill 37 } 38 } 39 // lest hope for the compiler to optimize it 40 return ByteString(b) 41 } 42 43 var _ FoldableReader = EmptyByteString 44 45 type ByteString string 46 47 func (v ByteString) IsEmpty() bool { 48 return len(v) == 0 49 } 50 51 func (v ByteString) WriteTo(w io.Writer) (int64, error) { 52 n, err := w.Write([]byte(v)) 53 return int64(n), err 54 } 55 56 func (v ByteString) CopyTo(b []byte) int { 57 return copy(b, v) 58 } 59 60 func (v ByteString) ReadAt(b []byte, off int64) (n int, err error) { 61 if n, err = VerifyReadAt(b, off, len(v)); err != nil || n == 0 { 62 return n, err 63 } 64 return copy(b, v[off:]), nil 65 } 66 67 func (v ByteString) AsByteString() ByteString { 68 return v 69 } 70 71 func (v ByteString) FixedByteSize() int { 72 return len(v) 73 } 74 75 func (v ByteString) CutOutUint64() uint64 { 76 folded := v.CutOutBits64() 77 return folded.FoldToUint64() 78 } 79 80 func (v ByteString) FoldToUint64() uint64 { 81 folded := v.FoldToBits64() 82 return folded.FoldToUint64() 83 } 84 85 func (v ByteString) BitMasked(index int) (value byte, mask uint8) { 86 bytePos, bitPos := v.BitPos(index) 87 mask = 1 << bitPos 88 return v[bytePos] & mask, mask 89 } 90 91 func (v ByteString) BitBool(index int) bool { 92 if b, _ := v.BitMasked(index); b != 0 { 93 return true 94 } 95 return false 96 } 97 98 func (v ByteString) BitValue(index int) byte { 99 if b, _ := v.BitMasked(index); b != 0 { 100 return 1 101 } 102 return 0 103 } 104 105 func (v ByteString) Byte(index int) byte { 106 return v[index] 107 } 108 109 func (v ByteString) BitPos(index int) (bytePos int, bitPos uint8) { 110 bytePos, bitPos = BitPos(index) 111 if bytePos >= len(v) { 112 panic("out of bounds") 113 } 114 return bytePos, bitPos 115 } 116 117 func (v ByteString) BitLen() int { 118 return len(v) << 3 119 } 120 121 func (v ByteString) SearchBit(startAt int, bit bool) int { 122 if startAt < 0 { 123 panic("illegal value") 124 } 125 if startAt>>3 >= len(v) { 126 return -1 127 } 128 129 if bit { 130 return v.searchBit1(startAt) 131 } 132 return v.searchBit0(startAt) 133 } 134 135 func (v ByteString) searchBit1(startAt int) int { 136 bytePos := startAt >> 3 137 bitPos := byte(startAt & 0x7) 138 139 b := v[bytePos] >> bitPos 140 if b != 0 { 141 return bytePos<<3 + int(bitPos) + bits.TrailingZeros8(b) 142 } 143 144 for bytePos++; bytePos < len(v); bytePos++ { 145 b := v[bytePos] 146 if b != 0 { 147 return bytePos<<3 + bits.TrailingZeros8(b) 148 } 149 } 150 return -1 151 } 152 153 func (v ByteString) searchBit0(startAt int) int { 154 bytePos := startAt >> 3 155 bitPos := byte(startAt & 0x7) 156 157 b := (^v[bytePos]) >> bitPos 158 if b != 0 { 159 return bytePos<<3 + int(bitPos) + bits.TrailingZeros8(b) 160 } 161 162 for bytePos++; bytePos < len(v); bytePos++ { 163 b := v[bytePos] 164 if b != 0xFF { 165 return bytePos<<3 + bits.TrailingZeros8(^b) 166 } 167 } 168 return -1 169 } 170 171 func (v ByteString) CutOutBits64() (folded Bits64) { 172 if len(v) <= len(folded) { 173 copy(folded[:], v) 174 return folded 175 } 176 177 for i := range folded { 178 folded[i] = v[i*(len(v)-1)/(len(folded)-1)] 179 } 180 return folded 181 } 182 183 func (v ByteString) FoldToBits64() (folded Bits64) { 184 if len(v) == 0 { 185 return folded 186 } 187 188 alignedLen := len(v) 189 alignedLen &^= len(folded) - 1 190 copy(folded[:], v[alignedLen:]) 191 192 for i := 0; i < alignedLen; i += len(folded) { 193 folded[0] ^= v[i+0] 194 folded[1] ^= v[i+1] 195 folded[2] ^= v[i+2] 196 folded[3] ^= v[i+3] 197 folded[4] ^= v[i+4] 198 folded[5] ^= v[i+5] 199 folded[6] ^= v[i+6] 200 folded[7] ^= v[i+7] 201 } 202 return folded 203 } 204 205 func (v ByteString) String() string { 206 return bitsToStringDefault(&v) 207 } 208 209 func (v ByteString) NewIoReader() io.Reader { 210 return strings.NewReader(string(v)) 211 } 212 213 func (v ByteString) Hex() string { 214 if v == "" { 215 return "" 216 } 217 b := make([]byte, hex.EncodedLen(len(v))) 218 hex.Encode(b, []byte(v)) 219 return string(b) 220 } 221 222 func (v ByteString) Equal(other FixedReader) bool { 223 if other == nil { 224 return false 225 } 226 if s, ok := other.(ByteString); ok { 227 return s == v 228 } 229 return Equal(v, other) 230 }