|
3 | 3 | // See the LICENSE file in the project root for more information.
|
4 | 4 |
|
5 | 5 | using System;
|
6 |
| -using System.Collections.Generic; |
7 | 6 | using System.Text.Json;
|
8 | 7 |
|
9 | 8 | namespace Elastic.Clients.Elasticsearch.Serialization;
|
@@ -38,61 +37,146 @@ internal enum JsonTokenTypes
|
38 | 37 |
|
39 | 38 | internal static class JsonUnionSelector
|
40 | 39 | {
|
41 |
| - public static UnionTag ByTokenType(ref Utf8JsonReader reader, JsonSerializerOptions options, JsonTokenTypes first, JsonTokenTypes second) |
| 40 | + /// <summary> |
| 41 | + /// A selector function that always returns <see cref="UnionTag.None"/>. |
| 42 | + /// </summary> |
| 43 | + /// <param name="reader">A reference to the <see cref="Utf8JsonReader"/> instance.</param> |
| 44 | + /// <param name="options">The <see cref="JsonSerializerOptions"/> to use.</param> |
| 45 | + /// <returns>A static value of <see cref="UnionTag.None"/>.</returns> |
| 46 | + public static UnionTag None(ref Utf8JsonReader reader, JsonSerializerOptions options) |
| 47 | + { |
| 48 | + _ = reader; |
| 49 | + _ = options; |
| 50 | + return UnionTag.None; |
| 51 | + } |
| 52 | + |
| 53 | + /// <summary> |
| 54 | + /// A selector function that always returns <see cref="UnionTag.T1"/>. |
| 55 | + /// </summary> |
| 56 | + /// <param name="reader">A reference to the <see cref="Utf8JsonReader"/> instance.</param> |
| 57 | + /// <param name="options">The <see cref="JsonSerializerOptions"/> to use.</param> |
| 58 | + /// <returns>A static value of <see cref="UnionTag.T1"/>.</returns> |
| 59 | + public static UnionTag T1(ref Utf8JsonReader reader, JsonSerializerOptions options) |
42 | 60 | {
|
43 | 61 | _ = reader;
|
44 | 62 | _ = options;
|
| 63 | + return UnionTag.T1; |
| 64 | + } |
45 | 65 |
|
46 |
| - if (((int)first & (1 << (int)reader.TokenType)) is not 0) |
| 66 | + /// <summary> |
| 67 | + /// A selector function that always returns <see cref="UnionTag.T2"/>. |
| 68 | + /// </summary> |
| 69 | + /// <param name="reader">A reference to the <see cref="Utf8JsonReader"/> instance.</param> |
| 70 | + /// <param name="options">The <see cref="JsonSerializerOptions"/> to use.</param> |
| 71 | + /// <returns>A static value of <see cref="UnionTag.T2"/>.</returns> |
| 72 | + public static UnionTag T2(ref Utf8JsonReader reader, JsonSerializerOptions options) |
| 73 | + { |
| 74 | + _ = reader; |
| 75 | + _ = options; |
| 76 | + return UnionTag.T2; |
| 77 | + } |
| 78 | + |
| 79 | + // We avoid using a `params` array for performance reasons. Create `Match()` overloads with additional parameters as needed. |
| 80 | + public static UnionTag Match(ref Utf8JsonReader reader, JsonSerializerOptions options, JsonUnionSelectorFunc case1, JsonUnionSelectorFunc case2) |
| 81 | + { |
| 82 | + if (case1(ref reader, options) is var tag1 and not UnionTag.None) |
47 | 83 | {
|
48 |
| - return UnionTag.T1; |
| 84 | + return tag1; |
49 | 85 | }
|
50 | 86 |
|
51 |
| - if (((int)second & (1 << (int)reader.TokenType)) is not 0) |
| 87 | + if (case2(ref reader, options) is var tag2 and not UnionTag.None) |
52 | 88 | {
|
53 |
| - return UnionTag.T2; |
| 89 | + return tag2; |
54 | 90 | }
|
55 | 91 |
|
56 | 92 | return UnionTag.None;
|
57 | 93 | }
|
58 | 94 |
|
59 |
| - public static UnionTag ByPropertyOfT1(ref Utf8JsonReader reader, JsonSerializerOptions options, string name) |
| 95 | + public static UnionTag MatchTokenTypes(ref Utf8JsonReader reader, JsonSerializerOptions options, JsonTokenTypes types, JsonUnionSelectorFunc next) |
60 | 96 | {
|
61 |
| - reader.ValidateToken(JsonTokenType.StartObject); |
62 |
| - |
63 |
| - var internalReader = reader; |
64 |
| - |
65 |
| - while (internalReader.Read() && (internalReader.TokenType is JsonTokenType.PropertyName)) |
| 97 | + if (((int)types & (1 << (int)reader.TokenType)) is not 0) |
66 | 98 | {
|
67 |
| - if (internalReader.ValueTextEquals(name)) |
68 |
| - { |
69 |
| - return UnionTag.T1; |
70 |
| - } |
71 |
| - |
72 |
| - internalReader.Read(); |
73 |
| - internalReader.Skip(); |
| 99 | + return next(ref reader, options); |
74 | 100 | }
|
75 | 101 |
|
76 |
| - return UnionTag.T2; |
| 102 | + return UnionTag.None; |
77 | 103 | }
|
78 | 104 |
|
79 |
| - public static UnionTag ByPropertyOfT2(ref Utf8JsonReader reader, JsonSerializerOptions options, string name) |
| 105 | + public static UnionTag MatchProperty(ref Utf8JsonReader reader, JsonSerializerOptions options, string name, UnionTag result) |
80 | 106 | {
|
81 |
| - reader.ValidateToken(JsonTokenType.StartObject); |
| 107 | + if (reader.TokenType is not JsonTokenType.StartObject) |
| 108 | + { |
| 109 | + return UnionTag.None; |
| 110 | + } |
82 | 111 |
|
83 | 112 | var internalReader = reader;
|
84 | 113 |
|
85 | 114 | while (internalReader.Read() && (internalReader.TokenType is JsonTokenType.PropertyName))
|
86 | 115 | {
|
87 | 116 | if (internalReader.ValueTextEquals(name))
|
88 | 117 | {
|
89 |
| - return UnionTag.T2; |
| 118 | + return result; |
90 | 119 | }
|
91 | 120 |
|
92 | 121 | internalReader.Read();
|
93 | 122 | internalReader.Skip();
|
94 | 123 | }
|
95 | 124 |
|
96 |
| - return UnionTag.T1; |
| 125 | + return UnionTag.None; |
| 126 | + } |
| 127 | + |
| 128 | + /// <summary> |
| 129 | + /// A selector function that selects a union variant based on the current JSON token type. |
| 130 | + /// </summary> |
| 131 | + /// <param name="reader">A reference to the <see cref="Utf8JsonReader"/> instance.</param> |
| 132 | + /// <param name="options">The <see cref="JsonSerializerOptions"/> to use.</param> |
| 133 | + /// <param name="first">The JSON token types that resolve to <see cref="UnionTag.T1"/>.</param> |
| 134 | + /// <param name="second">The JSON token types that resolve to <see cref="UnionTag.T2"/>.</param> |
| 135 | + /// <returns> |
| 136 | + /// Either <see cref="UnionTag.T1"/> or <see cref="UnionTag.T2"/> if the current token type of <paramref name="reader"/> matches one |
| 137 | + /// of the provided JSON token types or <see cref="UnionTag.None"/>, if not. |
| 138 | + /// </returns> |
| 139 | + public static UnionTag ByTokenType(ref Utf8JsonReader reader, JsonSerializerOptions options, JsonTokenTypes first, JsonTokenTypes second) |
| 140 | + { |
| 141 | + return Match(ref reader, options, |
| 142 | + (ref r, o) => MatchTokenTypes(ref r, o, first, T1), |
| 143 | + (ref r, o) => MatchTokenTypes(ref r, o, second, T2) |
| 144 | + ); |
| 145 | + } |
| 146 | + |
| 147 | + /// <summary> |
| 148 | + /// A selector function that selects a union variant based on the current JSON token type. |
| 149 | + /// </summary> |
| 150 | + /// <param name="reader">A reference to the <see cref="Utf8JsonReader"/> instance.</param> |
| 151 | + /// <param name="options">The <see cref="JsonSerializerOptions"/> to use.</param> |
| 152 | + /// <param name="name">The property name to look for.</param> |
| 153 | + /// <returns> |
| 154 | + /// <see cref="UnionTag.T1"/> if the <paramref name="reader"/> points to an object that contains a property of the given |
| 155 | + /// <paramref name="name"/> or <see cref="UnionTag.T2"/>, if not. |
| 156 | + /// </returns> |
| 157 | + public static UnionTag ByPropertyOfT1(ref Utf8JsonReader reader, JsonSerializerOptions options, string name) |
| 158 | + { |
| 159 | + return Match(ref reader, options, |
| 160 | + (ref r, o) => MatchProperty(ref r, o, name, UnionTag.T1), |
| 161 | + T2 |
| 162 | + ); |
| 163 | + } |
| 164 | + |
| 165 | + /// <summary> |
| 166 | + /// A selector function that selects a union variant based on the current JSON token type. |
| 167 | + /// </summary> |
| 168 | + /// <param name="reader">A reference to the <see cref="Utf8JsonReader"/> instance.</param> |
| 169 | + /// <param name="options">The <see cref="JsonSerializerOptions"/> to use.</param> |
| 170 | + /// <param name="name">The property name to look for.</param> |
| 171 | + /// <returns> |
| 172 | + /// <see cref="UnionTag.T2"/> if the <paramref name="reader"/> points to an object that contains a property of the given |
| 173 | + /// <paramref name="name"/> or <see cref="UnionTag.T1"/>, if not. |
| 174 | + /// </returns> |
| 175 | + public static UnionTag ByPropertyOfT2(ref Utf8JsonReader reader, JsonSerializerOptions options, string name) |
| 176 | + { |
| 177 | + return Match(ref reader, options, |
| 178 | + (ref r, o) => MatchProperty(ref r, o, name, UnionTag.T2), |
| 179 | + T1 |
| 180 | + ); |
97 | 181 | }
|
98 | 182 | }
|
0 commit comments