diff options
Diffstat (limited to 'lib/btrfsprogs/btrfsinspect')
-rw-r--r-- | lib/btrfsprogs/btrfsinspect/csums.go | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/lib/btrfsprogs/btrfsinspect/csums.go b/lib/btrfsprogs/btrfsinspect/csums.go index 78bf915..6335cb9 100644 --- a/lib/btrfsprogs/btrfsinspect/csums.go +++ b/lib/btrfsprogs/btrfsinspect/csums.go @@ -6,7 +6,11 @@ package btrfsinspect import ( "context" + "fmt" "io" + "strings" + + "git.lukeshu.com/go/lowmemjson" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsitem" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol" @@ -17,6 +21,82 @@ import ( type ShortSum string +var ( + _ lowmemjson.Encodable = ShortSum("") + _ lowmemjson.Decodable = (*ShortSum)(nil) +) + +func (sum ShortSum) EncodeJSON(w io.Writer) error { + const hextable = "0123456789abcdef" + var buf [2]byte + buf[0] = '"' + if _, err := w.Write(buf[:1]); err != nil { + return err + } + for i := 0; i < len(sum); i++ { + buf[0] = hextable[sum[i]>>4] + buf[1] = hextable[sum[i]&0x0f] + if _, err := w.Write(buf[:]); err != nil { + return err + } + } + buf[0] = '"' + if _, err := w.Write(buf[:1]); err != nil { + return err + } + return nil +} + +func deHex(r rune) (byte, bool) { + if r > 0xff { + return 0, false + } + c := byte(r) + switch { + case '0' <= c && c <= '9': + return c - '0', true + case 'a' <= c && c <= 'f': + return c - 'a' + 10, true + case 'A' <= c && c <= 'F': + return c - 'A' + 10, true + default: + return 0, false + } +} + +func (sum *ShortSum) DecodeJSON(r io.RuneScanner) error { + var out strings.Builder + if c, _, err := r.ReadRune(); err != nil { + return err + } else if c != '"' { + return fmt.Errorf("expected %q, got %q", '"', c) + } + for { + a, _, err := r.ReadRune() + if err != nil { + return err + } + if a == '"' { + break + } + aN, ok := deHex(a) + if !ok { + return fmt.Errorf("expected a hex digit, got %q", a) + } + b, _, err := r.ReadRune() + if err != nil { + return err + } + bN, ok := deHex(b) + if !ok { + return fmt.Errorf("expected a hex digit, got %q", b) + } + out.WriteByte(aN<<4 | bN) + } + *sum = ShortSum(out.String()) + return nil +} + // SumRun //////////////////////////////////////////////////////////// type SumRun[Addr btrfsvol.IntAddr[Addr]] struct { |