-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbind.go
More file actions
63 lines (56 loc) · 2.05 KB
/
Copy pathbind.go
File metadata and controls
63 lines (56 loc) · 2.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package fastconf
import (
"context"
"errors"
"fmt"
"github.com/fastabc/fastconf/codec"
"github.com/fastabc/fastconf/contracts"
)
// ErrParserUnknown is returned by a bound Source/Parser composite when
// no Parser was supplied to Bind and the Source's content-type hint
// did not match any registered Parser. The error is observed at the
// first Load() call, not at Bind time, because content-types may be
// runtime-discovered (e.g. HTTP Content-Type header).
var ErrParserUnknown = errors.New("fastconf: no parser for source content-type")
// Bind composes a byte-stream Source with a Parser into a
// contracts.Provider that the reload pipeline can consume. The
// returned Provider forwards Name/Priority/Watch to the Source and
// runs Source.Read + Parser.Decode on Load.
//
// If parser is nil, the framework attempts to resolve a Parser from
// the parser registry using the content-type hint returned by
// Source.Read. The lookup is deferred to Load() so that Sources whose
// content-type is only known at runtime (HTTP Content-Type response
// header, magic-byte detection, ...) work without ceremony. If
// neither an explicit Parser nor a registry match resolves a Parser
// by Load time, Load returns ErrParserUnknown.
func Bind(src contracts.Source, p contracts.Parser) contracts.Provider {
return &boundSource{src: src, parser: p}
}
type boundSource struct {
src contracts.Source
parser contracts.Parser
}
func (b *boundSource) Name() string { return b.src.Name() }
func (b *boundSource) Priority() int { return b.src.Priority() }
func (b *boundSource) Load(ctx context.Context) (map[string]any, error) {
data, ct, _, err := b.src.Read(ctx)
if err != nil {
return nil, err
}
if len(data) == 0 {
return map[string]any{}, nil
}
p := b.parser
if p == nil {
var ok bool
p, ok = codec.LookupParser(ct)
if !ok {
return nil, fmt.Errorf("%w: source %q content-type %q", ErrParserUnknown, b.src.Name(), ct)
}
}
return p.Decode(data)
}
func (b *boundSource) Watch(ctx context.Context) (<-chan contracts.Event, error) {
return b.src.Watch(ctx)
}