Skip to content

Commit 61a8cb1

Browse files
[CBOR] Implement support for tagged types (#34767)
* [CBOR] Implement support for dateTime types * fix test errors * refine RFC3339 dateTime formatting logic * add invalid date string tests * Implement BigInteger support * initial decimal support implementation * use stack allocated buffers instead of thread local buffers * add test cases for negative unix time dates * add WriteNegativeIntegerEncoding tests * implement checkpointing logic and apply to SkipValue() method * implement checkpointing for tagged type readers * store reader checkpoints in the stack * add tests for rollback logic in tagged type readers * add tested that utilizes nested reader state rollbacks * use culture invariant decimal parsing in tests * add WriteUnixTimeSeconds(double) method * split unix time and string time readers into separate methods * add WriteUnixTestSeconds invalid input test * add support and tests for indefinite-length buffers in tagged types * add PeekTag() tests * add Read/WriteInt32() convenience methods * add pervasive buffer postcondition checks on negative reader tests; fix related bug. * add comment on DateTime parsing * Rename CborReader.Peek() to CborReader.PeekState() * Use correct overload for int32 handling * add caching to CborReader.PeekState() * Use "simple" instead of "special" for cbor major type * add Write/ReadUInt32() convenience methods * add uint32 negative tests
1 parent ab4a117 commit 61a8cb1

27 files changed

+1753
-448
lines changed

src/libraries/System.Security.Cryptography.Encoding/tests/Cbor.Tests/CborReaderTests.Array.cs

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public static void ReadArray_SimpleValues_HappyPath(object[] expectedValues, str
2727
byte[] encoding = hexEncoding.HexToByteArray();
2828
var reader = new CborReader(encoding);
2929
Helpers.VerifyArray(reader, expectedValues);
30-
Assert.Equal(CborReaderState.Finished, reader.Peek());
30+
Assert.Equal(CborReaderState.Finished, reader.PeekState());
3131
}
3232

3333
[Theory]
@@ -39,7 +39,7 @@ public static void ReadArray_NestedValues_HappyPath(object[] expectedValues, str
3939
byte[] encoding = hexEncoding.HexToByteArray();
4040
var reader = new CborReader(encoding);
4141
Helpers.VerifyArray(reader, expectedValues);
42-
Assert.Equal(CborReaderState.Finished, reader.Peek());
42+
Assert.Equal(CborReaderState.Finished, reader.PeekState());
4343
}
4444

4545
[Theory]
@@ -55,7 +55,7 @@ public static void ReadArray_IndefiniteLength_HappyPath(object[] expectedValues,
5555
byte[] encoding = hexEncoding.HexToByteArray();
5656
var reader = new CborReader(encoding);
5757
Helpers.VerifyArray(reader, expectedValues, expectDefiniteLengthCollections: false);
58-
Assert.Equal(CborReaderState.Finished, reader.Peek());
58+
Assert.Equal(CborReaderState.Finished, reader.PeekState());
5959
}
6060

6161
[Theory]
@@ -75,7 +75,9 @@ public static void ReadArray_DefiniteLengthExceeded_ShouldThrowInvalidOperationE
7575
reader.ReadInt64();
7676
}
7777

78+
int bytesRemaining = reader.BytesRemaining;
7879
Assert.Throws<InvalidOperationException>(() => reader.ReadInt64());
80+
Assert.Equal(bytesRemaining, reader.BytesRemaining);
7981
}
8082

8183
[Theory]
@@ -109,12 +111,12 @@ public static void ReadArray_IndefiniteLength_MissingBreakByte_ShouldReportEndOf
109111
byte[] encoding = hexEncoding.HexToByteArray();
110112
var reader = new CborReader(encoding);
111113
reader.ReadStartArray();
112-
while (reader.Peek() == CborReaderState.UnsignedInteger)
114+
while (reader.PeekState() == CborReaderState.UnsignedInteger)
113115
{
114116
reader.ReadInt64();
115117
}
116118

117-
Assert.Equal(CborReaderState.EndOfData, reader.Peek());
119+
Assert.Equal(CborReaderState.EndOfData, reader.PeekState());
118120
}
119121

120122
[Theory]
@@ -131,7 +133,9 @@ public static void ReadArray_IndefiniteLength_PrematureEndArrayCall_ShouldThrowI
131133
reader.ReadInt64();
132134
}
133135

136+
int bytesRemaining = reader.BytesRemaining;
134137
Assert.Throws<InvalidOperationException>(() => reader.ReadEndArray());
138+
Assert.Equal(bytesRemaining, reader.BytesRemaining);
135139
}
136140

137141
[Theory]
@@ -150,7 +154,9 @@ public static void EndReadArray_DefiniteLengthNotMet_ShouldThrowInvalidOperation
150154
reader.ReadInt64();
151155
}
152156

157+
int bytesRemaining = reader.BytesRemaining;
153158
Assert.Throws<InvalidOperationException>(() => reader.ReadEndArray());
159+
Assert.Equal(bytesRemaining, reader.BytesRemaining);
154160
}
155161

156162
[Theory]
@@ -172,7 +178,9 @@ public static void EndReadArray_DefiniteLengthNotMet_WithNestedData_ShouldThrowI
172178
reader.ReadEndArray();
173179
}
174180

181+
int bytesRemaining = reader.BytesRemaining;
175182
Assert.Throws<InvalidOperationException>(() => reader.ReadEndArray());
183+
Assert.Equal(bytesRemaining, reader.BytesRemaining);
176184
}
177185

178186
[Fact]
@@ -199,7 +207,9 @@ public static void ReadArray_IncorrectDefiniteLength_ShouldThrowFormatException(
199207
reader.ReadInt64();
200208
}
201209

210+
int bytesRemaining = reader.BytesRemaining;
202211
Assert.Throws<FormatException>(() => reader.ReadInt64());
212+
Assert.Equal(bytesRemaining, reader.BytesRemaining);
203213
}
204214

205215
[Theory]
@@ -221,7 +231,9 @@ public static void ReadArray_IncorrectDefiniteLength_NestedValues_ShouldThrowFor
221231
reader.ReadEndArray();
222232
}
223233

234+
int bytesRemaining = reader.BytesRemaining;
224235
Assert.Throws<FormatException>(() => reader.ReadInt64());
236+
Assert.Equal(bytesRemaining, reader.BytesRemaining);
225237
}
226238

227239
[Fact]
@@ -231,6 +243,7 @@ public static void ReadStartArray_EmptyBuffer_ShouldThrowFormatException()
231243
var reader = new CborReader(encoding);
232244

233245
Assert.Throws<FormatException>(() => reader.ReadStartArray());
246+
Assert.Equal(encoding.Length, reader.BytesRemaining);
234247
}
235248

236249
[Theory]
@@ -244,9 +257,11 @@ public static void ReadStartArray_EmptyBuffer_ShouldThrowFormatException()
244257
[InlineData("fb3ff199999999999a")] // 1.1
245258
public static void ReadStartArray_InvalidType_ShouldThrowInvalidOperationException(string hexEncoding)
246259
{
247-
byte[] data = hexEncoding.HexToByteArray();
248-
var reader = new CborReader(data);
260+
byte[] encoding = hexEncoding.HexToByteArray();
261+
var reader = new CborReader(encoding);
262+
249263
Assert.Throws<InvalidOperationException>(() => reader.ReadStartArray());
264+
Assert.Equal(encoding.Length, reader.BytesRemaining);
250265
}
251266

252267
[Theory]
@@ -261,22 +276,24 @@ public static void ReadStartArray_InvalidType_ShouldThrowInvalidOperationExcepti
261276
[InlineData("9b00000000000000")]
262277
public static void ReadStartArray_InvalidData_ShouldThrowFormatException(string hexEncoding)
263278
{
264-
byte[] data = hexEncoding.HexToByteArray();
265-
var reader = new CborReader(data);
279+
byte[] encoding = hexEncoding.HexToByteArray();
280+
var reader = new CborReader(encoding);
266281

267282
Assert.Throws<FormatException>(() => reader.ReadStartArray());
283+
Assert.Equal(encoding.Length, reader.BytesRemaining);
268284
}
269285

270286
[Theory]
271-
[InlineData("81")]
272-
[InlineData("830102")]
287+
[InlineData("82")]
288+
[InlineData("870102")]
273289
[InlineData("9b7fffffffffffffff")] // long.MaxValue
274290
public static void ReadStartArray_BufferTooSmall_ShouldThrowFormatException(string hexEncoding)
275291
{
276-
byte[] data = hexEncoding.HexToByteArray();
277-
var reader = new CborReader(data);
292+
byte[] encoding = hexEncoding.HexToByteArray();
293+
var reader = new CborReader(encoding);
278294

279295
Assert.Throws<FormatException>(() => reader.ReadStartArray());
296+
Assert.Equal(encoding.Length, reader.BytesRemaining);
280297
}
281298
}
282299
}

src/libraries/System.Security.Cryptography.Encoding/tests/Cbor.Tests/CborReaderTests.Helpers.cs

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,18 @@ public static void VerifyValue(CborReader reader, object expectedValue, bool exp
1818
switch (expectedValue)
1919
{
2020
case null:
21-
Assert.Equal(CborReaderState.Null, reader.Peek());
21+
Assert.Equal(CborReaderState.Null, reader.PeekState());
2222
reader.ReadNull();
2323
break;
2424
case bool expected:
25-
Assert.Equal(CborReaderState.Boolean, reader.Peek());
25+
Assert.Equal(CborReaderState.Boolean, reader.PeekState());
2626
bool b = reader.ReadBoolean();
2727
Assert.Equal(expected, b);
2828
break;
2929
case int expected:
3030
VerifyPeekInteger(reader, isUnsignedInteger: expected >= 0);
31-
long i = reader.ReadInt64();
32-
Assert.Equal(expected, (int)i);
31+
int i = reader.ReadInt32();
32+
Assert.Equal(expected, i);
3333
break;
3434
case long expected:
3535
VerifyPeekInteger(reader, isUnsignedInteger: expected >= 0);
@@ -42,47 +42,47 @@ public static void VerifyValue(CborReader reader, object expectedValue, bool exp
4242
Assert.Equal(expected, u);
4343
break;
4444
case float expected:
45-
Assert.Equal(CborReaderState.SinglePrecisionFloat, reader.Peek());
45+
Assert.Equal(CborReaderState.SinglePrecisionFloat, reader.PeekState());
4646
float f = reader.ReadSingle();
4747
Assert.Equal(expected, f);
4848
break;
4949
case double expected:
50-
Assert.Equal(CborReaderState.DoublePrecisionFloat, reader.Peek());
50+
Assert.Equal(CborReaderState.DoublePrecisionFloat, reader.PeekState());
5151
double d = reader.ReadDouble();
5252
Assert.Equal(expected, d);
5353
break;
5454
case string expected:
55-
Assert.Equal(CborReaderState.TextString, reader.Peek());
55+
Assert.Equal(CborReaderState.TextString, reader.PeekState());
5656
string s = reader.ReadTextString();
5757
Assert.Equal(expected, s);
5858
break;
5959
case byte[] expected:
60-
Assert.Equal(CborReaderState.ByteString, reader.Peek());
60+
Assert.Equal(CborReaderState.ByteString, reader.PeekState());
6161
byte[] bytes = reader.ReadByteString();
6262
Assert.Equal(expected.ByteArrayToHex(), bytes.ByteArrayToHex());
6363
break;
6464
case string[] expectedChunks:
65-
Assert.Equal(CborReaderState.StartTextString, reader.Peek());
65+
Assert.Equal(CborReaderState.StartTextString, reader.PeekState());
6666
reader.ReadStartTextStringIndefiniteLength();
6767
foreach(string expectedChunk in expectedChunks)
6868
{
69-
Assert.Equal(CborReaderState.TextString, reader.Peek());
69+
Assert.Equal(CborReaderState.TextString, reader.PeekState());
7070
string chunk = reader.ReadTextString();
7171
Assert.Equal(expectedChunk, chunk);
7272
}
73-
Assert.Equal(CborReaderState.EndTextString, reader.Peek());
73+
Assert.Equal(CborReaderState.EndTextString, reader.PeekState());
7474
reader.ReadEndTextStringIndefiniteLength();
7575
break;
7676
case byte[][] expectedChunks:
77-
Assert.Equal(CborReaderState.StartByteString, reader.Peek());
77+
Assert.Equal(CborReaderState.StartByteString, reader.PeekState());
7878
reader.ReadStartByteStringIndefiniteLength();
7979
foreach (byte[] expectedChunk in expectedChunks)
8080
{
81-
Assert.Equal(CborReaderState.ByteString, reader.Peek());
81+
Assert.Equal(CborReaderState.ByteString, reader.PeekState());
8282
byte[] chunk = reader.ReadByteString();
8383
Assert.Equal(expectedChunk.ByteArrayToHex(), chunk.ByteArrayToHex());
8484
}
85-
Assert.Equal(CborReaderState.EndByteString, reader.Peek());
85+
Assert.Equal(CborReaderState.EndByteString, reader.PeekState());
8686
reader.ReadEndByteStringIndefiniteLength();
8787
break;
8888

@@ -99,13 +99,13 @@ public static void VerifyValue(CborReader reader, object expectedValue, bool exp
9999
static void VerifyPeekInteger(CborReader reader, bool isUnsignedInteger)
100100
{
101101
CborReaderState expectedState = isUnsignedInteger ? CborReaderState.UnsignedInteger : CborReaderState.NegativeInteger;
102-
Assert.Equal(expectedState, reader.Peek());
102+
Assert.Equal(expectedState, reader.PeekState());
103103
}
104104
}
105105

106106
public static void VerifyArray(CborReader reader, object[] expectedValues, bool expectDefiniteLengthCollections = true)
107107
{
108-
Assert.Equal(CborReaderState.StartArray, reader.Peek());
108+
Assert.Equal(CborReaderState.StartArray, reader.PeekState());
109109

110110
ulong? length = reader.ReadStartArray();
111111

@@ -124,7 +124,7 @@ public static void VerifyArray(CborReader reader, object[] expectedValues, bool
124124
VerifyValue(reader, value);
125125
}
126126

127-
Assert.Equal(CborReaderState.EndArray, reader.Peek());
127+
Assert.Equal(CborReaderState.EndArray, reader.PeekState());
128128
reader.ReadEndArray();
129129
}
130130

@@ -135,7 +135,7 @@ public static void VerifyMap(CborReader reader, object[] expectedValues, bool ex
135135
throw new ArgumentException($"cbor map expected values missing '{CborWriterTests.Helpers.MapPrefixIdentifier}' prefix.");
136136
}
137137

138-
Assert.Equal(CborReaderState.StartMap, reader.Peek());
138+
Assert.Equal(CborReaderState.StartMap, reader.PeekState());
139139

140140
ulong? length = reader.ReadStartMap();
141141

@@ -154,7 +154,7 @@ public static void VerifyMap(CborReader reader, object[] expectedValues, bool ex
154154
VerifyValue(reader, value);
155155
}
156156

157-
Assert.Equal(CborReaderState.EndMap, reader.Peek());
157+
Assert.Equal(CborReaderState.EndMap, reader.PeekState());
158158
reader.ReadEndMap();
159159
}
160160
}

0 commit comments

Comments
 (0)