cuelang.org/go@v0.10.1/internal/third_party/yaml/yaml.go (about)

     1  // Package yaml implements YAML support for the Go language.
     2  //
     3  // Source code and other details for the project are available at GitHub:
     4  //
     5  //	https://github.com/go-yaml/yaml
     6  package yaml
     7  
     8  import (
     9  	"fmt"
    10  	"io"
    11  	"strconv"
    12  	"strings"
    13  
    14  	"cuelang.org/go/cue/ast"
    15  )
    16  
    17  // Unmarshal decodes the first document found within the in byte slice
    18  // and returns it as a CUE syntax AST.
    19  func Unmarshal(filename string, in []byte) (expr ast.Expr, err error) {
    20  	return unmarshal(filename, in)
    21  }
    22  
    23  // A Decoder reads and decodes YAML values from an input stream.
    24  type Decoder struct {
    25  	strict    bool
    26  	firstDone bool
    27  	parser    *parser
    28  }
    29  
    30  // NewDecoder returns a new decoder that reads from r.
    31  //
    32  // The decoder introduces its own buffering and may read
    33  // data from r beyond the YAML values requested.
    34  func NewDecoder(filename string, src interface{}) (*Decoder, error) {
    35  	d, err := newParser(filename, src)
    36  	if err != nil {
    37  		return nil, err
    38  	}
    39  	return &Decoder{parser: d}, nil
    40  }
    41  
    42  // Decode reads the next YAML-encoded value from its input and returns
    43  // it as CUE syntax. It returns io.EOF if there are no more value in the
    44  // stream.
    45  func (dec *Decoder) Decode() (expr ast.Expr, err error) {
    46  	d := newDecoder(dec.parser)
    47  	defer handleErr(&err)
    48  	node := dec.parser.parse()
    49  	if node == nil {
    50  		if !dec.firstDone {
    51  			expr = ast.NewNull()
    52  		}
    53  		return expr, io.EOF
    54  	}
    55  	dec.firstDone = true
    56  	expr = d.unmarshal(node)
    57  	if len(d.terrors) > 0 {
    58  		return nil, &TypeError{d.terrors}
    59  	}
    60  	return expr, nil
    61  }
    62  
    63  func unmarshal(filename string, in []byte) (expr ast.Expr, err error) {
    64  	defer handleErr(&err)
    65  	p, err := newParser(filename, in)
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  	defer p.destroy()
    70  	node := p.parse()
    71  	d := newDecoder(p)
    72  	if node != nil {
    73  		expr = d.unmarshal(node)
    74  	}
    75  	if len(d.terrors) > 0 {
    76  		return nil, &TypeError{d.terrors}
    77  	}
    78  	return expr, nil
    79  }
    80  
    81  func handleErr(err *error) {
    82  	if v := recover(); v != nil {
    83  		if e, ok := v.(yamlError); ok {
    84  			*err = e.err
    85  		} else {
    86  			panic(v)
    87  		}
    88  	}
    89  }
    90  
    91  type yamlError struct {
    92  	err error
    93  }
    94  
    95  func (p *parser) failf(line int, format string, args ...interface{}) {
    96  	where := p.parser.filename + ":"
    97  	line++
    98  	where += strconv.Itoa(line) + ": "
    99  	panic(yamlError{fmt.Errorf(where+format, args...)})
   100  }
   101  
   102  // A TypeError is returned by Unmarshal when one or more fields in
   103  // the YAML document cannot be properly decoded into the requested
   104  // types. When this error is returned, the value is still
   105  // unmarshaled partially.
   106  type TypeError struct {
   107  	Errors []string
   108  }
   109  
   110  func (e *TypeError) Error() string {
   111  	return fmt.Sprintf("yaml: unmarshal errors:\n  %s", strings.Join(e.Errors, "\n  "))
   112  }