20c8d6c413
Co-authored-by: Dominik Menke <git@dmke.org>
131 lines
1.9 KiB
Go
131 lines
1.9 KiB
Go
package selfhostde
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
const (
|
|
lineSep = ","
|
|
recordSep = ":"
|
|
)
|
|
|
|
type Seq struct {
|
|
cursor int
|
|
ids []string
|
|
}
|
|
|
|
func NewSeq(ids ...string) *Seq {
|
|
return &Seq{ids: ids}
|
|
}
|
|
|
|
func (s *Seq) Next() string {
|
|
if len(s.ids) == 1 {
|
|
return s.ids[0]
|
|
}
|
|
|
|
v := s.ids[s.cursor]
|
|
|
|
if s.cursor < len(s.ids)-1 {
|
|
s.cursor++
|
|
} else {
|
|
s.cursor = 0
|
|
}
|
|
|
|
return v
|
|
}
|
|
|
|
func parseRecordsMapping(raw string) (map[string]*Seq, error) {
|
|
raw = strings.ReplaceAll(raw, " ", "")
|
|
|
|
if raw == "" {
|
|
return nil, errors.New("empty mapping")
|
|
}
|
|
|
|
acc := map[string]*Seq{}
|
|
|
|
for {
|
|
index, err := safeIndex(raw, lineSep)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if index != -1 {
|
|
name, seq, err := parseLine(raw[:index])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
acc[name] = seq
|
|
|
|
// Data for the next iteration.
|
|
raw = raw[index+1:]
|
|
|
|
continue
|
|
}
|
|
|
|
name, seq, errP := parseLine(raw)
|
|
if errP != nil {
|
|
return nil, errP
|
|
}
|
|
|
|
acc[name] = seq
|
|
|
|
return acc, nil
|
|
}
|
|
}
|
|
|
|
func parseLine(line string) (string, *Seq, error) {
|
|
idx, err := safeIndex(line, recordSep)
|
|
if err != nil {
|
|
return "", nil, err
|
|
}
|
|
|
|
if idx == -1 {
|
|
return "", nil, fmt.Errorf("missing %q: %s", recordSep, line)
|
|
}
|
|
|
|
name, rawIDs := line[:idx], line[idx+1:]
|
|
|
|
var ids []string
|
|
var count int
|
|
|
|
for {
|
|
idx, err = safeIndex(rawIDs, recordSep)
|
|
if err != nil {
|
|
return "", nil, err
|
|
}
|
|
|
|
if count == 2 {
|
|
return "", nil, fmt.Errorf("too many record IDs for one domain: %s", line)
|
|
}
|
|
|
|
if idx != -1 {
|
|
ids = append(ids, rawIDs[:idx])
|
|
count++
|
|
|
|
// Data for the next iteration.
|
|
rawIDs = rawIDs[idx+1:]
|
|
|
|
continue
|
|
}
|
|
|
|
ids = append(ids, rawIDs)
|
|
|
|
return name, NewSeq(ids...), nil
|
|
}
|
|
}
|
|
|
|
func safeIndex(v, sep string) (int, error) {
|
|
index := strings.Index(v, sep)
|
|
if index == 0 {
|
|
return 0, fmt.Errorf("first char is %q: %s", sep, v)
|
|
}
|
|
|
|
if index == len(v)-1 {
|
|
return 0, fmt.Errorf("last char is %q: %s", sep, v)
|
|
}
|
|
|
|
return index, nil
|
|
}
|