1 /* Deals with parsing Manifest Text. */
3 // Inspired by the Manifest class in arvados/sdk/ruby/lib/arvados/keep.rb
16 var LocatorPattern = regexp.MustCompile(
17 "^[0-9a-fA-F]{32}\\+[0-9]+(\\+[A-Z][A-Za-z0-9@_-]+)*$")
19 type Manifest struct {
23 type BlockLocator struct {
29 type ManifestLine struct {
35 func parseBlockLocator(s string) (b BlockLocator, err error) {
36 if !LocatorPattern.MatchString(s) {
37 err = fmt.Errorf("String \"%s\" does not match BlockLocator pattern " +
40 LocatorPattern.String())
42 tokens := strings.Split(s, "+")
44 // We expect ParseInt to succeed since LocatorPattern restricts
45 // tokens[1] to contain exclusively digits.
46 blockSize, err = strconv.ParseInt(tokens[1], 10, 0)
49 b.Size = int(blockSize)
56 func parseManifestLine(s string) (m ManifestLine) {
57 tokens := strings.Split(s, " ")
58 m.StreamName = tokens[0]
61 for i = range tokens {
62 if !LocatorPattern.MatchString(tokens[i]) {
71 func (m *Manifest) LineIter() <-chan ManifestLine {
72 ch := make(chan ManifestLine)
73 go func(input string) {
74 scanner := bufio.NewScanner(strings.NewReader(input))
76 // We parse one line at a time, to save effort if we only need
77 // the first few lines.
78 ch <- parseManifestLine(scanner.Text())
86 // Blocks may appear mulitple times within the same manifest if they
87 // are used by multiple files. In that case this Iterator will output
88 // the same block multiple times.
89 func (m *Manifest) BlockIterWithDuplicates() <-chan BlockLocator {
90 blockChannel := make(chan BlockLocator)
91 go func(lineChannel <-chan ManifestLine) {
92 for m := range lineChannel {
93 for _, block := range m.Blocks {
94 if b, err := parseBlockLocator(block); err == nil {
97 log.Printf("ERROR: Failed to parse block: %v", err)