github.com/badrootd/celestia-core@v0.0.0-20240305091328-aa4207a4b25d/libs/bytes/bytes.go (about)

     1  package bytes
     2  
     3  import (
     4  	"encoding/binary"
     5  	"encoding/hex"
     6  	"encoding/json"
     7  	"fmt"
     8  	"strings"
     9  )
    10  
    11  // HexBytes enables HEX-encoding for json/encoding.
    12  type HexBytes []byte
    13  
    14  var (
    15  	_ json.Marshaler   = HexBytes{}
    16  	_ json.Unmarshaler = &HexBytes{}
    17  )
    18  
    19  func (bz HexBytes) MarshalDelimited() ([]byte, error) {
    20  	lenBuf := make([]byte, binary.MaxVarintLen64)
    21  	length := uint64(len(bz))
    22  	n := binary.PutUvarint(lenBuf, length)
    23  
    24  	return append(lenBuf[:n], bz...), nil
    25  }
    26  
    27  // Marshal needed for protobuf compatibility
    28  func (bz HexBytes) Marshal() ([]byte, error) {
    29  	return bz, nil
    30  }
    31  
    32  // Unmarshal needed for protobuf compatibility
    33  func (bz *HexBytes) Unmarshal(data []byte) error {
    34  	*bz = data
    35  	return nil
    36  }
    37  
    38  // This is the point of Bytes.
    39  func (bz HexBytes) MarshalJSON() ([]byte, error) {
    40  	s := strings.ToUpper(hex.EncodeToString(bz))
    41  	jbz := make([]byte, len(s)+2)
    42  	jbz[0] = '"'
    43  	copy(jbz[1:], s)
    44  	jbz[len(jbz)-1] = '"'
    45  	return jbz, nil
    46  }
    47  
    48  // This is the point of Bytes.
    49  func (bz *HexBytes) UnmarshalJSON(data []byte) error {
    50  	if len(data) < 2 || data[0] != '"' || data[len(data)-1] != '"' {
    51  		return fmt.Errorf("invalid hex string: %s", data)
    52  	}
    53  	bz2, err := hex.DecodeString(string(data[1 : len(data)-1]))
    54  	if err != nil {
    55  		return err
    56  	}
    57  	*bz = bz2
    58  	return nil
    59  }
    60  
    61  // Bytes fulfills various interfaces in light-client, etc...
    62  func (bz HexBytes) Bytes() []byte {
    63  	return bz
    64  }
    65  
    66  func (bz HexBytes) String() string {
    67  	return strings.ToUpper(hex.EncodeToString(bz))
    68  }
    69  
    70  // Format writes either address of 0th element in a slice in base 16 notation,
    71  // with leading 0x (%p), or casts HexBytes to bytes and writes as hexadecimal
    72  // string to s.
    73  func (bz HexBytes) Format(s fmt.State, verb rune) {
    74  	switch verb {
    75  	case 'p':
    76  		s.Write([]byte(fmt.Sprintf("%p", bz)))
    77  	default:
    78  		s.Write([]byte(fmt.Sprintf("%X", []byte(bz))))
    79  	}
    80  }
    81  
    82  func FromBytes(b []byte) []HexBytes {
    83  	return []HexBytes{b}
    84  }