encoding/yaml: expose internal yaml functionality
Only the plain function API is exposed for now.
The Decoder and Encoder are still to be done.
Change-Id: I7e003c59c2dc3bd89896336fc24a7ace39cc5f92
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/2564
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/encoding/yaml/yaml.go b/encoding/yaml/yaml.go
new file mode 100644
index 0000000..3db8b08
--- /dev/null
+++ b/encoding/yaml/yaml.go
@@ -0,0 +1,100 @@
+// Copyright 2019 The CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package yaml converts YAML encodings to and from CUE. When converting to CUE,
+// comments and position information are retained.
+package yaml
+
+import (
+ "bytes"
+ "io"
+
+ "cuelang.org/go/cue"
+ "cuelang.org/go/cue/ast"
+ "cuelang.org/go/internal/third_party/yaml"
+ goyaml "github.com/ghodss/yaml"
+)
+
+// TODO: replace the ghodss YAML encoder. It has a few major issues:
+// - it does not expose the underlying error, which means we lose valuable
+// information.
+// - comments and other meta data are lost.
+
+// Extract parses the YAML to a CUE expression. Streams are returned as a list
+// of the streamed values.
+func Extract(filename string, src interface{}) (*ast.File, error) {
+ a := []ast.Expr{}
+ d, err := yaml.NewDecoder(filename, src)
+ if err != nil {
+ return nil, err
+ }
+ for {
+ expr, err := d.Decode()
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return nil, err
+ }
+ a = append(a, expr)
+ }
+ f := &ast.File{Filename: filename}
+ switch len(a) {
+ case 0:
+ case 1:
+ switch x := a[0].(type) {
+ case *ast.StructLit:
+ f.Decls = x.Elts
+ default:
+ f.Decls = []ast.Decl{&ast.EmitDecl{Expr: x}}
+ }
+ default:
+ f.Decls = []ast.Decl{&ast.EmitDecl{Expr: &ast.ListLit{Elts: a}}}
+ }
+ return f, nil
+}
+
+// Decode converts a YAML file to a CUE value. Streams are returned as a list
+// of the streamed values.
+func Decode(r *cue.Runtime, filename string, src interface{}) (*cue.Instance, error) {
+ file, err := Extract(filename, src)
+ if err != nil {
+ return nil, err
+ }
+ return r.CompileFile(file)
+}
+
+// Encode returns the YAML encoding of v.
+func Encode(v cue.Value) ([]byte, error) {
+ b, err := goyaml.Marshal(v)
+ return b, err
+}
+
+// EncodeStream returns the YAML encoding of iter, where consecutive values
+// of iter are separated with a `---`.
+func EncodeStream(iter cue.Iterator) ([]byte, error) {
+ // TODO: return an io.Reader and allow asynchronous processing.
+ buf := &bytes.Buffer{}
+ for i := 0; iter.Next(); i++ {
+ if i > 0 {
+ buf.WriteString("---\n")
+ }
+ b, err := goyaml.Marshal(iter.Value())
+ if err != nil {
+ return nil, err
+ }
+ buf.Write(b)
+ }
+ return buf.Bytes(), nil
+}