package yaml

import (
	
	
	
	
	
	
	
	
	
	
)
jsonNumber is the interface of the encoding/json.Number datatype. Repeating the interface here avoids a dependency on encoding/json, and also supports other libraries like jsoniter, which use a similar datatype with the same interface. Detecting this interface is useful when dealing with structures containing json.Number, which is a string under the hood. The encoder should prefer the use of Int64(), Float64() and string(), in that order, when encoding this type.
type jsonNumber interface {
	Float64() (float64, error)
	Int64() (int64, error)
	String() string
}

type encoder struct {
	emitter yaml_emitter_t
	event   yaml_event_t
	out     []byte
This will internally delete the e.event value.
	.must(yaml_emitter_emit(&.emitter, &.event))
}

func ( *encoder) ( bool) {
	if ! {
		 := .emitter.problem
		if  == "" {
			 = "unknown problem generating YAML content"
		}
		failf("%s", )
	}
}

func ( *encoder) ( string,  reflect.Value) {
	.init()
	yaml_document_start_event_initialize(&.event, nil, nil, true)
	.emit()
	.marshal(, )
	yaml_document_end_event_initialize(&.event, true)
	.emit()
}

func ( *encoder) ( string,  reflect.Value) {
	if !.IsValid() || .Kind() == reflect.Ptr && .IsNil() {
		.nilv()
		return
	}
	 := .Interface()
	switch m := .(type) {
	case jsonNumber:
		,  := .Int64()
In this case the json.Number is a valid int64
			 = reflect.ValueOf()
			break
		}
		,  := .Float64()
In this case the json.Number is a valid float64
			 = reflect.ValueOf()
			break
fallback case - no number could be obtained
		 = reflect.ValueOf(.String())
Although time.Time implements TextMarshaler, we don't want to treat it as a string for YAML purposes because YAML has special support for timestamps.
	case Marshaler:
		,  := .MarshalYAML()
		if  != nil {
			fail()
		}
		if  == nil {
			.nilv()
			return
		}
		 = reflect.ValueOf()
	case encoding.TextMarshaler:
		,  := .MarshalText()
		if  != nil {
			fail()
		}
		 = reflect.ValueOf(string())
	case nil:
		.nilv()
		return
	}
	switch .Kind() {
	case reflect.Interface:
		.(, .Elem())
	case reflect.Map:
		.mapv(, )
	case reflect.Ptr:
		if .Type() == ptrTimeType {
			.timev(, .Elem())
		} else {
			.(, .Elem())
		}
	case reflect.Struct:
		if .Type() == timeType {
			.timev(, )
		} else {
			.structv(, )
		}
	case reflect.Slice, reflect.Array:
		if .Type().Elem() == mapItemType {
			.itemsv(, )
		} else {
			.slicev(, )
		}
	case reflect.String:
		.stringv(, )
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		if .Type() == durationType {
			.stringv(, reflect.ValueOf(.(time.Duration).String()))
		} else {
			.intv(, )
		}
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		.uintv(, )
	case reflect.Float32, reflect.Float64:
		.floatv(, )
	case reflect.Bool:
		.boolv(, )
	default:
		panic("cannot marshal type: " + .Type().String())
	}
}

func ( *encoder) ( string,  reflect.Value) {
	.mappingv(, func() {
		 := keyList(.MapKeys())
		sort.Sort()
		for ,  := range  {
			.marshal("", )
			.marshal("", .MapIndex())
		}
	})
}

func ( *encoder) ( string,  reflect.Value) {
	.mappingv(, func() {
		 := .Convert(reflect.TypeOf([]MapItem{})).Interface().([]MapItem)
		for ,  := range  {
			.marshal("", reflect.ValueOf(.Key))
			.marshal("", reflect.ValueOf(.Value))
		}
	})
}

func ( *encoder) ( string,  reflect.Value) {
	,  := getStructInfo(.Type())
	if  != nil {
		panic()
	}
	.mappingv(, func() {
		for ,  := range .FieldsList {
			var  reflect.Value
			if .Inline == nil {
				 = .Field(.Num)
			} else {
				 = .FieldByIndex(.Inline)
			}
			if .OmitEmpty && isZero() {
				continue
			}
			.marshal("", reflect.ValueOf(.Key))
			.flow = .Flow
			.marshal("", )
		}
		if .InlineMap >= 0 {
			 := .Field(.InlineMap)
			if .Len() > 0 {
				.flow = false
				 := keyList(.MapKeys())
				sort.Sort()
				for ,  := range  {
					if ,  := .FieldsMap[.String()];  {
						panic(fmt.Sprintf("Can't have key %q in inlined map; conflicts with struct field", .String()))
					}
					.marshal("", )
					.flow = false
					.marshal("", .MapIndex())
				}
			}
		}
	})
}

func ( *encoder) ( string,  func()) {
	 :=  == ""
	 := yaml_BLOCK_MAPPING_STYLE
	if .flow {
		.flow = false
		 = yaml_FLOW_MAPPING_STYLE
	}
	yaml_mapping_start_event_initialize(&.event, nil, []byte(), , )
	.emit()
	()
	yaml_mapping_end_event_initialize(&.event)
	.emit()
}

func ( *encoder) ( string,  reflect.Value) {
	 :=  == ""
	 := yaml_BLOCK_SEQUENCE_STYLE
	if .flow {
		.flow = false
		 = yaml_FLOW_SEQUENCE_STYLE
	}
	.must(yaml_sequence_start_event_initialize(&.event, nil, []byte(), , ))
	.emit()
	 := .Len()
	for  := 0;  < ; ++ {
		.marshal("", .Index())
	}
	.must(yaml_sequence_end_event_initialize(&.event))
	.emit()
}
isBase60 returns whether s is in base 60 notation as defined in YAML 1.1. The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported in YAML 1.2 and by this package, but these should be marshalled quoted for the time being for compatibility with other parsers.
Fast path.
	if  == "" {
		return false
	}
	 := [0]
	if !( == '+' ||  == '-' ||  >= '0' &&  <= '9') || strings.IndexByte(, ':') < 0 {
		return false
Do the full match.
	return base60float.MatchString()
}
From http://yaml.org/type/float.html, except the regular expression there is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix.
var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`)

func ( *encoder) ( string,  reflect.Value) {
	var  yaml_scalar_style_t
	 := .String()
	 := true
	switch {
	case !utf8.ValidString():
		if  == yaml_BINARY_TAG {
			failf("explicitly tagged !!binary data must be base64-encoded")
		}
		if  != "" {
			failf("cannot marshal invalid UTF-8 data as %s", shortTag())
It can't be encoded directly as YAML so use a binary tag and encode it as base64.
Check to see if it would resolve to a specific tag when encoded unquoted. If it doesn't, there's no need to quote it.
		,  := resolve("", )
		 =  == yaml_STR_TAG && !isBase60Float()
Note: it's possible for user code to emit invalid YAML if they explicitly specify a tag and a string containing text that's incompatible with that tag.
	switch {
	case strings.Contains(, "\n"):
		 = yaml_LITERAL_SCALAR_STYLE
	case :
		 = yaml_PLAIN_SCALAR_STYLE
	default:
		 = yaml_DOUBLE_QUOTED_SCALAR_STYLE
	}
	.emitScalar(, "", , )
}

func ( *encoder) ( string,  reflect.Value) {
	var  string
	if .Bool() {
		 = "true"
	} else {
		 = "false"
	}
	.emitScalar(, "", , yaml_PLAIN_SCALAR_STYLE)
}

func ( *encoder) ( string,  reflect.Value) {
	 := strconv.FormatInt(.Int(), 10)
	.emitScalar(, "", , yaml_PLAIN_SCALAR_STYLE)
}

func ( *encoder) ( string,  reflect.Value) {
	 := strconv.FormatUint(.Uint(), 10)
	.emitScalar(, "", , yaml_PLAIN_SCALAR_STYLE)
}

func ( *encoder) ( string,  reflect.Value) {
	 := .Interface().(time.Time)
	 := .Format(time.RFC3339Nano)
	.emitScalar(, "", , yaml_PLAIN_SCALAR_STYLE)
}

Issue #352: When formatting, use the precision of the underlying value
	 := 64
	if .Kind() == reflect.Float32 {
		 = 32
	}

	 := strconv.FormatFloat(.Float(), 'g', -1, )
	switch  {
	case "+Inf":
		 = ".inf"
	case "-Inf":
		 = "-.inf"
	case "NaN":
		 = ".nan"
	}
	.emitScalar(, "", , yaml_PLAIN_SCALAR_STYLE)
}

func ( *encoder) () {
	.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE)
}

func ( *encoder) (, ,  string,  yaml_scalar_style_t) {
	 :=  == ""
	.must(yaml_scalar_event_initialize(&.event, []byte(), []byte(), []byte(), , , ))
	.emit()