cue-lang / cue

The home of the CUE language! Validate and define text-based and dynamic configuration
https://cuelang.org
Apache License 2.0
5.02k stars 287 forks source link

encoding/yaml: encoder that receives an io.Writer #1351

Open nyarly opened 2 years ago

nyarly commented 2 years ago

Building a Go tool emit multiple files, I need to be able to emit JSON and YAML based on CUE values.

For JSON, I have

func writeJSON(path string, v cue.Value) error {
    f, err := os.Create(path)
    if err != nil {
        return err
    }
    defer f.Close()

    enc := json.NewEncoder(f)
    enc.SetIndent("", "    ")
    return enc.Encode(v)
}

(just using Go's encoding/json)

For YAML it's like

import "cuelang.org/go/pkg/encoding/yaml"

// notionally:
// function writeYAML(path string, v cue.Value) error {
// but I'm assembling from my code
str, err := yaml.Marshal(v)
if err != nil {
  return err
}
bs := []byte(str)
f, err := os.Create(path)
if err != nil {
    return err
}
defer f.Close()

_, err = f.Write(bs)    
}

It'd be great to have a streaming YAML encoder. I think encoding a string, converting to bytes, and then writing is probably not my biggest performance problem, but it couldn't hurt.

myitcv commented 2 years ago

@nyarly did you perhaps mean to reference https://pkg.go.dev/cuelang.org/go@v0.4.0/encoding/yaml above? cuelang.org/go/pkg/encoding/yaml is definition of the builtin package encoding/yaml.

nyarly commented 2 years ago

I'd found the pkg implementation and was using that. The nice thing about using Encode is that it would be a []byte value already, so we can save a conversion.

Being able to stream the output remains a (perhaps only aesthetic) benefit.

myitcv commented 2 years ago

Indeed. The pattern from encoding/json of being able to create encoders/decoders that effectively wrap an io.{Reader,Writer} makes sense. Any such implementation would however live in the encoding/yaml package, not the builtin pkg/encoding/yaml.