From 9e44c7e51e63df42a984b278bc6c213c2abb7b9c Mon Sep 17 00:00:00 2001 From: Andrea Maria Piana Date: Sat, 2 Nov 2019 09:46:37 +0100 Subject: [PATCH] Marshal json hash --- types/hash.go | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/types/hash.go b/types/hash.go index df30452..bde4cda 100644 --- a/types/hash.go +++ b/types/hash.go @@ -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 +}