Arvados-DCO-1.1-Signed-off-by: Radhika Chippada <radhika@curoverse.com>
[arvados.git] / sdk / go / blockdigest / blockdigest.go
index 9b818d365303ac6805c15be534400a0c3c854448..b9ecc45abc6a29d6d92642f41efcd26689457d52 100644 (file)
@@ -1,22 +1,44 @@
-/* Stores a Block Locator Digest compactly. Can be used as a map key. */
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: Apache-2.0
 
+// Stores a Block Locator Digest compactly. Can be used as a map key.
 package blockdigest
 
 import (
        "fmt"
-       "log"
+       "regexp"
        "strconv"
+       "strings"
 )
 
+var LocatorPattern = regexp.MustCompile(
+       "^[0-9a-fA-F]{32}\\+[0-9]+(\\+[A-Z][A-Za-z0-9@_-]*)*$")
+
 // Stores a Block Locator Digest compactly, up to 128 bits.
 // Can be used as a map key.
 type BlockDigest struct {
-       h uint64
-       l uint64
+       H uint64
+       L uint64
+}
+
+type DigestWithSize struct {
+       Digest BlockDigest
+       Size   uint32
+}
+
+type BlockLocator struct {
+       Digest BlockDigest
+       Size   int
+       Hints  []string
 }
 
 func (d BlockDigest) String() string {
-       return fmt.Sprintf("%016x%016x", d.h, d.l)
+       return fmt.Sprintf("%016x%016x", d.H, d.L)
+}
+
+func (w DigestWithSize) String() string {
+       return fmt.Sprintf("%s+%d", w.Digest.String(), w.Size)
 }
 
 // Will create a new BlockDigest unless an error is encountered.
@@ -27,11 +49,11 @@ func FromString(s string) (dig BlockDigest, err error) {
        }
 
        var d BlockDigest
-       d.h, err = strconv.ParseUint(s[:16], 16, 64)
+       d.H, err = strconv.ParseUint(s[:16], 16, 64)
        if err != nil {
                return
        }
-       d.l, err = strconv.ParseUint(s[16:], 16, 64)
+       d.L, err = strconv.ParseUint(s[16:], 16, 64)
        if err != nil {
                return
        }
@@ -39,11 +61,33 @@ func FromString(s string) (dig BlockDigest, err error) {
        return
 }
 
-// Will fatal with the error if an error is encountered
-func AssertFromString(s string) BlockDigest {
-       d, err := FromString(s)
-       if err != nil {
-               log.Fatalf("Error creating BlockDigest from %s: %v", s, err)
+func IsBlockLocator(s string) bool {
+       return LocatorPattern.MatchString(s)
+}
+
+func ParseBlockLocator(s string) (b BlockLocator, err error) {
+       if !LocatorPattern.MatchString(s) {
+               err = fmt.Errorf("String \"%s\" does not match BlockLocator pattern "+
+                       "\"%s\".",
+                       s,
+                       LocatorPattern.String())
+       } else {
+               tokens := strings.Split(s, "+")
+               var blockSize int64
+               var blockDigest BlockDigest
+               // We expect both of the following to succeed since LocatorPattern
+               // restricts the strings appropriately.
+               blockDigest, err = FromString(tokens[0])
+               if err != nil {
+                       return
+               }
+               blockSize, err = strconv.ParseInt(tokens[1], 10, 0)
+               if err != nil {
+                       return
+               }
+               b.Digest = blockDigest
+               b.Size = int(blockSize)
+               b.Hints = tokens[2:]
        }
-       return d
+       return
 }