| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 |
- package sub
- import (
- "reflect"
- "regexp"
- "strings"
- "github.com/goccy/go-yaml"
- )
- type yamlQuotedString string
- func (s yamlQuotedString) MarshalYAML() ([]byte, error) {
- return []byte("'" + strings.ReplaceAll(string(s), "'", "''") + "'"), nil
- }
- var yamlNonStringWords = map[string]bool{
- "~": true, "null": true, "Null": true, "NULL": true,
- "true": true, "True": true, "TRUE": true,
- "false": true, "False": true, "FALSE": true,
- "yes": true, "Yes": true, "YES": true,
- "no": true, "No": true, "NO": true,
- "on": true, "On": true, "ON": true,
- "off": true, "Off": true, "OFF": true,
- "y": true, "Y": true, "n": true, "N": true,
- }
- var yamlNonStringNumber = regexp.MustCompile(`^(?:` +
- `[-+]?[0-9]+|` +
- `0[oO]?[0-7]+|0[xX][0-9a-fA-F]+|` +
- `[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+|` +
- `[-+]?(?:[0-9]*\.[0-9]+|[0-9]+\.?[0-9]*)(?:[eE][-+]?[0-9]+)?|` +
- `[-+]?\.(?:inf|Inf|INF)|\.(?:nan|NaN|NAN)|` +
- `[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}(?:[Tt ].*)?` +
- `)$`)
- func yamlScalarIsAmbiguous(s string) bool {
- if s == "" {
- return false
- }
- return yamlNonStringWords[s] || yamlNonStringNumber.MatchString(s)
- }
- func quoteAmbiguousYAMLScalars(v any) any {
- if v == nil {
- return nil
- }
- if s, ok := v.(string); ok {
- if yamlScalarIsAmbiguous(s) {
- return yamlQuotedString(s)
- }
- return s
- }
- rv := reflect.ValueOf(v)
- switch rv.Kind() {
- case reflect.Map:
- out := make(map[string]any, rv.Len())
- iter := rv.MapRange()
- for iter.Next() {
- key, ok := iter.Key().Interface().(string)
- if !ok {
- return v
- }
- out[key] = quoteAmbiguousYAMLScalars(iter.Value().Interface())
- }
- return out
- case reflect.Slice, reflect.Array:
- if rv.Kind() == reflect.Slice && rv.Type().Elem().Kind() == reflect.Uint8 {
- return v
- }
- out := make([]any, rv.Len())
- for i := range rv.Len() {
- out[i] = quoteAmbiguousYAMLScalars(rv.Index(i).Interface())
- }
- return out
- case reflect.Pointer, reflect.Interface:
- if rv.IsNil() {
- return v
- }
- return quoteAmbiguousYAMLScalars(rv.Elem().Interface())
- default:
- return v
- }
- }
- func marshalClashYAML(config any) ([]byte, error) {
- return yaml.Marshal(quoteAmbiguousYAMLScalars(config))
- }
|