-
-
Notifications
You must be signed in to change notification settings - Fork 135
/
parser.go
135 lines (117 loc) · 3.75 KB
/
parser.go
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package storage
import (
"fmt"
"io"
"os"
"path/filepath"
"strings"
"github.com/tomwright/dasel/v2"
)
var readParsersByExtension = map[string]ReadParser{}
var writeParsersByExtension = map[string]WriteParser{}
var readParsersByName = map[string]ReadParser{}
var writeParsersByName = map[string]WriteParser{}
func registerReadParser(names []string, extensions []string, parser ReadParser) {
for _, n := range names {
readParsersByName[n] = parser
}
for _, e := range extensions {
readParsersByExtension[e] = parser
}
}
func registerWriteParser(names []string, extensions []string, parser WriteParser) {
for _, n := range names {
writeParsersByName[n] = parser
}
for _, e := range extensions {
writeParsersByExtension[e] = parser
}
}
// UnknownParserErr is returned when an invalid parser name is given.
type UnknownParserErr struct {
Parser string
}
func (e UnknownParserErr) Is(other error) bool {
_, ok := other.(*UnknownParserErr)
return ok
}
// Error returns the error message.
func (e UnknownParserErr) Error() string {
return fmt.Sprintf("unknown parser: %s", e.Parser)
}
// ReadParser can be used to convert bytes to data.
type ReadParser interface {
// FromBytes returns some data that is represented by the given bytes.
FromBytes(byteData []byte, options ...ReadWriteOption) (dasel.Value, error)
}
// WriteParser can be used to convert data to bytes.
type WriteParser interface {
// ToBytes returns a slice of bytes that represents the given value.
ToBytes(value dasel.Value, options ...ReadWriteOption) ([]byte, error)
}
// Parser can be used to load and save files from/to disk.
type Parser interface {
ReadParser
WriteParser
}
// NewReadParserFromFilename returns a ReadParser from the given filename.
func NewReadParserFromFilename(filename string) (ReadParser, error) {
ext := strings.ToLower(filepath.Ext(filename))
p, ok := readParsersByExtension[ext]
if !ok {
return nil, &UnknownParserErr{Parser: ext}
}
return p, nil
}
// NewReadParserFromString returns a ReadParser from the given parser name.
func NewReadParserFromString(parser string) (ReadParser, error) {
p, ok := readParsersByName[parser]
if !ok {
return nil, &UnknownParserErr{Parser: parser}
}
return p, nil
}
// NewWriteParserFromFilename returns a WriteParser from the given filename.
func NewWriteParserFromFilename(filename string) (WriteParser, error) {
ext := strings.ToLower(filepath.Ext(filename))
p, ok := writeParsersByExtension[ext]
if !ok {
return nil, &UnknownParserErr{Parser: ext}
}
return p, nil
}
// NewWriteParserFromString returns a WriteParser from the given parser name.
func NewWriteParserFromString(parser string) (WriteParser, error) {
p, ok := writeParsersByName[parser]
if !ok {
return nil, &UnknownParserErr{Parser: parser}
}
return p, nil
}
// LoadFromFile loads data from the given file.
func LoadFromFile(filename string, p ReadParser, options ...ReadWriteOption) (dasel.Value, error) {
f, err := os.Open(filename)
if err != nil {
return dasel.Value{}, fmt.Errorf("could not open file for reading: %w", err)
}
return Load(p, f, options...)
}
// Load loads data from the given io.Reader.
func Load(p ReadParser, reader io.Reader, options ...ReadWriteOption) (dasel.Value, error) {
byteData, err := io.ReadAll(reader)
if err != nil {
return dasel.Value{}, fmt.Errorf("could not read data: %w", err)
}
return p.FromBytes(byteData, options...)
}
// Write writes the value to the given io.Writer.
func Write(p WriteParser, value dasel.Value, writer io.Writer, options ...ReadWriteOption) error {
byteData, err := p.ToBytes(value, options...)
if err != nil {
return fmt.Errorf("could not get byte data for file: %w", err)
}
if _, err := writer.Write(byteData); err != nil {
return fmt.Errorf("could not write data: %w", err)
}
return nil
}