lotus/postfix-config/decoder.go

109 lines
2.3 KiB
Go

package postfix_config
import (
"errors"
"fmt"
commaListScanner "github.com/1f349/lotus/postfix-config/comma-list-scanner"
configParser "github.com/1f349/lotus/postfix-config/config-parser"
mapProvider "github.com/1f349/lotus/postfix-config/map-provider"
"io"
"path/filepath"
"strings"
)
type Decoder struct {
r *configParser.ConfigParser
temp map[string]string
basePath string
}
func NewDecoder(r io.Reader) *Decoder {
return &Decoder{r: configParser.NewConfigParser(r)}
}
func (d *Decoder) Load() error {
for d.r.Scan() {
k, v := d.r.Pair()
d.temp[k] = v
}
if err := d.r.Err(); err != nil {
return err
}
switch d.value.ParseProvider(k) {
case "comma":
m := mapProvider.SequenceMapProvider{}
s := commaListScanner.NewCommaListScanner(strings.NewReader(v))
for s.Scan() {
a := s.Text()
println("a", a)
if strings.HasPrefix(a, "$") {
m = append(m, &mapProvider.Variable{Name: a[1:]})
continue
}
v2, err := d.createValue(a)
if err != nil {
return err
}
m = append(m, v2)
}
if err := s.Err(); err != nil {
return err
}
d.value.SetKey(k, m)
case "union":
if !strings.HasPrefix(v, "unionmap:{") || !strings.HasSuffix(v, "}") {
return errors.New("key requires a union map")
}
v = v[len("unionmap:{") : len(v)-1]
m := mapProvider.SequenceMapProvider{}
s := commaListScanner.NewCommaListScanner(strings.NewReader(v))
for s.Scan() {
a := s.Text()
v2, err := d.createValue(a)
if err != nil {
return err
}
m = append(m, v2)
}
default:
return fmt.Errorf("key '%s' has no defined parse provider", k)
}
}
return d.r.Err()
}
func (d *Decoder) createValue(a string) (mapProvider.MapProvider, error) {
n := strings.IndexByte(a, ':')
if n == -1 {
return nil, fmt.Errorf("missing prefix")
}
namespace := a[:n]
value := a[n+1:]
switch namespace {
case "mysql":
if !filepath.IsAbs(value) {
value = filepath.Join(d.basePath, value)
}
provider, err := mapProvider.NewMySqlMapProvider(value)
if err != nil {
return nil, err
}
return provider, nil
case "hash":
if !filepath.IsAbs(value) {
value = filepath.Join(d.basePath, value)
}
provider, err := mapProvider.NewHashMapProvider(value)
if err != nil {
return nil, err
}
return provider, nil
}
return nil, errors.New("invalid provider namespace")
}