github.com/cockroachdb/cockroachdb-parser@v0.23.3-0.20240213214944-911057d40c9a/pkg/util/json/config.go (about)

     1  // Copyright 2022 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package json
    12  
    13  import (
    14  	"github.com/cockroachdb/cockroachdb-parser/pkg/util"
    15  	"github.com/cockroachdb/errors"
    16  )
    17  
    18  // ParseOption is an option for JSON parsing.
    19  type ParseOption interface {
    20  	apply(cfg *parseConfig)
    21  }
    22  
    23  // WithUnorderedObjectKeys returns an option that leaves JSON
    24  // object keys unordered.
    25  func WithUnorderedObjectKeys() ParseOption {
    26  	return funcOpt(func(cfg *parseConfig) {
    27  		cfg.unordered = true
    28  	})
    29  }
    30  
    31  // WithGoStandardParser returns an option that forces the use of Go parser
    32  // (encoding/json).
    33  func WithGoStandardParser() ParseOption {
    34  	return funcOpt(func(cfg *parseConfig) {
    35  		cfg.impl = useStdGoJSON
    36  	})
    37  }
    38  
    39  // WithFastJSONParser returns an option that forces the use of fast json parser.
    40  func WithFastJSONParser() ParseOption {
    41  	return funcOpt(func(cfg *parseConfig) {
    42  		cfg.impl = useFastJSONParser
    43  	})
    44  }
    45  
    46  // parseJSONImplType is the implementation library
    47  // used to parse JSON.
    48  type parseJSONImplType int
    49  
    50  const (
    51  	// useStdGoJSON : encoding/json
    52  	useStdGoJSON parseJSONImplType = iota
    53  	// useFastJSONParser : uses fast JSON parser (built on top of pkg/json high performance library)
    54  	useFastJSONParser
    55  
    56  	// Note: Other libraries tested and rejected include:
    57  	//  * json-iter: A fine library; however, fastJSONParser consistently
    58  	//    performed better, with much better memory allocation behavior.
    59  	//  * go-json: universally slower, worse (allocation) than either
    60  	//    standard or json-iter for larger inputs.
    61  	//  * simdjson-go: too restrictive; doesn't work on all platforms,
    62  	//    does not parse raw json literals (true/false, etc); and is not
    63  	//    a drop in replacement.
    64  	//  * ffjson, easyjson: not appropriate since these library use code
    65  	//    generation, and cannot parse arbitrary JSON.
    66  )
    67  
    68  // default configuration for parsing JSON.
    69  var parseJSONDefaultConfig = func() (cfg parseConfig) {
    70  	cfg.impl = util.ConstantWithMetamorphicTestChoice(
    71  		"parse-json-impl", useFastJSONParser, useStdGoJSON,
    72  	).(parseJSONImplType)
    73  	return cfg
    74  }()
    75  
    76  type parseConfig struct {
    77  	unordered bool
    78  	impl      parseJSONImplType
    79  }
    80  
    81  func (c parseConfig) parseJSON(s string) (JSON, error) {
    82  	switch c.impl {
    83  	case useStdGoJSON:
    84  		return parseJSONGoStd(s, c)
    85  	case useFastJSONParser:
    86  		return parseUsingFastParser(s, c)
    87  	default:
    88  		return nil, errors.AssertionFailedf("invalid ParseJSON implementation %v", c.impl)
    89  	}
    90  }
    91  
    92  type funcOpt func(cfg *parseConfig)
    93  
    94  func (f funcOpt) apply(cfg *parseConfig) {
    95  	f(cfg)
    96  }