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  }