/[aya]/vendor/gopkg.in/yaml.v3/yaml.go
ViewVC logotype

Annotation of /vendor/gopkg.in/yaml.v3/yaml.go

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.1 - (hide annotations)
Mon Sep 30 00:42:06 2024 UTC (6 weeks, 4 days ago) by yakumo_izuru
Branch: MAIN
CVS Tags: HEAD
Mirrored from https://git.chaotic.ninja/git/yakumo_izuru/aya

1 yakumo_izuru 1.1 //
2     // Copyright (c) 2011-2019 Canonical Ltd
3     //
4     // Licensed under the Apache License, Version 2.0 (the "License");
5     // you may not use this file except in compliance with the License.
6     // You may obtain a copy of the License at
7     //
8     // http://www.apache.org/licenses/LICENSE-2.0
9     //
10     // Unless required by applicable law or agreed to in writing, software
11     // distributed under the License is distributed on an "AS IS" BASIS,
12     // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13     // See the License for the specific language governing permissions and
14     // limitations under the License.
15    
16     // Package yaml implements YAML support for the Go language.
17     //
18     // Source code and other details for the project are available at GitHub:
19     //
20     // https://github.com/go-yaml/yaml
21     //
22     package yaml
23    
24     import (
25     "errors"
26     "fmt"
27     "io"
28     "reflect"
29     "strings"
30     "sync"
31     "unicode/utf8"
32     )
33    
34     // The Unmarshaler interface may be implemented by types to customize their
35     // behavior when being unmarshaled from a YAML document.
36     type Unmarshaler interface {
37     UnmarshalYAML(value *Node) error
38     }
39    
40     type obsoleteUnmarshaler interface {
41     UnmarshalYAML(unmarshal func(interface{}) error) error
42     }
43    
44     // The Marshaler interface may be implemented by types to customize their
45     // behavior when being marshaled into a YAML document. The returned value
46     // is marshaled in place of the original value implementing Marshaler.
47     //
48     // If an error is returned by MarshalYAML, the marshaling procedure stops
49     // and returns with the provided error.
50     type Marshaler interface {
51     MarshalYAML() (interface{}, error)
52     }
53    
54     // Unmarshal decodes the first document found within the in byte slice
55     // and assigns decoded values into the out value.
56     //
57     // Maps and pointers (to a struct, string, int, etc) are accepted as out
58     // values. If an internal pointer within a struct is not initialized,
59     // the yaml package will initialize it if necessary for unmarshalling
60     // the provided data. The out parameter must not be nil.
61     //
62     // The type of the decoded values should be compatible with the respective
63     // values in out. If one or more values cannot be decoded due to a type
64     // mismatches, decoding continues partially until the end of the YAML
65     // content, and a *yaml.TypeError is returned with details for all
66     // missed values.
67     //
68     // Struct fields are only unmarshalled if they are exported (have an
69     // upper case first letter), and are unmarshalled using the field name
70     // lowercased as the default key. Custom keys may be defined via the
71     // "yaml" name in the field tag: the content preceding the first comma
72     // is used as the key, and the following comma-separated options are
73     // used to tweak the marshalling process (see Marshal).
74     // Conflicting names result in a runtime error.
75     //
76     // For example:
77     //
78     // type T struct {
79     // F int `yaml:"a,omitempty"`
80     // B int
81     // }
82     // var t T
83     // yaml.Unmarshal([]byte("a: 1\nb: 2"), &t)
84     //
85     // See the documentation of Marshal for the format of tags and a list of
86     // supported tag options.
87     //
88     func Unmarshal(in []byte, out interface{}) (err error) {
89     return unmarshal(in, out, false)
90     }
91    
92     // A Decoder reads and decodes YAML values from an input stream.
93     type Decoder struct {
94     parser *parser
95     knownFields bool
96     }
97    
98     // NewDecoder returns a new decoder that reads from r.
99     //
100     // The decoder introduces its own buffering and may read
101     // data from r beyond the YAML values requested.
102     func NewDecoder(r io.Reader) *Decoder {
103     return &Decoder{
104     parser: newParserFromReader(r),
105     }
106     }
107    
108     // KnownFields ensures that the keys in decoded mappings to
109     // exist as fields in the struct being decoded into.
110     func (dec *Decoder) KnownFields(enable bool) {
111     dec.knownFields = enable
112     }
113    
114     // Decode reads the next YAML-encoded value from its input
115     // and stores it in the value pointed to by v.
116     //
117     // See the documentation for Unmarshal for details about the
118     // conversion of YAML into a Go value.
119     func (dec *Decoder) Decode(v interface{}) (err error) {
120     d := newDecoder()
121     d.knownFields = dec.knownFields
122     defer handleErr(&err)
123     node := dec.parser.parse()
124     if node == nil {
125     return io.EOF
126     }
127     out := reflect.ValueOf(v)
128     if out.Kind() == reflect.Ptr && !out.IsNil() {
129     out = out.Elem()
130     }
131     d.unmarshal(node, out)
132     if len(d.terrors) > 0 {
133     return &TypeError{d.terrors}
134     }
135     return nil
136     }
137    
138     // Decode decodes the node and stores its data into the value pointed to by v.
139     //
140     // See the documentation for Unmarshal for details about the
141     // conversion of YAML into a Go value.
142     func (n *Node) Decode(v interface{}) (err error) {
143     d := newDecoder()
144     defer handleErr(&err)
145     out := reflect.ValueOf(v)
146     if out.Kind() == reflect.Ptr && !out.IsNil() {
147     out = out.Elem()
148     }
149     d.unmarshal(n, out)
150     if len(d.terrors) > 0 {
151     return &TypeError{d.terrors}
152     }
153     return nil
154     }
155    
156     func unmarshal(in []byte, out interface{}, strict bool) (err error) {
157     defer handleErr(&err)
158     d := newDecoder()
159     p := newParser(in)
160     defer p.destroy()
161     node := p.parse()
162     if node != nil {
163     v := reflect.ValueOf(out)
164     if v.Kind() == reflect.Ptr && !v.IsNil() {
165     v = v.Elem()
166     }
167     d.unmarshal(node, v)
168     }
169     if len(d.terrors) > 0 {
170     return &TypeError{d.terrors}
171     }
172     return nil
173     }
174    
175     // Marshal serializes the value provided into a YAML document. The structure
176     // of the generated document will reflect the structure of the value itself.
177     // Maps and pointers (to struct, string, int, etc) are accepted as the in value.
178     //
179     // Struct fields are only marshalled if they are exported (have an upper case
180     // first letter), and are marshalled using the field name lowercased as the
181     // default key. Custom keys may be defined via the "yaml" name in the field
182     // tag: the content preceding the first comma is used as the key, and the
183     // following comma-separated options are used to tweak the marshalling process.
184     // Conflicting names result in a runtime error.
185     //
186     // The field tag format accepted is:
187     //
188     // `(...) yaml:"[<key>][,<flag1>[,<flag2>]]" (...)`
189     //
190     // The following flags are currently supported:
191     //
192     // omitempty Only include the field if it's not set to the zero
193     // value for the type or to empty slices or maps.
194     // Zero valued structs will be omitted if all their public
195     // fields are zero, unless they implement an IsZero
196     // method (see the IsZeroer interface type), in which
197     // case the field will be excluded if IsZero returns true.
198     //
199     // flow Marshal using a flow style (useful for structs,
200     // sequences and maps).
201     //
202     // inline Inline the field, which must be a struct or a map,
203     // causing all of its fields or keys to be processed as if
204     // they were part of the outer struct. For maps, keys must
205     // not conflict with the yaml keys of other struct fields.
206     //
207     // In addition, if the key is "-", the field is ignored.
208     //
209     // For example:
210     //
211     // type T struct {
212     // F int `yaml:"a,omitempty"`
213     // B int
214     // }
215     // yaml.Marshal(&T{B: 2}) // Returns "b: 2\n"
216     // yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n"
217     //
218     func Marshal(in interface{}) (out []byte, err error) {
219     defer handleErr(&err)
220     e := newEncoder()
221     defer e.destroy()
222     e.marshalDoc("", reflect.ValueOf(in))
223     e.finish()
224     out = e.out
225     return
226     }
227    
228     // An Encoder writes YAML values to an output stream.
229     type Encoder struct {
230     encoder *encoder
231     }
232    
233     // NewEncoder returns a new encoder that writes to w.
234     // The Encoder should be closed after use to flush all data
235     // to w.
236     func NewEncoder(w io.Writer) *Encoder {
237     return &Encoder{
238     encoder: newEncoderWithWriter(w),
239     }
240     }
241    
242     // Encode writes the YAML encoding of v to the stream.
243     // If multiple items are encoded to the stream, the
244     // second and subsequent document will be preceded
245     // with a "---" document separator, but the first will not.
246     //
247     // See the documentation for Marshal for details about the conversion of Go
248     // values to YAML.
249     func (e *Encoder) Encode(v interface{}) (err error) {
250     defer handleErr(&err)
251     e.encoder.marshalDoc("", reflect.ValueOf(v))
252     return nil
253     }
254    
255     // Encode encodes value v and stores its representation in n.
256     //
257     // See the documentation for Marshal for details about the
258     // conversion of Go values into YAML.
259     func (n *Node) Encode(v interface{}) (err error) {
260     defer handleErr(&err)
261     e := newEncoder()
262     defer e.destroy()
263     e.marshalDoc("", reflect.ValueOf(v))
264     e.finish()
265     p := newParser(e.out)
266     p.textless = true
267     defer p.destroy()
268     doc := p.parse()
269     *n = *doc.Content[0]
270     return nil
271     }
272    
273     // SetIndent changes the used indentation used when encoding.
274     func (e *Encoder) SetIndent(spaces int) {
275     if spaces < 0 {
276     panic("yaml: cannot indent to a negative number of spaces")
277     }
278     e.encoder.indent = spaces
279     }
280    
281     // Close closes the encoder by writing any remaining data.
282     // It does not write a stream terminating string "...".
283     func (e *Encoder) Close() (err error) {
284     defer handleErr(&err)
285     e.encoder.finish()
286     return nil
287     }
288    
289     func handleErr(err *error) {
290     if v := recover(); v != nil {
291     if e, ok := v.(yamlError); ok {
292     *err = e.err
293     } else {
294     panic(v)
295     }
296     }
297     }
298    
299     type yamlError struct {
300     err error
301     }
302    
303     func fail(err error) {
304     panic(yamlError{err})
305     }
306    
307     func failf(format string, args ...interface{}) {
308     panic(yamlError{fmt.Errorf("yaml: "+format, args...)})
309     }
310    
311     // A TypeError is returned by Unmarshal when one or more fields in
312     // the YAML document cannot be properly decoded into the requested
313     // types. When this error is returned, the value is still
314     // unmarshaled partially.
315     type TypeError struct {
316     Errors []string
317     }
318    
319     func (e *TypeError) Error() string {
320     return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n "))
321     }
322    
323     type Kind uint32
324    
325     const (
326     DocumentNode Kind = 1 << iota
327     SequenceNode
328     MappingNode
329     ScalarNode
330     AliasNode
331     )
332    
333     type Style uint32
334    
335     const (
336     TaggedStyle Style = 1 << iota
337     DoubleQuotedStyle
338     SingleQuotedStyle
339     LiteralStyle
340     FoldedStyle
341     FlowStyle
342     )
343    
344     // Node represents an element in the YAML document hierarchy. While documents
345     // are typically encoded and decoded into higher level types, such as structs
346     // and maps, Node is an intermediate representation that allows detailed
347     // control over the content being decoded or encoded.
348     //
349     // It's worth noting that although Node offers access into details such as
350     // line numbers, colums, and comments, the content when re-encoded will not
351     // have its original textual representation preserved. An effort is made to
352     // render the data plesantly, and to preserve comments near the data they
353     // describe, though.
354     //
355     // Values that make use of the Node type interact with the yaml package in the
356     // same way any other type would do, by encoding and decoding yaml data
357     // directly or indirectly into them.
358     //
359     // For example:
360     //
361     // var person struct {
362     // Name string
363     // Address yaml.Node
364     // }
365     // err := yaml.Unmarshal(data, &person)
366     //
367     // Or by itself:
368     //
369     // var person Node
370     // err := yaml.Unmarshal(data, &person)
371     //
372     type Node struct {
373     // Kind defines whether the node is a document, a mapping, a sequence,
374     // a scalar value, or an alias to another node. The specific data type of
375     // scalar nodes may be obtained via the ShortTag and LongTag methods.
376     Kind Kind
377    
378     // Style allows customizing the apperance of the node in the tree.
379     Style Style
380    
381     // Tag holds the YAML tag defining the data type for the value.
382     // When decoding, this field will always be set to the resolved tag,
383     // even when it wasn't explicitly provided in the YAML content.
384     // When encoding, if this field is unset the value type will be
385     // implied from the node properties, and if it is set, it will only
386     // be serialized into the representation if TaggedStyle is used or
387     // the implicit tag diverges from the provided one.
388     Tag string
389    
390     // Value holds the unescaped and unquoted represenation of the value.
391     Value string
392    
393     // Anchor holds the anchor name for this node, which allows aliases to point to it.
394     Anchor string
395    
396     // Alias holds the node that this alias points to. Only valid when Kind is AliasNode.
397     Alias *Node
398    
399     // Content holds contained nodes for documents, mappings, and sequences.
400     Content []*Node
401    
402     // HeadComment holds any comments in the lines preceding the node and
403     // not separated by an empty line.
404     HeadComment string
405    
406     // LineComment holds any comments at the end of the line where the node is in.
407     LineComment string
408    
409     // FootComment holds any comments following the node and before empty lines.
410     FootComment string
411    
412     // Line and Column hold the node position in the decoded YAML text.
413     // These fields are not respected when encoding the node.
414     Line int
415     Column int
416     }
417    
418     // IsZero returns whether the node has all of its fields unset.
419     func (n *Node) IsZero() bool {
420     return n.Kind == 0 && n.Style == 0 && n.Tag == "" && n.Value == "" && n.Anchor == "" && n.Alias == nil && n.Content == nil &&
421     n.HeadComment == "" && n.LineComment == "" && n.FootComment == "" && n.Line == 0 && n.Column == 0
422     }
423    
424    
425     // LongTag returns the long form of the tag that indicates the data type for
426     // the node. If the Tag field isn't explicitly defined, one will be computed
427     // based on the node properties.
428     func (n *Node) LongTag() string {
429     return longTag(n.ShortTag())
430     }
431    
432     // ShortTag returns the short form of the YAML tag that indicates data type for
433     // the node. If the Tag field isn't explicitly defined, one will be computed
434     // based on the node properties.
435     func (n *Node) ShortTag() string {
436     if n.indicatedString() {
437     return strTag
438     }
439     if n.Tag == "" || n.Tag == "!" {
440     switch n.Kind {
441     case MappingNode:
442     return mapTag
443     case SequenceNode:
444     return seqTag
445     case AliasNode:
446     if n.Alias != nil {
447     return n.Alias.ShortTag()
448     }
449     case ScalarNode:
450     tag, _ := resolve("", n.Value)
451     return tag
452     case 0:
453     // Special case to make the zero value convenient.
454     if n.IsZero() {
455     return nullTag
456     }
457     }
458     return ""
459     }
460     return shortTag(n.Tag)
461     }
462    
463     func (n *Node) indicatedString() bool {
464     return n.Kind == ScalarNode &&
465     (shortTag(n.Tag) == strTag ||
466     (n.Tag == "" || n.Tag == "!") && n.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0)
467     }
468    
469     // SetString is a convenience function that sets the node to a string value
470     // and defines its style in a pleasant way depending on its content.
471     func (n *Node) SetString(s string) {
472     n.Kind = ScalarNode
473     if utf8.ValidString(s) {
474     n.Value = s
475     n.Tag = strTag
476     } else {
477     n.Value = encodeBase64(s)
478     n.Tag = binaryTag
479     }
480     if strings.Contains(n.Value, "\n") {
481     n.Style = LiteralStyle
482     }
483     }
484    
485     // --------------------------------------------------------------------------
486     // Maintain a mapping of keys to structure field indexes
487    
488     // The code in this section was copied from mgo/bson.
489    
490     // structInfo holds details for the serialization of fields of
491     // a given struct.
492     type structInfo struct {
493     FieldsMap map[string]fieldInfo
494     FieldsList []fieldInfo
495    
496     // InlineMap is the number of the field in the struct that
497     // contains an ,inline map, or -1 if there's none.
498     InlineMap int
499    
500     // InlineUnmarshalers holds indexes to inlined fields that
501     // contain unmarshaler values.
502     InlineUnmarshalers [][]int
503     }
504    
505     type fieldInfo struct {
506     Key string
507     Num int
508     OmitEmpty bool
509     Flow bool
510     // Id holds the unique field identifier, so we can cheaply
511     // check for field duplicates without maintaining an extra map.
512     Id int
513    
514     // Inline holds the field index if the field is part of an inlined struct.
515     Inline []int
516     }
517    
518     var structMap = make(map[reflect.Type]*structInfo)
519     var fieldMapMutex sync.RWMutex
520     var unmarshalerType reflect.Type
521    
522     func init() {
523     var v Unmarshaler
524     unmarshalerType = reflect.ValueOf(&v).Elem().Type()
525     }
526    
527     func getStructInfo(st reflect.Type) (*structInfo, error) {
528     fieldMapMutex.RLock()
529     sinfo, found := structMap[st]
530     fieldMapMutex.RUnlock()
531     if found {
532     return sinfo, nil
533     }
534    
535     n := st.NumField()
536     fieldsMap := make(map[string]fieldInfo)
537     fieldsList := make([]fieldInfo, 0, n)
538     inlineMap := -1
539     inlineUnmarshalers := [][]int(nil)
540     for i := 0; i != n; i++ {
541     field := st.Field(i)
542     if field.PkgPath != "" && !field.Anonymous {
543     continue // Private field
544     }
545    
546     info := fieldInfo{Num: i}
547    
548     tag := field.Tag.Get("yaml")
549     if tag == "" && strings.Index(string(field.Tag), ":") < 0 {
550     tag = string(field.Tag)
551     }
552     if tag == "-" {
553     continue
554     }
555    
556     inline := false
557     fields := strings.Split(tag, ",")
558     if len(fields) > 1 {
559     for _, flag := range fields[1:] {
560     switch flag {
561     case "omitempty":
562     info.OmitEmpty = true
563     case "flow":
564     info.Flow = true
565     case "inline":
566     inline = true
567     default:
568     return nil, errors.New(fmt.Sprintf("unsupported flag %q in tag %q of type %s", flag, tag, st))
569     }
570     }
571     tag = fields[0]
572     }
573    
574     if inline {
575     switch field.Type.Kind() {
576     case reflect.Map:
577     if inlineMap >= 0 {
578     return nil, errors.New("multiple ,inline maps in struct " + st.String())
579     }
580     if field.Type.Key() != reflect.TypeOf("") {
581     return nil, errors.New("option ,inline needs a map with string keys in struct " + st.String())
582     }
583     inlineMap = info.Num
584     case reflect.Struct, reflect.Ptr:
585     ftype := field.Type
586     for ftype.Kind() == reflect.Ptr {
587     ftype = ftype.Elem()
588     }
589     if ftype.Kind() != reflect.Struct {
590     return nil, errors.New("option ,inline may only be used on a struct or map field")
591     }
592     if reflect.PtrTo(ftype).Implements(unmarshalerType) {
593     inlineUnmarshalers = append(inlineUnmarshalers, []int{i})
594     } else {
595     sinfo, err := getStructInfo(ftype)
596     if err != nil {
597     return nil, err
598     }
599     for _, index := range sinfo.InlineUnmarshalers {
600     inlineUnmarshalers = append(inlineUnmarshalers, append([]int{i}, index...))
601     }
602     for _, finfo := range sinfo.FieldsList {
603     if _, found := fieldsMap[finfo.Key]; found {
604     msg := "duplicated key '" + finfo.Key + "' in struct " + st.String()
605     return nil, errors.New(msg)
606     }
607     if finfo.Inline == nil {
608     finfo.Inline = []int{i, finfo.Num}
609     } else {
610     finfo.Inline = append([]int{i}, finfo.Inline...)
611     }
612     finfo.Id = len(fieldsList)
613     fieldsMap[finfo.Key] = finfo
614     fieldsList = append(fieldsList, finfo)
615     }
616     }
617     default:
618     return nil, errors.New("option ,inline may only be used on a struct or map field")
619     }
620     continue
621     }
622    
623     if tag != "" {
624     info.Key = tag
625     } else {
626     info.Key = strings.ToLower(field.Name)
627     }
628    
629     if _, found = fieldsMap[info.Key]; found {
630     msg := "duplicated key '" + info.Key + "' in struct " + st.String()
631     return nil, errors.New(msg)
632     }
633    
634     info.Id = len(fieldsList)
635     fieldsList = append(fieldsList, info)
636     fieldsMap[info.Key] = info
637     }
638    
639     sinfo = &structInfo{
640     FieldsMap: fieldsMap,
641     FieldsList: fieldsList,
642     InlineMap: inlineMap,
643     InlineUnmarshalers: inlineUnmarshalers,
644     }
645    
646     fieldMapMutex.Lock()
647     structMap[st] = sinfo
648     fieldMapMutex.Unlock()
649     return sinfo, nil
650     }
651    
652     // IsZeroer is used to check whether an object is zero to
653     // determine whether it should be omitted when marshaling
654     // with the omitempty flag. One notable implementation
655     // is time.Time.
656     type IsZeroer interface {
657     IsZero() bool
658     }
659    
660     func isZero(v reflect.Value) bool {
661     kind := v.Kind()
662     if z, ok := v.Interface().(IsZeroer); ok {
663     if (kind == reflect.Ptr || kind == reflect.Interface) && v.IsNil() {
664     return true
665     }
666     return z.IsZero()
667     }
668     switch kind {
669     case reflect.String:
670     return len(v.String()) == 0
671     case reflect.Interface, reflect.Ptr:
672     return v.IsNil()
673     case reflect.Slice:
674     return v.Len() == 0
675     case reflect.Map:
676     return v.Len() == 0
677     case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
678     return v.Int() == 0
679     case reflect.Float32, reflect.Float64:
680     return v.Float() == 0
681     case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
682     return v.Uint() == 0
683     case reflect.Bool:
684     return !v.Bool()
685     case reflect.Struct:
686     vt := v.Type()
687     for i := v.NumField() - 1; i >= 0; i-- {
688     if vt.Field(i).PkgPath != "" {
689     continue // Private field
690     }
691     if !isZero(v.Field(i)) {
692     return false
693     }
694     }
695     return true
696     }
697     return false
698     }

nishi@chaotic.ninja
ViewVC Help
Powered by ViewVC 1.3.0-dev