Source file src/encoding/json/internal/jsonflags/flags.go

     1  // Copyright 2023 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  //go:build goexperiment.jsonv2
     6  
     7  // jsonflags implements all the optional boolean flags.
     8  // These flags are shared across both "json", "jsontext", and "jsonopts".
     9  package jsonflags
    10  
    11  import "encoding/json/internal"
    12  
    13  // Bools represents zero or more boolean flags, all set to true or false.
    14  // The least-significant bit is the boolean value of all flags in the set.
    15  // The remaining bits identify which particular flags.
    16  //
    17  // In common usage, this is OR'd with 0 or 1. For example:
    18  //   - (AllowInvalidUTF8 | 0) means "AllowInvalidUTF8 is false"
    19  //   - (Multiline | Indent | 1) means "Multiline and Indent are true"
    20  type Bools uint64
    21  
    22  func (Bools) JSONOptions(internal.NotForPublicUse) {}
    23  
    24  const (
    25  	// AllFlags is the set of all flags.
    26  	AllFlags = AllCoderFlags | AllArshalV2Flags | AllArshalV1Flags
    27  
    28  	// AllCoderFlags is the set of all encoder/decoder flags.
    29  	AllCoderFlags = (maxCoderFlag - 1) - initFlag
    30  
    31  	// AllArshalV2Flags is the set of all v2 marshal/unmarshal flags.
    32  	AllArshalV2Flags = (maxArshalV2Flag - 1) - (maxCoderFlag - 1)
    33  
    34  	// AllArshalV1Flags is the set of all v1 marshal/unmarshal flags.
    35  	AllArshalV1Flags = (maxArshalV1Flag - 1) - (maxArshalV2Flag - 1)
    36  
    37  	// NonBooleanFlags is the set of non-boolean flags,
    38  	// where the value is some other concrete Go type.
    39  	// The value of the flag is stored within jsonopts.Struct.
    40  	NonBooleanFlags = 0 |
    41  		Indent |
    42  		IndentPrefix |
    43  		ByteLimit |
    44  		DepthLimit |
    45  		Marshalers |
    46  		Unmarshalers
    47  
    48  	// DefaultV1Flags is the set of booleans flags that default to true under
    49  	// v1 semantics. None of the non-boolean flags differ between v1 and v2.
    50  	DefaultV1Flags = 0 |
    51  		AllowDuplicateNames |
    52  		AllowInvalidUTF8 |
    53  		EscapeForHTML |
    54  		EscapeForJS |
    55  		PreserveRawStrings |
    56  		Deterministic |
    57  		FormatNilMapAsNull |
    58  		FormatNilSliceAsNull |
    59  		MatchCaseInsensitiveNames |
    60  		CallMethodsWithLegacySemantics |
    61  		FormatByteArrayAsArray |
    62  		FormatBytesWithLegacySemantics |
    63  		FormatDurationAsNano |
    64  		MatchCaseSensitiveDelimiter |
    65  		MergeWithLegacySemantics |
    66  		OmitEmptyWithLegacySemantics |
    67  		ParseBytesWithLooseRFC4648 |
    68  		ParseTimeWithLooseRFC3339 |
    69  		ReportErrorsWithLegacySemantics |
    70  		StringifyWithLegacySemantics |
    71  		UnmarshalArrayFromAnyLength
    72  
    73  	// AnyWhitespace reports whether the encoded output might have any whitespace.
    74  	AnyWhitespace = Multiline | SpaceAfterColon | SpaceAfterComma
    75  
    76  	// WhitespaceFlags is the set of flags related to whitespace formatting.
    77  	// In contrast to AnyWhitespace, this includes Indent and IndentPrefix
    78  	// as those settings take no effect if Multiline is false.
    79  	WhitespaceFlags = AnyWhitespace | Indent | IndentPrefix
    80  
    81  	// AnyEscape is the set of flags related to escaping in a JSON string.
    82  	AnyEscape = EscapeForHTML | EscapeForJS
    83  
    84  	// CanonicalizeNumbers is the set of flags related to raw number canonicalization.
    85  	CanonicalizeNumbers = CanonicalizeRawInts | CanonicalizeRawFloats
    86  )
    87  
    88  // Encoder and decoder flags.
    89  const (
    90  	initFlag Bools = 1 << iota // reserved for the boolean value itself
    91  
    92  	AllowDuplicateNames   // encode or decode
    93  	AllowInvalidUTF8      // encode or decode
    94  	WithinArshalCall      // encode or decode; for internal use by json.Marshal and json.Unmarshal
    95  	OmitTopLevelNewline   // encode only; for internal use by json.Marshal and json.MarshalWrite
    96  	PreserveRawStrings    // encode only
    97  	CanonicalizeRawInts   // encode only
    98  	CanonicalizeRawFloats // encode only
    99  	ReorderRawObjects     // encode only
   100  	EscapeForHTML         // encode only
   101  	EscapeForJS           // encode only
   102  	Multiline             // encode only
   103  	SpaceAfterColon       // encode only
   104  	SpaceAfterComma       // encode only
   105  	Indent                // encode only; non-boolean flag
   106  	IndentPrefix          // encode only; non-boolean flag
   107  	ByteLimit             // encode or decode; non-boolean flag
   108  	DepthLimit            // encode or decode; non-boolean flag
   109  
   110  	maxCoderFlag
   111  )
   112  
   113  // Marshal and Unmarshal flags (for v2).
   114  const (
   115  	_ Bools = (maxCoderFlag >> 1) << iota
   116  
   117  	StringifyNumbers          // marshal or unmarshal
   118  	Deterministic             // marshal only
   119  	FormatNilMapAsNull        // marshal only
   120  	FormatNilSliceAsNull      // marshal only
   121  	OmitZeroStructFields      // marshal only
   122  	MatchCaseInsensitiveNames // marshal or unmarshal
   123  	DiscardUnknownMembers     // marshal only
   124  	RejectUnknownMembers      // unmarshal only
   125  	Marshalers                // marshal only; non-boolean flag
   126  	Unmarshalers              // unmarshal only; non-boolean flag
   127  
   128  	maxArshalV2Flag
   129  )
   130  
   131  // Marshal and Unmarshal flags (for v1).
   132  const (
   133  	_ Bools = (maxArshalV2Flag >> 1) << iota
   134  
   135  	CallMethodsWithLegacySemantics  // marshal or unmarshal
   136  	FormatByteArrayAsArray          // marshal or unmarshal
   137  	FormatBytesWithLegacySemantics  // marshal or unmarshal
   138  	FormatDurationAsNano            // marshal or unmarshal
   139  	MatchCaseSensitiveDelimiter     // marshal or unmarshal
   140  	MergeWithLegacySemantics        // unmarshal
   141  	OmitEmptyWithLegacySemantics    // marshal
   142  	ParseBytesWithLooseRFC4648      // unmarshal
   143  	ParseTimeWithLooseRFC3339       // unmarshal
   144  	ReportErrorsWithLegacySemantics // marshal or unmarshal
   145  	StringifyWithLegacySemantics    // marshal or unmarshal
   146  	StringifyBoolsAndStrings        // marshal or unmarshal; for internal use by jsonv2.makeStructArshaler
   147  	UnmarshalAnyWithRawNumber       // unmarshal; for internal use by jsonv1.Decoder.UseNumber
   148  	UnmarshalArrayFromAnyLength     // unmarshal
   149  
   150  	maxArshalV1Flag
   151  )
   152  
   153  // bitsUsed is the number of bits used in the 64-bit boolean flags
   154  const bitsUsed = 42
   155  
   156  // Static compile check that bitsUsed and maxArshalV1Flag are in sync.
   157  const _ = uint64((1<<bitsUsed)-maxArshalV1Flag) + uint64(maxArshalV1Flag-(1<<bitsUsed))
   158  
   159  // Flags is a set of boolean flags.
   160  // If the presence bit is zero, then the value bit must also be zero.
   161  // The least-significant bit of both fields is always zero.
   162  //
   163  // Unlike Bools, which can represent a set of bools that are all true or false,
   164  // Flags represents a set of bools, each individually may be true or false.
   165  type Flags struct{ Presence, Values uint64 }
   166  
   167  // Join joins two sets of flags such that the latter takes precedence.
   168  func (dst *Flags) Join(src Flags) {
   169  	// Copy over all source presence bits over to the destination (using OR),
   170  	// then invert the source presence bits to clear out source value (using AND-NOT),
   171  	// then copy over source value bits over to the destination (using OR).
   172  	//	e.g., dst := Flags{Presence: 0b_1100_0011, Value: 0b_1000_0011}
   173  	//	e.g., src := Flags{Presence: 0b_0101_1010, Value: 0b_1001_0010}
   174  	dst.Presence |= src.Presence // e.g., 0b_1100_0011 | 0b_0101_1010 -> 0b_110_11011
   175  	dst.Values &= ^src.Presence  // e.g., 0b_1000_0011 & 0b_1010_0101 -> 0b_100_00001
   176  	dst.Values |= src.Values     // e.g., 0b_1000_0001 | 0b_1001_0010 -> 0b_100_10011
   177  }
   178  
   179  // Set sets both the presence and value for the provided bool (or set of bools).
   180  func (fs *Flags) Set(f Bools) {
   181  	// Select out the bits for the flag identifiers (everything except LSB),
   182  	// then set the presence for all the identifier bits (using OR),
   183  	// then invert the identifier bits to clear out the values (using AND-NOT),
   184  	// then copy over all the identifier bits to the value if LSB is 1.
   185  	//	e.g., fs := Flags{Presence: 0b_0101_0010, Value: 0b_0001_0010}
   186  	//	e.g., f := 0b_1001_0001
   187  	id := uint64(f) &^ uint64(1)  // e.g., 0b_1001_0001 & 0b_1111_1110 -> 0b_1001_0000
   188  	fs.Presence |= id             // e.g., 0b_0101_0010 | 0b_1001_0000 -> 0b_1101_0011
   189  	fs.Values &= ^id              // e.g., 0b_0001_0010 & 0b_0110_1111 -> 0b_0000_0010
   190  	fs.Values |= uint64(f&1) * id // e.g., 0b_0000_0010 | 0b_1001_0000 -> 0b_1001_0010
   191  }
   192  
   193  // Get reports whether the bool (or any of the bools) is true.
   194  // This is generally only used with a singular bool.
   195  // The value bit of f (i.e., the LSB) is ignored.
   196  func (fs Flags) Get(f Bools) bool {
   197  	return fs.Values&uint64(f) > 0
   198  }
   199  
   200  // Has reports whether the bool (or any of the bools) is set.
   201  // The value bit of f (i.e., the LSB) is ignored.
   202  func (fs Flags) Has(f Bools) bool {
   203  	return fs.Presence&uint64(f) > 0
   204  }
   205  
   206  // Clear clears both the presence and value for the provided bool or bools.
   207  // The value bit of f (i.e., the LSB) is ignored.
   208  func (fs *Flags) Clear(f Bools) {
   209  	// Invert f to produce a mask to clear all bits in f (using AND).
   210  	//	e.g., fs := Flags{Presence: 0b_0101_0010, Value: 0b_0001_0010}
   211  	//	e.g., f := 0b_0001_1000
   212  	mask := uint64(^f)  // e.g., 0b_0001_1000 -> 0b_1110_0111
   213  	fs.Presence &= mask // e.g., 0b_0101_0010 &  0b_1110_0111 -> 0b_0100_0010
   214  	fs.Values &= mask   // e.g., 0b_0001_0010 &  0b_1110_0111 -> 0b_0000_0010
   215  }
   216  

View as plain text