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

View as plain text