1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
35
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
45
46
47
48
49
50 type Marshaler interface {
51 MarshalYAML() (interface{}, error)
52 }
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88 func Unmarshal(in []byte, out interface{}) (err error) {
89 return unmarshal(in, out, false)
90 }
91
92
93 type Decoder struct {
94 parser *parser
95 knownFields bool
96 }
97
98
99
100
101
102 func NewDecoder(r io.Reader) *Decoder {
103 return &Decoder{
104 parser: newParserFromReader(r),
105 }
106 }
107
108
109
110 func (dec *Decoder) KnownFields(enable bool) {
111 dec.knownFields = enable
112 }
113
114
115
116
117
118
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
139
140
141
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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
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
229 type Encoder struct {
230 encoder *encoder
231 }
232
233
234
235
236 func NewEncoder(w io.Writer) *Encoder {
237 return &Encoder{
238 encoder: newEncoderWithWriter(w),
239 }
240 }
241
242
243
244
245
246
247
248
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
256
257
258
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
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
282
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
312
313
314
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
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372 type Node struct {
373
374
375
376 Kind Kind
377
378
379 Style Style
380
381
382
383
384
385
386
387
388 Tag string
389
390
391 Value string
392
393
394 Anchor string
395
396
397 Alias *Node
398
399
400 Content []*Node
401
402
403
404 HeadComment string
405
406
407 LineComment string
408
409
410 FootComment string
411
412
413
414 Line int
415 Column int
416 }
417
418
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
426
427
428 func (n *Node) LongTag() string {
429 return longTag(n.ShortTag())
430 }
431
432
433
434
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
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
470
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
487
488
489
490
491
492 type structInfo struct {
493 FieldsMap map[string]fieldInfo
494 FieldsList []fieldInfo
495
496
497
498 InlineMap int
499
500
501
502 InlineUnmarshalers [][]int
503 }
504
505 type fieldInfo struct {
506 Key string
507 Num int
508 OmitEmpty bool
509 Flow bool
510
511
512 Id int
513
514
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
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
653
654
655
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
690 }
691 if !isZero(v.Field(i)) {
692 return false
693 }
694 }
695 return true
696 }
697 return false
698 }
699
View as plain text