1
1
mirror of https://github.com/wader/fq.git synced 2024-12-25 22:34:14 +03:00
fq/format/registry/registry.go
2021-09-28 13:04:51 +02:00

116 lines
2.2 KiB
Go

package registry
import (
"errors"
"fmt"
"sort"
"sync"
"github.com/wader/fq/pkg/decode"
)
type Registry struct {
Groups map[string][]*decode.Format
resolveOnce sync.Once
resolved bool
}
func New() *Registry {
return &Registry{
Groups: map[string][]*decode.Format{},
resolveOnce: sync.Once{},
}
}
func (r *Registry) register(groupName string, format *decode.Format, single bool) *decode.Format { //nolint:unparam
if r.resolved {
// for now can't change after resolved
panic("registry already resolved")
}
formats, ok := r.Groups[groupName]
if ok {
if !single {
panic(fmt.Sprintf("%s: format already registered", groupName))
}
} else {
formats = []*decode.Format{}
}
r.Groups[groupName] = append(formats, format)
return format
}
func (r *Registry) MustRegister(format *decode.Format) *decode.Format {
r.register(format.Name, format, false)
for _, g := range format.Groups {
r.register(g, format, true)
}
r.register("all", format, true)
return format
}
func sortFormats(fs []*decode.Format) {
sort.Slice(fs, func(i, j int) bool {
if fs[i].ProbeOrder == fs[j].ProbeOrder {
return fs[i].Name < fs[j].Name
}
return fs[i].ProbeOrder < fs[j].ProbeOrder
})
}
func (r *Registry) resolve() error {
for _, fs := range r.Groups {
for _, f := range fs {
for _, d := range f.Dependencies {
var formats []*decode.Format
for _, dName := range d.Names {
df, ok := r.Groups[dName]
if !ok {
return fmt.Errorf("%s: can't find format dependency %s", f.Name, dName)
}
formats = append(formats, df...)
}
sortFormats(formats)
*d.Formats = formats
}
}
}
for _, fs := range r.Groups {
sortFormats(fs)
}
r.resolved = true
return nil
}
func (r *Registry) Group(name string) ([]*decode.Format, error) {
r.resolveOnce.Do(func() {
if err := r.resolve(); err != nil {
panic(err)
}
})
if g, ok := r.Groups[name]; ok {
return g, nil
}
return nil, errors.New("format group not found")
}
func (r *Registry) MustGroup(name string) []*decode.Format {
g, err := r.Group(name)
if err == nil {
return g
}
panic(err)
}
func (r *Registry) MustAll() []*decode.Format {
return r.MustGroup("all")
}