github.com/ledgerwatch/erigon-lib@v1.0.0/common/bytes4.go (about) 1 package common 2 3 import ( 4 "bytes" 5 "database/sql/driver" 6 "encoding/hex" 7 "fmt" 8 "math/rand" 9 "reflect" 10 11 "github.com/ledgerwatch/erigon-lib/common/hexutility" 12 "github.com/ledgerwatch/erigon-lib/common/length" 13 ) 14 15 var ( 16 bytes4T = reflect.TypeOf(Bytes4{}) 17 ) 18 19 type Bytes4 [length.Bytes4]byte 20 21 // Hex converts a hash to a hex string. 22 func (b Bytes4) Hex() string { return hexutility.Encode(b[:]) } 23 24 // UnmarshalJSON parses a hash in hex syntax. 25 func (b *Bytes4) UnmarshalJSON(input []byte) error { 26 return hexutility.UnmarshalFixedJSON(bytes4T, input, b[:]) 27 } 28 29 // UnmarshalText parses a hash in hex syntax. 30 func (b *Bytes4) UnmarshalText(input []byte) error { 31 return hexutility.UnmarshalFixedText("Bytes4", input, b[:]) 32 } 33 34 // MarshalText returns the hex representation of a. 35 func (b Bytes4) MarshalText() ([]byte, error) { 36 bl := b[:] 37 result := make([]byte, len(b)*2+2) 38 copy(result, hexPrefix) 39 hex.Encode(result[2:], bl) 40 return result, nil 41 } 42 43 // Format implements fmt.Formatter. 44 // Hash supports the %v, %s, %v, %x, %X and %d format verbs. 45 func (b Bytes4) Format(s fmt.State, c rune) { 46 hexb := make([]byte, 2+len(b)*2) 47 copy(hexb, "0x") 48 hex.Encode(hexb[2:], b[:]) 49 50 switch c { 51 case 'x', 'X': 52 if !s.Flag('#') { 53 hexb = hexb[2:] 54 } 55 if c == 'X' { 56 hexb = bytes.ToUpper(hexb) 57 } 58 fallthrough 59 case 'v', 's': 60 s.Write(hexb) 61 case 'q': 62 q := []byte{'"'} 63 s.Write(q) 64 s.Write(hexb) 65 s.Write(q) 66 case 'd': 67 fmt.Fprint(s, ([len(b)]byte)(b)) 68 default: 69 fmt.Fprintf(s, "%%!%c(hash=%x)", c, b) 70 } 71 } 72 73 // String implements the stringer interface and is used also by the logger when 74 // doing full logging into a file. 75 func (b Bytes4) String() string { 76 return b.Hex() 77 } 78 79 // SetBytes sets the hash to the value of i. 80 // If b is larger than len(h), b will be cropped from the left. 81 func (b *Bytes4) SetBytes(i []byte) { 82 if len(i) > len(b) { 83 i = i[len(i)-length.Hash:] 84 } 85 86 copy(b[length.Hash-len(i):], i) 87 } 88 89 // Generate implements testing/quick.Generator. 90 func (b Bytes4) Generate(rand *rand.Rand, size int) reflect.Value { 91 m := rand.Intn(len(b)) 92 for i := len(b) - 1; i > m; i-- { 93 b[i] = byte(rand.Uint32()) 94 } 95 return reflect.ValueOf(b) 96 } 97 98 // Value implements valuer for database/sql. 99 func (b Bytes4) Value() (driver.Value, error) { 100 return b[:], nil 101 } 102 103 // TerminalString implements log.TerminalStringer, formatting a string for console 104 // output during logging. 105 func (b Bytes4) TerminalString() string { 106 return fmt.Sprintf("%x", b) 107 }