Marshal json hash

This commit is contained in:
Andrea Maria Piana 2019-11-02 09:46:37 +01:00
parent 019becdcbb
commit 9e44c7e51e
No known key found for this signature in database
GPG Key ID: AA6CCA6DE0E06424
1 changed files with 50 additions and 0 deletions

View File

@ -4,6 +4,8 @@ package statusproto
import (
"encoding/hex"
"fmt"
"reflect"
)
const (
@ -14,6 +16,8 @@ const (
// Hash represents the 32 byte Keccak256 hash of arbitrary data.
type Hash [HashLength]byte
var hashT = reflect.TypeOf(Hash{})
// Encode encodes b as a hex string with 0x prefix.
func encode(b []byte) string {
enc := make([]byte, len(b)*2+2)
@ -71,6 +75,21 @@ func (h *Hash) SetBytes(b []byte) {
copy(h[HashLength-len(b):], b)
}
// UnmarshalText parses a hash in hex syntax.
func (h *Hash) UnmarshalText(input []byte) error {
return UnmarshalFixedText("Hash", input, h[:])
}
// UnmarshalJSON parses a hash in hex syntax.
func (h *Hash) UnmarshalJSON(input []byte) error {
return UnmarshalFixedJSON(hashT, input, h[:])
}
// MarshalText returns the hex representation of h.
func (h Hash) MarshalText() ([]byte, error) {
return HexBytes(h[:]).MarshalText()
}
// BytesToHash sets b to hash.
// If b is larger than len(h), b will be cropped from the left.
func BytesToHash(b []byte) Hash {
@ -78,3 +97,34 @@ func BytesToHash(b []byte) Hash {
h.SetBytes(b)
return h
}
// UnmarshalFixedJSON decodes the input as a string with 0x prefix. The length of out
// determines the required input length. This function is commonly used to implement the
// UnmarshalJSON method for fixed-size types.
func UnmarshalFixedJSON(typ reflect.Type, input, out []byte) error {
if !isString(input) {
return errNonString(typ)
}
return wrapTypeError(UnmarshalFixedText(typ.String(), input[1:len(input)-1], out), typ)
}
// UnmarshalFixedText decodes the input as a string with 0x prefix. The length of out
// determines the required input length. This function is commonly used to implement the
// UnmarshalText method for fixed-size types.
func UnmarshalFixedText(typname string, input, out []byte) error {
raw, err := checkText(input, true)
if err != nil {
return err
}
if len(raw)/2 != len(out) {
return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname)
}
// Pre-verify syntax before modifying out.
for _, b := range raw {
if decodeNibble(b) == badNibble {
return ErrSyntax
}
}
_, err = hex.Decode(out, raw)
return err
}