package meta import ( "crypto/sha256" "encoding/base64" "encoding/json" "fmt" ) type Meta struct { Params Name string `json:"name"` ShardMerkle FileHash `json:"shardMerkle"` ShardHashes HashList `json:"shardHashes"` ParityMerkle FileHash `json:"parityMerkle"` ParityHashes HashList `json:"parityHashes"` } type FileHash []byte func (hash FileHash) MarshalJSON() ([]byte, error) { text, err := hash.MarshalText() if err != nil { return nil, err } return json.Marshal(string(text)) } func (hash FileHash) MarshalText() ([]byte, error) { return []byte(base64.StdEncoding.EncodeToString(hash)), nil } func (hash *FileHash) UnmarshalJSON(data []byte) error { s := "" json.Unmarshal(data, &s) return hash.UnmarshalText([]byte(s)) } func (hash *FileHash) UnmarshalText(text []byte) error { raw, err := base64.StdEncoding.DecodeString(string(text)) if err != nil { return err } if len(raw) != sha256.Size { return fmt.Errorf("expected hash to be %d bytes (got %d)", sha256.Size, len(raw)) } *hash = raw return nil } type HashList [][]byte func (hashes HashList) MarshalJSON() ([]byte, error) { text, err := hashes.MarshalText() if err != nil { return nil, err } return json.Marshal(string(text)) } func (hashes HashList) MarshalText() ([]byte, error) { // fmt.Printf("marshal hash list...\n") hashesLen := len(hashes) hashLen := 0 dataLen := 0 if hashesLen != 0 { hashLen = len(hashes[0]) dataLen = hashesLen * hashLen } data := make([]byte, dataLen) for i, hash := range hashes { copy(data[i*hashLen:], hash) } return []byte(base64.StdEncoding.EncodeToString(data)), nil } func (hashes *HashList) UnmarshalJSON(data []byte) error { s := "" json.Unmarshal(data, &s) return hashes.UnmarshalText([]byte(s)) } func (hashes *HashList) UnmarshalText(text []byte) error { raw, err := base64.StdEncoding.DecodeString(string(text)) if err != nil { return err } if len(raw)%sha256.Size != 0 { return fmt.Errorf("expected hash list to be multiple of %d bytes", sha256.Size) } split := make([][]byte, len(raw)/sha256.Size) for i := 0; i < len(raw); i += sha256.Size { split[i/sha256.Size] = raw[i : i+sha256.Size] } *hashes = split return nil }