mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-09 14:43:19 +00:00
The HexBytes wrapper type handles decoding byte strings from JSON. In the RPC API, hashes are encoded as hex digits rather than the standard base64. Simplify the implementation of this wrapper using the TextMarshaler interface, which the encoding/json package uses for values (like these) that are meant to be wrapped in JSON strings. In addition, allow HexBytes values to be decoded from either hex OR base64 input. This preserves all existing use, but will allow us to remove some reflection special cases in the RPC decoder plumbing. Update tests to correctly tolerate empty/nil.
72 lines
1.7 KiB
Go
72 lines
1.7 KiB
Go
package bytes
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// HexBytes is a wrapper around []byte that encodes data as hexadecimal strings
|
|
// for use in JSON.
|
|
type HexBytes []byte
|
|
|
|
// Marshal needed for protobuf compatibility
|
|
func (bz HexBytes) Marshal() ([]byte, error) {
|
|
return bz, nil
|
|
}
|
|
|
|
// Unmarshal needed for protobuf compatibility
|
|
func (bz *HexBytes) Unmarshal(data []byte) error {
|
|
*bz = data
|
|
return nil
|
|
}
|
|
|
|
// MarshalText encodes a HexBytes value as hexadecimal digits.
|
|
// This method is used by json.Marshal.
|
|
func (bz HexBytes) MarshalText() ([]byte, error) {
|
|
enc := hex.EncodeToString([]byte(bz))
|
|
return []byte(strings.ToUpper(enc)), nil
|
|
}
|
|
|
|
// UnmarshalText handles decoding of HexBytes from JSON strings.
|
|
// This method is used by json.Unmarshal.
|
|
// It allows decoding of both hex and base64-encoded byte arrays.
|
|
func (bz *HexBytes) UnmarshalText(data []byte) error {
|
|
input := string(data)
|
|
if input == "" || input == "null" {
|
|
return nil
|
|
}
|
|
dec, err := hex.DecodeString(input)
|
|
if err != nil {
|
|
dec, err = base64.StdEncoding.DecodeString(input)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
*bz = HexBytes(dec)
|
|
return nil
|
|
}
|
|
|
|
// Bytes fulfills various interfaces in light-client, etc...
|
|
func (bz HexBytes) Bytes() []byte {
|
|
return bz
|
|
}
|
|
|
|
func (bz HexBytes) String() string {
|
|
return strings.ToUpper(hex.EncodeToString(bz))
|
|
}
|
|
|
|
// Format writes either address of 0th element in a slice in base 16 notation,
|
|
// with leading 0x (%p), or casts HexBytes to bytes and writes as hexadecimal
|
|
// string to s.
|
|
func (bz HexBytes) Format(s fmt.State, verb rune) {
|
|
switch verb {
|
|
case 'p':
|
|
s.Write([]byte(fmt.Sprintf("%p", bz)))
|
|
default:
|
|
s.Write([]byte(fmt.Sprintf("%X", []byte(bz))))
|
|
}
|
|
}
|