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
}
|