k8s.io/kube-openapi@v0.0.0-20240228011516-70dd3763d340/pkg/internal/third_party/go-json-experiment/json/arshal_any.go (about)

     1  // Copyright 2022 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package json
     6  
     7  import "reflect"
     8  
     9  // This files contains an optimized marshal and unmarshal implementation
    10  // for the any type. This type is often used when the Go program has
    11  // no knowledge of the JSON schema. This is a common enough occurrence
    12  // to justify the complexity of adding logic for this.
    13  
    14  func marshalValueAny(mo MarshalOptions, enc *Encoder, val any) error {
    15  	switch val := val.(type) {
    16  	case nil:
    17  		return enc.WriteToken(Null)
    18  	case bool:
    19  		return enc.WriteToken(Bool(val))
    20  	case string:
    21  		return enc.WriteToken(String(val))
    22  	case float64:
    23  		return enc.WriteToken(Float(val))
    24  	case map[string]any:
    25  		return marshalObjectAny(mo, enc, val)
    26  	case []any:
    27  		return marshalArrayAny(mo, enc, val)
    28  	default:
    29  		v := newAddressableValue(reflect.TypeOf(val))
    30  		v.Set(reflect.ValueOf(val))
    31  		marshal := lookupArshaler(v.Type()).marshal
    32  		if mo.Marshalers != nil {
    33  			marshal, _ = mo.Marshalers.lookup(marshal, v.Type())
    34  		}
    35  		return marshal(mo, enc, v)
    36  	}
    37  }
    38  
    39  func unmarshalValueAny(uo UnmarshalOptions, dec *Decoder) (any, error) {
    40  	switch k := dec.PeekKind(); k {
    41  	case '{':
    42  		return unmarshalObjectAny(uo, dec)
    43  	case '[':
    44  		return unmarshalArrayAny(uo, dec)
    45  	default:
    46  		var flags valueFlags
    47  		val, err := dec.readValue(&flags)
    48  		if err != nil {
    49  			return nil, err
    50  		}
    51  		switch val.Kind() {
    52  		case 'n':
    53  			return nil, nil
    54  		case 'f':
    55  			return false, nil
    56  		case 't':
    57  			return true, nil
    58  		case '"':
    59  			val = unescapeStringMayCopy(val, flags.isVerbatim())
    60  			if dec.stringCache == nil {
    61  				dec.stringCache = new(stringCache)
    62  			}
    63  			return dec.stringCache.make(val), nil
    64  		case '0':
    65  			fv, _ := parseFloat(val, 64) // ignore error since readValue guarantees val is valid
    66  			return fv, nil
    67  		default:
    68  			panic("BUG: invalid kind: " + k.String())
    69  		}
    70  	}
    71  }
    72  
    73  func marshalObjectAny(mo MarshalOptions, enc *Encoder, obj map[string]any) error {
    74  	// Check for cycles.
    75  	if enc.tokens.depth() > startDetectingCyclesAfter {
    76  		v := reflect.ValueOf(obj)
    77  		if err := enc.seenPointers.visit(v); err != nil {
    78  			return err
    79  		}
    80  		defer enc.seenPointers.leave(v)
    81  	}
    82  
    83  	// Optimize for marshaling an empty map without any preceding whitespace.
    84  	if len(obj) == 0 && !enc.options.multiline && !enc.tokens.last.needObjectName() {
    85  		enc.buf = enc.tokens.mayAppendDelim(enc.buf, '{')
    86  		enc.buf = append(enc.buf, "{}"...)
    87  		enc.tokens.last.increment()
    88  		if enc.needFlush() {
    89  			return enc.flush()
    90  		}
    91  		return nil
    92  	}
    93  
    94  	if err := enc.WriteToken(ObjectStart); err != nil {
    95  		return err
    96  	}
    97  	// A Go map guarantees that each entry has a unique key
    98  	// The only possibility of duplicates is due to invalid UTF-8.
    99  	if !enc.options.AllowInvalidUTF8 {
   100  		enc.tokens.last.disableNamespace()
   101  	}
   102  	if !mo.Deterministic || len(obj) <= 1 {
   103  		for name, val := range obj {
   104  			if err := enc.WriteToken(String(name)); err != nil {
   105  				return err
   106  			}
   107  			if err := marshalValueAny(mo, enc, val); err != nil {
   108  				return err
   109  			}
   110  		}
   111  	} else {
   112  		names := getStrings(len(obj))
   113  		var i int
   114  		for name := range obj {
   115  			(*names)[i] = name
   116  			i++
   117  		}
   118  		names.Sort()
   119  		for _, name := range *names {
   120  			if err := enc.WriteToken(String(name)); err != nil {
   121  				return err
   122  			}
   123  			if err := marshalValueAny(mo, enc, obj[name]); err != nil {
   124  				return err
   125  			}
   126  		}
   127  		putStrings(names)
   128  	}
   129  	if err := enc.WriteToken(ObjectEnd); err != nil {
   130  		return err
   131  	}
   132  	return nil
   133  }
   134  
   135  func unmarshalObjectAny(uo UnmarshalOptions, dec *Decoder) (map[string]any, error) {
   136  	tok, err := dec.ReadToken()
   137  	if err != nil {
   138  		return nil, err
   139  	}
   140  	k := tok.Kind()
   141  	switch k {
   142  	case 'n':
   143  		return nil, nil
   144  	case '{':
   145  		obj := make(map[string]any)
   146  		// A Go map guarantees that each entry has a unique key
   147  		// The only possibility of duplicates is due to invalid UTF-8.
   148  		if !dec.options.AllowInvalidUTF8 {
   149  			dec.tokens.last.disableNamespace()
   150  		}
   151  		for dec.PeekKind() != '}' {
   152  			tok, err := dec.ReadToken()
   153  			if err != nil {
   154  				return obj, err
   155  			}
   156  			name := tok.String()
   157  
   158  			// Manually check for duplicate names.
   159  			if _, ok := obj[name]; ok {
   160  				name := dec.previousBuffer()
   161  				err := &SyntacticError{str: "duplicate name " + string(name) + " in object"}
   162  				return obj, err.withOffset(dec.InputOffset() - int64(len(name)))
   163  			}
   164  
   165  			val, err := unmarshalValueAny(uo, dec)
   166  			obj[name] = val
   167  			if err != nil {
   168  				return obj, err
   169  			}
   170  		}
   171  		if _, err := dec.ReadToken(); err != nil {
   172  			return obj, err
   173  		}
   174  		return obj, nil
   175  	}
   176  	return nil, &SemanticError{action: "unmarshal", JSONKind: k, GoType: mapStringAnyType}
   177  }
   178  
   179  func marshalArrayAny(mo MarshalOptions, enc *Encoder, arr []any) error {
   180  	// Check for cycles.
   181  	if enc.tokens.depth() > startDetectingCyclesAfter {
   182  		v := reflect.ValueOf(arr)
   183  		if err := enc.seenPointers.visit(v); err != nil {
   184  			return err
   185  		}
   186  		defer enc.seenPointers.leave(v)
   187  	}
   188  
   189  	// Optimize for marshaling an empty slice without any preceding whitespace.
   190  	if len(arr) == 0 && !enc.options.multiline && !enc.tokens.last.needObjectName() {
   191  		enc.buf = enc.tokens.mayAppendDelim(enc.buf, '[')
   192  		enc.buf = append(enc.buf, "[]"...)
   193  		enc.tokens.last.increment()
   194  		if enc.needFlush() {
   195  			return enc.flush()
   196  		}
   197  		return nil
   198  	}
   199  
   200  	if err := enc.WriteToken(ArrayStart); err != nil {
   201  		return err
   202  	}
   203  	for _, val := range arr {
   204  		if err := marshalValueAny(mo, enc, val); err != nil {
   205  			return err
   206  		}
   207  	}
   208  	if err := enc.WriteToken(ArrayEnd); err != nil {
   209  		return err
   210  	}
   211  	return nil
   212  }
   213  
   214  func unmarshalArrayAny(uo UnmarshalOptions, dec *Decoder) ([]any, error) {
   215  	tok, err := dec.ReadToken()
   216  	if err != nil {
   217  		return nil, err
   218  	}
   219  	k := tok.Kind()
   220  	switch k {
   221  	case 'n':
   222  		return nil, nil
   223  	case '[':
   224  		arr := []any{}
   225  		for dec.PeekKind() != ']' {
   226  			val, err := unmarshalValueAny(uo, dec)
   227  			arr = append(arr, val)
   228  			if err != nil {
   229  				return arr, err
   230  			}
   231  		}
   232  		if _, err := dec.ReadToken(); err != nil {
   233  			return arr, err
   234  		}
   235  		return arr, nil
   236  	}
   237  	return nil, &SemanticError{action: "unmarshal", JSONKind: k, GoType: sliceAnyType}
   238  }