@@ -49,6 +49,7 @@ internal partial class CborReader
4949 private bool _isEvenNumberOfDataItemsRead = true ; // required for indefinite-length map writes
5050 private Stack < ( CborMajorType type , int bytesRead , bool isEvenNumberOfDataItemsWritten , ulong ? remainingDataItems ) > ? _nestedDataItems ;
5151 private bool _isTagContext = false ; // true if reader is expecting a tagged value
52+ private CborReaderState _cachedState = CborReaderState . Unknown ; // caches the current reader state
5253
5354 // stores a reusable List allocation for keeping ranges in the buffer
5455 private List < ( int offset , int length ) > ? _rangeListAllocation = null ;
@@ -62,6 +63,16 @@ internal CborReader(ReadOnlyMemory<byte> buffer)
6263 public int BytesRemaining => _buffer . Length ;
6364
6465 public CborReaderState PeekState ( )
66+ {
67+ if ( _cachedState == CborReaderState . Unknown )
68+ {
69+ _cachedState = PeekStateCore ( ) ;
70+ }
71+
72+ return _cachedState ;
73+ }
74+
75+ private CborReaderState PeekStateCore ( )
6576 {
6677 if ( _remainingDataItems == 0 )
6778 {
@@ -289,6 +300,11 @@ private void PopDataItem(CborMajorType expectedType)
289300 _nestedDataItems . Pop ( ) ;
290301 _remainingDataItems = remainingItems ;
291302 _isEvenNumberOfDataItemsRead = isEvenNumberOfDataItemsWritten ;
303+ // Popping items from the stack can change the reader state
304+ // without necessarily needing to advance the buffer
305+ // (e.g. we're at the end of a definite-length collection).
306+ // We therefore need to invalidate the cache here.
307+ _cachedState = CborReaderState . Unknown ;
292308 }
293309
294310 private void AdvanceDataItemCounters ( )
@@ -302,6 +318,8 @@ private void AdvanceBuffer(int length)
302318 {
303319 _buffer = _buffer . Slice ( length ) ;
304320 _bytesRead += length ;
321+ // invalidate the state cache
322+ _cachedState = CborReaderState . Unknown ;
305323 }
306324
307325 private void EnsureBuffer ( int length )
@@ -373,6 +391,8 @@ private void RestoreCheckpoint(CborReaderCheckpoint checkpoint)
373391 _remainingDataItems = checkpoint . RemainingDataItems ;
374392 _isEvenNumberOfDataItemsRead = checkpoint . IsEvenNumberOfDataItemsRead ;
375393 _isTagContext = checkpoint . IsTagContext ;
394+ // invalidate the state cache
395+ _cachedState = CborReaderState . Unknown ;
376396 }
377397 }
378398
0 commit comments