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