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