ParseMetadata validates and constructs a [Metadata]. See [NewMetadata]. It doesn't allocate.
(source string)
| 70 | // |
| 71 | // It doesn't allocate. |
| 72 | func ParseMetadata(source string) (Metadata, error) { |
| 73 | if err := ValidMetadata(source); err != nil || source == "" { |
| 74 | return Metadata{}, err |
| 75 | } |
| 76 | |
| 77 | remaining := source |
| 78 | if remaining[0] != metadataSeparator { |
| 79 | return Metadata{}, errMalformedMetadata{source: source, reason: fmt.Sprintf("missing '%c' at start", metadataSeparator)} |
| 80 | } |
| 81 | prevKey := "" // < than every other string |
| 82 | for len(remaining) > 0 { |
| 83 | next := strings.IndexByte(remaining[1:], metadataSeparator) |
| 84 | if next < 0 { |
| 85 | next = len(remaining) |
| 86 | } else { |
| 87 | next += 1 // Add back the ':' |
| 88 | } |
| 89 | |
| 90 | kv := remaining[:next] |
| 91 | remaining = remaining[next:] |
| 92 | |
| 93 | key, _, ok := stringsCut(kv, metadataKVSeparator) |
| 94 | if !ok { |
| 95 | return Metadata{}, errMalformedMetadata{source: source, reason: fmt.Sprintf("no key-value separator '%c' in %q", metadataKVSeparator, kv)} |
| 96 | } |
| 97 | if prevKey >= key { |
| 98 | return Metadata{}, errMalformedMetadata{source: source, reason: "keys must be unique and sorted"} |
| 99 | } |
| 100 | prevKey = key |
| 101 | } |
| 102 | return NewMetadata(source), nil |
| 103 | } |
| 104 | |
| 105 | // ValidMetadata returns an error if the metadata is invalid, nil otherwise. |
| 106 | // Metadata must contain only lowercase letters, digits, '-', and '='. |
no test coverage detected