1
1
mirror of https://github.com/wader/fq.git synced 2024-12-28 08:02:28 +03:00
fq/format/yaml/yaml.go
2023-05-01 13:19:04 +02:00

71 lines
1.3 KiB
Go

package yaml
// TODO: yaml type eval? walk eval?
import (
"embed"
"errors"
"io"
"github.com/wader/fq/format"
"github.com/wader/fq/internal/gojqex"
"github.com/wader/fq/pkg/bitio"
"github.com/wader/fq/pkg/decode"
"github.com/wader/fq/pkg/interp"
"github.com/wader/fq/pkg/scalar"
"gopkg.in/yaml.v3"
)
//go:embed yaml.jq
var yamlFS embed.FS
func init() {
interp.RegisterFormat(
format.YAML,
&decode.Format{
Description: "YAML Ain't Markup Language",
ProbeOrder: format.ProbeOrderTextFuzzy,
Groups: []*decode.Group{format.Probe},
DecodeFn: decodeYAML,
Functions: []string{"_todisplay"},
})
interp.RegisterFS(yamlFS)
interp.RegisterFunc0("to_yaml", toYAML)
}
func decodeYAML(d *decode.D) any {
br := d.RawLen(d.Len())
var r any
yd := yaml.NewDecoder(bitio.NewIOReader(br))
if err := yd.Decode(&r); err != nil {
d.Fatalf("%s", err)
}
if err := yd.Decode(new(any)); !errors.Is(err, io.EOF) {
d.Fatalf("trialing data after top-level value")
}
var s scalar.Any
s.Actual = gojqex.Normalize(r)
switch s.Actual.(type) {
case map[string]any,
[]any:
default:
d.Fatalf("root not object or array")
}
d.Value.V = &s
d.Value.Range.Len = d.Len()
return nil
}
func toYAML(_ *interp.Interp, c any) any {
b, err := yaml.Marshal(gojqex.Normalize(c))
if err != nil {
return err
}
return string(b)
}