github.com/kaleido-io/firefly@v0.0.0-20210622132723-8b4b6aacb971/pkg/fftypes/bytyetypes.go (about) 1 // Copyright © 2021 Kaleido, Inc. 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 package fftypes 18 19 import ( 20 "context" 21 "crypto/rand" 22 "database/sql/driver" 23 "encoding/hex" 24 "hash" 25 "strings" 26 27 "github.com/kaleido-io/firefly/internal/i18n" 28 ) 29 30 // Bytes32 is a holder of a hash, that can be used to correlate onchain data with off-chain data. 31 type Bytes32 [32]byte 32 33 func NewRandB32() *Bytes32 { 34 var b Bytes32 35 _, _ = rand.Read(b[0:32]) 36 return &b 37 } 38 39 func HashResult(hash hash.Hash) *Bytes32 { 40 sum := hash.Sum(make([]byte, 0, 32)) 41 var b32 Bytes32 42 copy(b32[:], sum) 43 return &b32 44 } 45 46 func (b32 Bytes32) MarshalText() ([]byte, error) { 47 hexstr := make([]byte, 64) 48 hex.Encode(hexstr, b32[0:32]) 49 return hexstr, nil 50 } 51 52 func (b32 *Bytes32) UnmarshalText(b []byte) error { 53 // We don't encourage the 0x prefix or use it internally, but we will strip it if supplied 54 s := strings.TrimPrefix(string(b), "0x") 55 _, err := hex.Decode(b32[0:32], []byte(s)) 56 return err 57 } 58 59 func ParseBytes32(ctx context.Context, hexStr string) (*Bytes32, error) { 60 trimmed := []byte(strings.TrimPrefix(hexStr, "0x")) 61 if len(trimmed) != 64 { 62 return nil, i18n.NewError(context.Background(), i18n.MsgInvalidWrongLenB32) 63 } 64 var b32 Bytes32 65 err := b32.UnmarshalText(trimmed) 66 if err != nil { 67 return nil, i18n.WrapError(context.Background(), err, i18n.MsgInvalidHex) 68 } 69 return &b32, nil 70 } 71 72 // Scan implements sql.Scanner 73 func (b32 *Bytes32) Scan(src interface{}) error { 74 switch src := src.(type) { 75 case nil: 76 return nil 77 78 case string: 79 if src == "" { 80 return nil 81 } 82 return b32.UnmarshalText([]byte(src)) 83 84 case []byte: 85 if len(src) == 0 { 86 return nil 87 } 88 if len(src) != 32 { 89 return b32.UnmarshalText(src) 90 } 91 copy((*b32)[:], src) 92 return nil 93 94 default: 95 return i18n.NewError(context.Background(), i18n.MsgScanFailed, src, b32) 96 } 97 98 } 99 100 // Value implements sql.Valuer 101 func (b32 *Bytes32) Value() (driver.Value, error) { 102 if b32 == nil { 103 return nil, nil 104 } 105 return b32.String(), nil 106 } 107 108 func (b32 *Bytes32) String() string { 109 if b32 == nil { 110 return "" 111 } 112 return hex.EncodeToString(b32[0:32]) 113 } 114 115 // HexUUID is 32 character ASCII string containing the hex representation of UUID, with the dashes of the canonical representation removed 116 type HexUUID = Bytes32 117 118 // UUIDBytes returns the bytes of a UUID as a compressed hex string 119 func UUIDBytes(u *UUID) *Bytes32 { 120 var d Bytes32 121 copy(d[:], u[:]) 122 return &d 123 } 124 125 func (b32 *Bytes32) Equals(b2 *Bytes32) bool { 126 switch { 127 case b32 == nil && b2 == nil: 128 return true 129 case b32 == nil || b2 == nil: 130 return false 131 default: 132 return *b32 == *b2 133 } 134 }