blob: 80c19b9f2dd78baa4535bdb57175dc74a426b835 [file] [log] [blame]
Marcel van Lohuizen4e5b69a2019-07-14 21:24:00 +02001// Copyright 2019 The CUE Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// Package yaml converts YAML encodings to and from CUE. When converting to CUE,
16// comments and position information are retained.
17package yaml
18
19import (
20 "bytes"
21 "io"
22
23 "cuelang.org/go/cue"
24 "cuelang.org/go/cue/ast"
Marcel van Lohuizencf727962020-02-26 13:01:52 +010025 cueyaml "cuelang.org/go/internal/encoding/yaml"
Marcel van Lohuizen4e5b69a2019-07-14 21:24:00 +020026 "cuelang.org/go/internal/third_party/yaml"
Marcel van Lohuizen41cce522019-08-21 15:56:29 +020027 pkgyaml "cuelang.org/go/pkg/encoding/yaml"
Marcel van Lohuizen4e5b69a2019-07-14 21:24:00 +020028)
29
Marcel van Lohuizen4e5b69a2019-07-14 21:24:00 +020030// Extract parses the YAML to a CUE expression. Streams are returned as a list
31// of the streamed values.
32func Extract(filename string, src interface{}) (*ast.File, error) {
33 a := []ast.Expr{}
34 d, err := yaml.NewDecoder(filename, src)
35 if err != nil {
36 return nil, err
37 }
38 for {
39 expr, err := d.Decode()
40 if err == io.EOF {
41 break
42 }
43 if err != nil {
44 return nil, err
45 }
46 a = append(a, expr)
47 }
48 f := &ast.File{Filename: filename}
49 switch len(a) {
50 case 0:
51 case 1:
52 switch x := a[0].(type) {
53 case *ast.StructLit:
54 f.Decls = x.Elts
55 default:
Marcel van Lohuizen2463e2d2019-07-21 12:58:34 +020056 f.Decls = []ast.Decl{&ast.EmbedDecl{Expr: x}}
Marcel van Lohuizen4e5b69a2019-07-14 21:24:00 +020057 }
58 default:
Marcel van Lohuizen2463e2d2019-07-21 12:58:34 +020059 f.Decls = []ast.Decl{&ast.EmbedDecl{Expr: &ast.ListLit{Elts: a}}}
Marcel van Lohuizen4e5b69a2019-07-14 21:24:00 +020060 }
61 return f, nil
62}
63
64// Decode converts a YAML file to a CUE value. Streams are returned as a list
65// of the streamed values.
66func Decode(r *cue.Runtime, filename string, src interface{}) (*cue.Instance, error) {
67 file, err := Extract(filename, src)
68 if err != nil {
69 return nil, err
70 }
71 return r.CompileFile(file)
72}
73
74// Encode returns the YAML encoding of v.
75func Encode(v cue.Value) ([]byte, error) {
Marcel van Lohuizencf727962020-02-26 13:01:52 +010076 n := v.Syntax(cue.Final())
77 b, err := cueyaml.Encode(n)
Marcel van Lohuizen4e5b69a2019-07-14 21:24:00 +020078 return b, err
79}
80
81// EncodeStream returns the YAML encoding of iter, where consecutive values
82// of iter are separated with a `---`.
83func EncodeStream(iter cue.Iterator) ([]byte, error) {
84 // TODO: return an io.Reader and allow asynchronous processing.
85 buf := &bytes.Buffer{}
86 for i := 0; iter.Next(); i++ {
87 if i > 0 {
88 buf.WriteString("---\n")
89 }
Marcel van Lohuizencf727962020-02-26 13:01:52 +010090 n := iter.Value().Syntax(cue.Final())
91 b, err := cueyaml.Encode(n)
Marcel van Lohuizen4e5b69a2019-07-14 21:24:00 +020092 if err != nil {
93 return nil, err
94 }
95 buf.Write(b)
96 }
97 return buf.Bytes(), nil
98}
Marcel van Lohuizen41cce522019-08-21 15:56:29 +020099
100// Validate validates the YAML and confirms it matches the constraints
101// specified by v. For YAML streams, all values must match v.
102func Validate(b []byte, v cue.Value) error {
103 _, err := pkgyaml.Validate(b, v)
104 return err
105}