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 booleans 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  
   136  	maxArshalV2Flag
   137  )
   138  
   139  // Marshal and Unmarshal flags (for v1).
   140  const (
   141  	_ Bools = (maxArshalV2Flag >> 1) << iota
   142  
   143  	CallMethodsWithLegacySemantics  // marshal or unmarshal
   144  	FormatByteArrayAsArray          // marshal or unmarshal
   145  	FormatBytesWithLegacySemantics  // marshal or unmarshal
   146  	FormatDurationAsNano            // marshal or unmarshal
   147  	MatchCaseSensitiveDelimiter     // marshal or unmarshal
   148  	MergeWithLegacySemantics        // unmarshal
   149  	OmitEmptyWithLegacySemantics    // marshal
   150  	ParseBytesWithLooseRFC4648      // unmarshal
   151  	ParseTimeWithLooseRFC3339       // unmarshal
   152  	ReportErrorsWithLegacySemantics // marshal or unmarshal
   153  	StringifyWithLegacySemantics    // marshal or unmarshal
   154  	UnmarshalAnyWithRawNumber       // unmarshal; for internal use by jsonv1.Decoder.UseNumber
   155  	UnmarshalArrayFromAnyLength     // unmarshal
   156  
   157  	maxArshalV1Flag
   158  )
   159  
   160  // bitsUsed is the number of bits used in the 64-bit boolean flags
   161  const bitsUsed = 42
   162  
   163  // Static compile check that bitsUsed and maxArshalV1Flag are in sync.
   164  const _ = uint64((1<<bitsUsed)-maxArshalV1Flag) + uint64(maxArshalV1Flag-(1<<bitsUsed))
   165  
   166  // Flags is a set of boolean flags.
   167  // If the presence bit is zero, then the value bit must also be zero.
   168  // The least-significant bit of both fields is always zero.
   169  //
   170  // Unlike Bools, which can represent a set of bools that are all true or false,
   171  // Flags represents a set of bools, each individually may be true or false.
   172  type Flags struct{ Presence, Values uint64 }
   173  
   174  // Join joins two sets of flags such that the latter takes precedence.
   175  func (dst *Flags) Join(src Flags) {
   176  	// Copy over all source presence bits over to the destination (using OR),
   177  	// then invert the source presence bits to clear out source value (using AND-NOT),
   178  	// then copy over source value bits over to the destination (using OR).
   179  	//	e.g., dst := Flags{Presence: 0b_1100_0011, Values: 0b_1000_0011}
   180  	//	e.g., src := Flags{Presence: 0b_0101_1010, Values: 0b_1001_0010}
   181  	dst.Presence |= src.Presence // e.g., 0b_1100_0011 | 0b_0101_1010 -> 0b_1101_1011
   182  	dst.Values &= ^src.Presence  // e.g., 0b_1000_0011 & 0b_1010_0101 -> 0b_1000_0001
   183  	dst.Values |= src.Values     // e.g., 0b_1000_0001 | 0b_1001_0010 -> 0b_1001_0011
   184  }
   185  
   186  // Set sets both the presence and value for the provided bool (or set of bools).
   187  func (fs *Flags) Set(f Bools) {
   188  	// Select out the bits for the flag identifiers (everything except LSB),
   189  	// then set the presence for all the identifier bits (using OR),
   190  	// then invert the identifier bits to clear out the values (using AND-NOT),
   191  	// then copy over all the identifier bits to the value if LSB is 1.
   192  	//	e.g., fs := Flags{Presence: 0b_0101_0010, Values: 0b_0001_0010}
   193  	//	e.g., f := 0b_1001_0001
   194  	id := uint64(f) &^ uint64(1)  // e.g., 0b_1001_0001 & 0b_1111_1110 -> 0b_1001_0000
   195  	fs.Presence |= id             // e.g., 0b_0101_0010 | 0b_1001_0000 -> 0b_1101_0010
   196  	fs.Values &= ^id              // e.g., 0b_0001_0010 & 0b_0110_1111 -> 0b_0000_0010
   197  	fs.Values |= uint64(f&1) * id // e.g., 0b_0000_0010 | 0b_1001_0000 -> 0b_1001_0010
   198  }
   199  
   200  // Get reports whether the bool (or any of the bools) is true.
   201  // This is generally only used with a singular bool.
   202  // The value bit of f (i.e., the LSB) is ignored.
   203  func (fs Flags) Get(f Bools) bool {
   204  	return fs.Values&uint64(f) > 0
   205  }
   206  
   207  // Has reports whether the bool (or any of the bools) is set.
   208  // The value bit of f (i.e., the LSB) is ignored.
   209  func (fs Flags) Has(f Bools) bool {
   210  	return fs.Presence&uint64(f) > 0
   211  }
   212  
   213  // Clear clears both the presence and value for the provided bool or bools.
   214  // The value bit of f (i.e., the LSB) is ignored.
   215  func (fs *Flags) Clear(f Bools) {
   216  	// Invert f to produce a mask to clear all bits in f (using AND).
   217  	//	e.g., fs := Flags{Presence: 0b_0101_0010, Values: 0b_0001_0010}
   218  	//	e.g., f := 0b_0001_1000
   219  	mask := uint64(^f)  // e.g., 0b_0001_1000 -> 0b_1110_0111
   220  	fs.Presence &= mask // e.g., 0b_0101_0010 &  0b_1110_0111 -> 0b_0100_0010
   221  	fs.Values &= mask   // e.g., 0b_0001_0010 &  0b_1110_0111 -> 0b_0000_0010
   222  }
   223  

View as plain text