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  		FormatTag
    48  
    49  	// DefaultV1Flags is the set of boolean flags that default to true under
    50  	// v1 semantics. None of the non-boolean flags differ between v1 and v2.
    51  	DefaultV1Flags = 0 |
    52  		AllowDuplicateNames |
    53  		AllowInvalidUTF8 |
    54  		EscapeForHTML |
    55  		EscapeForJS |
    56  		PreserveRawStrings |
    57  		Deterministic |
    58  		FormatNilMapAsNull |
    59  		FormatNilSliceAsNull |
    60  		MatchCaseInsensitiveNames |
    61  		CallMethodsWithLegacySemantics |
    62  		FormatByteArrayAsArray |
    63  		FormatBytesWithLegacySemantics |
    64  		FormatDurationAsNano |
    65  		MatchCaseSensitiveDelimiter |
    66  		MergeWithLegacySemantics |
    67  		OmitEmptyWithLegacySemantics |
    68  		ParseBytesWithLooseRFC4648 |
    69  		ParseTimeWithLooseRFC3339 |
    70  		ReportErrorsWithLegacySemantics |
    71  		StringifyWithLegacySemantics |
    72  		UnmarshalArrayFromAnyLength
    73  
    74  	// AnyWhitespace reports whether the encoded output might have any whitespace.
    75  	AnyWhitespace = Multiline | SpaceAfterColon | SpaceAfterComma
    76  
    77  	// WhitespaceFlags is the set of flags related to whitespace formatting.
    78  	// In contrast to AnyWhitespace, this includes Indent and IndentPrefix
    79  	// as those settings take no effect if Multiline is false.
    80  	WhitespaceFlags = AnyWhitespace | Indent | IndentPrefix
    81  
    82  	// AnyEscape is the set of flags related to escaping in a JSON string.
    83  	AnyEscape = EscapeForHTML | EscapeForJS
    84  
    85  	// CanonicalizeNumbers is the set of flags related to raw number canonicalization.
    86  	CanonicalizeNumbers = CanonicalizeRawInts | CanonicalizeRawFloats
    87  
    88  	// TagFlags is the set of flags related to the presence of struct field tags.
    89  	// Tags have non-recursive effects, where the tag only applies to
    90  	// the top-level of the field value itself.
    91  	// Whenever descending into a JSON object or array, these flags are cleared.
    92  	TagFlags = StringTag | FormatTag
    93  )
    94  
    95  // Encoder and decoder flags.
    96  const (
    97  	initFlag Bools = 1 << iota // reserved for the boolean value itself
    98  
    99  	AllowDuplicateNames   // encode or decode
   100  	AllowInvalidUTF8      // encode or decode
   101  	WithinArshalCall      // encode or decode; for internal use by json.Marshal and json.Unmarshal
   102  	OmitTopLevelNewline   // encode only; for internal use by json.Marshal and json.MarshalWrite
   103  	PreserveRawStrings    // encode only
   104  	CanonicalizeRawInts   // encode only
   105  	CanonicalizeRawFloats // encode only
   106  	ReorderRawObjects     // encode only
   107  	EscapeForHTML         // encode only
   108  	EscapeForJS           // encode only
   109  	Multiline             // encode only
   110  	SpaceAfterColon       // encode only
   111  	SpaceAfterComma       // encode only
   112  	Indent                // encode only; non-boolean flag
   113  	IndentPrefix          // encode only; non-boolean flag
   114  	ByteLimit             // encode or decode; non-boolean flag
   115  	DepthLimit            // encode or decode; non-boolean flag
   116  
   117  	maxCoderFlag
   118  )
   119  
   120  // Marshal and Unmarshal flags (for v2).
   121  const (
   122  	_ Bools = (maxCoderFlag >> 1) << iota
   123  
   124  	StringifyNumbers          // marshal or unmarshal
   125  	Deterministic             // marshal only
   126  	FormatNilMapAsNull        // marshal only
   127  	FormatNilSliceAsNull      // marshal only
   128  	OmitZeroStructFields      // marshal only
   129  	MatchCaseInsensitiveNames // marshal or unmarshal
   130  	RejectUnknownMembers      // unmarshal only
   131  	Marshalers                // marshal only; non-boolean flag
   132  	Unmarshalers              // unmarshal only; non-boolean flag
   133  	StringTag                 // marshal or unmarshal
   134  	FormatTag                 // marshal or unmarshal; non-boolean flag
   135  	FormatTagSupported        // marshal or unmarshal
   136  
   137  	maxArshalV2Flag
   138  )
   139  
   140  // Marshal and Unmarshal flags (for v1).
   141  const (
   142  	_ Bools = (maxArshalV2Flag >> 1) << iota
   143  
   144  	CallMethodsWithLegacySemantics  // marshal or unmarshal
   145  	FormatByteArrayAsArray          // marshal or unmarshal
   146  	FormatBytesWithLegacySemantics  // marshal or unmarshal
   147  	FormatDurationAsNano            // marshal or unmarshal
   148  	MatchCaseSensitiveDelimiter     // marshal or unmarshal
   149  	MergeWithLegacySemantics        // unmarshal
   150  	OmitEmptyWithLegacySemantics    // marshal
   151  	ParseBytesWithLooseRFC4648      // unmarshal
   152  	ParseTimeWithLooseRFC3339       // unmarshal
   153  	ReportErrorsWithLegacySemantics // marshal or unmarshal
   154  	StringifyWithLegacySemantics    // marshal or unmarshal
   155  	UnmarshalAnyWithRawNumber       // unmarshal; for internal use by jsonv1.Decoder.UseNumber
   156  	UnmarshalArrayFromAnyLength     // unmarshal
   157  
   158  	maxArshalV1Flag
   159  )
   160  
   161  // bitsUsed is the number of bits used in the 64-bit boolean flags
   162  const bitsUsed = 43
   163  
   164  // Static compile check that bitsUsed and maxArshalV1Flag are in sync.
   165  const _ = uint64((1<<bitsUsed)-maxArshalV1Flag) + uint64(maxArshalV1Flag-(1<<bitsUsed))
   166  
   167  // Flags is a set of boolean flags.
   168  // If the presence bit is zero, then the value bit must also be zero.
   169  // The least-significant bit of both fields is always zero.
   170  //
   171  // Unlike Bools, which can represent a set of bools that are all true or false,
   172  // Flags represents a set of bools, each individually may be true or false.
   173  type Flags struct{ Presence, Values uint64 }
   174  
   175  // Join joins two sets of flags such that the latter takes precedence.
   176  func (dst *Flags) Join(src Flags) {
   177  	// Copy over all source presence bits over to the destination (using OR),
   178  	// then invert the source presence bits to clear out source value (using AND-NOT),
   179  	// then copy over source value bits over to the destination (using OR).
   180  	//	e.g., dst := Flags{Presence: 0b_1100_0011, Values: 0b_1000_0011}
   181  	//	e.g., src := Flags{Presence: 0b_0101_1010, Values: 0b_1001_0010}
   182  	dst.Presence |= src.Presence // e.g., 0b_1100_0011 | 0b_0101_1010 -> 0b_1101_1011
   183  	dst.Values &= ^src.Presence  // e.g., 0b_1000_0011 & 0b_1010_0101 -> 0b_1000_0001
   184  	dst.Values |= src.Values     // e.g., 0b_1000_0001 | 0b_1001_0010 -> 0b_1001_0011
   185  }
   186  
   187  // Set sets both the presence and value for the provided bool (or set of bools).
   188  func (fs *Flags) Set(f Bools) {
   189  	// Select out the bits for the flag identifiers (everything except LSB),
   190  	// then set the presence for all the identifier bits (using OR),
   191  	// then invert the identifier bits to clear out the values (using AND-NOT),
   192  	// then copy over all the identifier bits to the value if LSB is 1.
   193  	//	e.g., fs := Flags{Presence: 0b_0101_0010, Values: 0b_0001_0010}
   194  	//	e.g., f := 0b_1001_0001
   195  	id := uint64(f) &^ uint64(1)  // e.g., 0b_1001_0001 & 0b_1111_1110 -> 0b_1001_0000
   196  	fs.Presence |= id             // e.g., 0b_0101_0010 | 0b_1001_0000 -> 0b_1101_0010
   197  	fs.Values &= ^id              // e.g., 0b_0001_0010 & 0b_0110_1111 -> 0b_0000_0010
   198  	fs.Values |= uint64(f&1) * id // e.g., 0b_0000_0010 | 0b_1001_0000 -> 0b_1001_0010
   199  }
   200  
   201  // Get reports whether the bool (or any of the bools) is true.
   202  // This is generally only used with a singular bool.
   203  // The value bit of f (i.e., the LSB) is ignored.
   204  func (fs Flags) Get(f Bools) bool {
   205  	return fs.Values&uint64(f) > 0
   206  }
   207  
   208  // Has reports whether the bool (or any of the bools) is set.
   209  // The value bit of f (i.e., the LSB) is ignored.
   210  func (fs Flags) Has(f Bools) bool {
   211  	return fs.Presence&uint64(f) > 0
   212  }
   213  
   214  // Clear clears both the presence and value for the provided bool or bools.
   215  // The value bit of f (i.e., the LSB) is ignored.
   216  func (fs *Flags) Clear(f Bools) {
   217  	// Invert f to produce a mask to clear all bits in f (using AND).
   218  	//	e.g., fs := Flags{Presence: 0b_0101_0010, Values: 0b_0001_0010}
   219  	//	e.g., f := 0b_0001_1000
   220  	mask := uint64(^f)  // e.g., 0b_0001_1000 -> 0b_1110_0111
   221  	fs.Presence &= mask // e.g., 0b_0101_0010 &  0b_1110_0111 -> 0b_0100_0010
   222  	fs.Values &= mask   // e.g., 0b_0001_0010 &  0b_1110_0111 -> 0b_0000_0010
   223  }
   224  

View as plain text