21891: Remove unused sdk/go/manifest package and ManifestFileReader.
[arvados.git] / sdk / go / blockdigest / blockdigest.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: Apache-2.0
4
5 // Package blockdigest stores a Block Locator Digest compactly. Can be used as a map key.
6 package blockdigest
7
8 import (
9         "fmt"
10         "regexp"
11         "strconv"
12         "strings"
13 )
14
15 var LocatorPattern = regexp.MustCompile(
16         "^[0-9a-fA-F]{32}\\+[0-9]+(\\+[A-Z][A-Za-z0-9@_-]*)*$")
17
18 // BlockDigest stores a Block Locator Digest compactly, up to 128 bits. Can be
19 // used as a map key.
20 type BlockDigest struct {
21         H uint64
22         L uint64
23 }
24
25 type DigestWithSize struct {
26         Digest BlockDigest
27         Size   uint32
28 }
29
30 type BlockLocator struct {
31         Digest BlockDigest
32         Size   int
33         Hints  []string
34 }
35
36 func (d BlockDigest) String() string {
37         return fmt.Sprintf("%016x%016x", d.H, d.L)
38 }
39
40 func (w DigestWithSize) String() string {
41         return fmt.Sprintf("%s+%d", w.Digest.String(), w.Size)
42 }
43
44 // FromString creates a new BlockDigest unless an error is encountered.
45 func FromString(s string) (dig BlockDigest, err error) {
46         if len(s) != 32 {
47                 err = fmt.Errorf("Block digest should be exactly 32 characters but this one is %d: %s", len(s), s)
48                 return
49         }
50
51         var d BlockDigest
52         d.H, err = strconv.ParseUint(s[:16], 16, 64)
53         if err != nil {
54                 return
55         }
56         d.L, err = strconv.ParseUint(s[16:], 16, 64)
57         if err != nil {
58                 return
59         }
60         dig = d
61         return
62 }
63
64 func IsBlockLocator(s string) bool {
65         return LocatorPattern.MatchString(s)
66 }
67
68 func ParseBlockLocator(s string) (BlockLocator, error) {
69         if !LocatorPattern.MatchString(s) {
70                 return BlockLocator{}, fmt.Errorf("String %q does not match block locator pattern %q.", s, LocatorPattern.String())
71         }
72         tokens := strings.Split(s, "+")
73         // We expect both of the following to succeed since
74         // LocatorPattern restricts the strings appropriately.
75         blockDigest, err := FromString(tokens[0])
76         if err != nil {
77                 return BlockLocator{}, err
78         }
79         blockSize, err := strconv.ParseInt(tokens[1], 10, 0)
80         if err != nil {
81                 return BlockLocator{}, err
82         }
83         return BlockLocator{
84                 Digest: blockDigest,
85                 Size:   int(blockSize),
86                 Hints:  tokens[2:],
87         }, nil
88 }