file-store/pkg/erasureencode/main.go
2022-08-23 21:56:32 -05:00

98 lines
2.2 KiB
Go

package erasureencode
import (
"crypto/sha256"
"encoding/base64"
"encoding/json"
"fmt"
)
type EEMeta 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
}