@@ -16,9 +16,9 @@ internal open class CborReader(override val cbor: Cbor, protected val parser: Cb
16
16
CborDecoder {
17
17
18
18
override fun decodeCborElement (): CborElement =
19
- when (parser) {
20
- is CborParser -> CborTreeReader (cbor.configuration, parser).read()
21
- is StructuredCborParser -> parser.element
19
+ when (parser) {
20
+ is CborParser -> CborTreeReader (cbor.configuration, parser).read()
21
+ is StructuredCborParser -> parser.element
22
22
}
23
23
24
24
@@ -58,7 +58,7 @@ internal open class CborReader(override val cbor: Cbor, protected val parser: Cb
58
58
}
59
59
60
60
override fun endStructure (descriptor : SerialDescriptor ) {
61
- if (! finiteMode) parser.end()
61
+ if (! finiteMode || parser is StructuredCborParser ) parser.end()
62
62
}
63
63
64
64
override fun decodeElementIndex (descriptor : SerialDescriptor ): Int {
@@ -158,7 +158,8 @@ internal open class CborReader(override val cbor: Cbor, protected val parser: Cb
158
158
}
159
159
}
160
160
161
- internal class CborParser (private val input : ByteArrayInput , private val verifyObjectTags : Boolean ) : CborParserInterface {
161
+ internal class CborParser (private val input : ByteArrayInput , private val verifyObjectTags : Boolean ) :
162
+ CborParserInterface {
162
163
var curByte: Int = - 1
163
164
164
165
init {
@@ -196,7 +197,7 @@ internal class CborParser(private val input: ByteArrayInput, private val verifyO
196
197
}
197
198
}
198
199
199
- override fun nextTag (): ULong {
200
+ fun nextTag (): ULong {
200
201
if ((curByte shr 5 ) != 6 ) {
201
202
throw CborDecodingException (" Expected tag (major type 6), got major type ${curByte shr 5 } " )
202
203
}
@@ -554,165 +555,156 @@ private fun Iterable<ByteArray>.flatten(): ByteArray {
554
555
return output
555
556
}
556
557
557
- private typealias ElementHolder = Pair <MutableList <ULong >, CborElement >
558
- private val ElementHolder .tags: MutableList <ULong > get() = first
559
- private val ElementHolder .element: CborElement get() = second
560
- internal class StructuredCborParser (val element : CborElement , private val verifyObjectTags : Boolean ) : CborParserInterface {
561
-
562
558
563
- internal var current : ElementHolder = element.tags.toMutableList() to element
564
- private var listIterator : Iterator < CborElement > ? = null
559
+ internal class StructuredCborParser ( internal val element : CborElement , private val verifyObjectTags : Boolean ) :
560
+ CborParserInterface {
565
561
566
- // Implementation of methods needed for CborTreeReader
567
- override fun nextTag (): ULong {
568
- if (current.tags.isEmpty()) {
569
- throw CborDecodingException ( " Expected tag, but no tags found on current element " )
570
- }
571
- return current.tags.removeFirst ()
572
- }
573
-
574
- override fun isNull () : Boolean {
575
- // TODO this is a bit wonky! if we are inside a map, we want to skip over the key, and check the value,
576
- // so the below call is not what it should be!
577
- processTags( null )
578
- return current.element is CborNull
562
+
563
+ internal var currentElement = element
564
+ private var listIterator : ListIterator < CborElement > ? = null
565
+ private var isMap = false
566
+ private val isMapStack = ArrayDeque < Boolean >()
567
+ private val layerStack = ArrayDeque < ListIterator < CborElement > ? > ()
568
+
569
+ override fun isNull (): Boolean {
570
+ return if (isMap) {
571
+ val isNull = listIterator !! .next() is CborNull
572
+ listIterator !! .previous()
573
+ isNull
574
+ } else currentElement is CborNull
579
575
}
580
-
576
+
581
577
override fun isEnd () = when {
582
578
listIterator != null -> ! listIterator!! .hasNext()
583
579
else -> false
584
580
}
585
-
581
+
586
582
override fun end () {
587
583
// Reset iterators when ending a structure
588
- listIterator = null
584
+ isMap = isMapStack.removeLast()
585
+ listIterator = layerStack.removeLast()
589
586
}
590
587
591
588
override fun startArray (tags : ULongArray? ): Int {
592
589
processTags(tags)
593
- if (current.element !is CborList ) {
594
- throw CborDecodingException (" Expected array, got ${current.element::class .simpleName} " )
595
- }
596
-
597
- val list = current.element as CborList
598
- listIterator = list.iterator()
590
+ if (currentElement !is CborList ) {
591
+ throw CborDecodingException (" Expected array, got ${currentElement::class .simpleName} " )
592
+ }
593
+ isMapStack+ = isMap
594
+ layerStack+ = listIterator
595
+ isMap = false
596
+ val list = currentElement as CborList
597
+ listIterator = list.listIterator()
599
598
return list.size
600
599
}
601
-
600
+
602
601
override fun startMap (tags : ULongArray? ): Int {
603
602
processTags(tags)
604
- if (current.element !is CborMap ) {
605
- throw CborDecodingException (" Expected map, got ${current.element ::class .simpleName} " )
603
+ if (currentElement !is CborMap ) {
604
+ throw CborDecodingException (" Expected map, got ${currentElement ::class .simpleName} " )
606
605
}
607
-
608
- val map = current.element as CborMap
606
+ layerStack+ = listIterator
607
+ isMapStack+ = isMap
608
+ isMap = true
609
+
610
+ val map = currentElement as CborMap
609
611
// zip key, value, key, value, ... pairs to mirror byte-layout of CBOR map
610
- listIterator = map.entries.flatMap { listOf (it.key, it.value) }.iterator ()
612
+ listIterator = map.entries.flatMap { listOf (it.key, it.value) }.listIterator ()
611
613
return map.size // cbor map size is the size of the map, not the doubled size of the flattened pairs
612
614
}
613
-
615
+
614
616
override fun nextNull (tags : ULongArray? ): Nothing? {
615
617
processTags(tags)
616
- if (current.element !is CborNull ) {
617
- throw CborDecodingException (" Expected null, got ${current.element ::class .simpleName} " )
618
+ if (currentElement !is CborNull ) {
619
+ throw CborDecodingException (" Expected null, got ${currentElement ::class .simpleName} " )
618
620
}
619
621
return null
620
622
}
621
-
623
+
622
624
override fun nextBoolean (tags : ULongArray? ): Boolean {
623
625
processTags(tags)
624
- if (current.element !is CborBoolean ) {
625
- throw CborDecodingException (" Expected boolean, got ${current.element ::class .simpleName} " )
626
+ if (currentElement !is CborBoolean ) {
627
+ throw CborDecodingException (" Expected boolean, got ${currentElement ::class .simpleName} " )
626
628
}
627
- return (current.element as CborBoolean ).value
629
+ return (currentElement as CborBoolean ).value
628
630
}
629
-
631
+
630
632
override fun nextNumber (tags : ULongArray? ): Long {
631
633
processTags(tags)
632
- return when (current.element ) {
633
- is CborPositiveInt -> (current.element as CborPositiveInt ).value.toLong()
634
- is CborNegativeInt -> (current.element as CborNegativeInt ).value
635
- else -> throw CborDecodingException (" Expected number, got ${current.element ::class .simpleName} " )
634
+ return when (currentElement ) {
635
+ is CborPositiveInt -> (currentElement as CborPositiveInt ).value.toLong()
636
+ is CborNegativeInt -> (currentElement as CborNegativeInt ).value
637
+ else -> throw CborDecodingException (" Expected number, got ${currentElement ::class .simpleName} " )
636
638
}
637
639
}
638
-
640
+
639
641
override fun nextString (tags : ULongArray? ): String {
640
642
processTags(tags)
641
-
642
- // Special handling for polymorphic serialization
643
- // If we have a CborList with a string as first element, return that string
644
- if (current.element is CborList && (current.element as CborList ).isNotEmpty() && (current.element as CborList )[0 ] is CborString ) {
645
- val stringElement = (current.element as CborList )[0 ] as CborString
646
- // Move to the next element (the map) for subsequent operations
647
- current = (current.element as CborList )[1 ].tags.toMutableList() to (current.element as CborList )[1 ]
648
- return stringElement.value
649
- }
650
-
651
- if (current.element !is CborString ) {
652
- throw CborDecodingException (" Expected string, got ${current.element::class .simpleName} " )
653
- }
654
- return (current.element as CborString ).value
655
- }
656
-
643
+ if (currentElement !is CborString ) {
644
+ throw CborDecodingException (" Expected string, got ${currentElement::class .simpleName} " )
645
+ }
646
+ return (currentElement as CborString ).value
647
+ }
648
+
657
649
override fun nextByteString (tags : ULongArray? ): ByteArray {
658
650
processTags(tags)
659
- if (current.element !is CborByteString ) {
660
- throw CborDecodingException (" Expected byte string, got ${current.element ::class .simpleName} " )
651
+ if (currentElement !is CborByteString ) {
652
+ throw CborDecodingException (" Expected byte string, got ${currentElement ::class .simpleName} " )
661
653
}
662
- return (current.element as CborByteString ).value
654
+ return (currentElement as CborByteString ).value
663
655
}
664
-
656
+
665
657
override fun nextDouble (tags : ULongArray? ): Double {
666
658
processTags(tags)
667
- return when (current.element ) {
668
- is CborDouble -> (current.element as CborDouble ).value
669
- else -> throw CborDecodingException (" Expected double, got ${current.element ::class .simpleName} " )
659
+ return when (currentElement ) {
660
+ is CborDouble -> (currentElement as CborDouble ).value
661
+ else -> throw CborDecodingException (" Expected double, got ${currentElement ::class .simpleName} " )
670
662
}
671
663
}
672
-
664
+
673
665
override fun nextFloat (tags : ULongArray? ): Float {
674
666
return nextDouble(tags).toFloat()
675
667
}
676
-
668
+
677
669
override fun nextTaggedStringOrNumber (): Triple <String ?, Long ?, ULongArray ?> {
678
670
val tags = processTags(null )
679
-
680
- return when (val key = current.element ) {
671
+
672
+ return when (val key = currentElement ) {
681
673
is CborString -> Triple (key.value, null , tags)
682
674
is CborPositiveInt -> Triple (null , key.value.toLong(), tags)
683
675
is CborNegativeInt -> Triple (null , key.value, tags)
684
676
else -> throw CborDecodingException (" Expected string or number key, got ${key?.let { it::class .simpleName } ? : " null" } " )
685
677
}
686
678
}
687
-
679
+
688
680
private fun processTags (tags : ULongArray? ): ULongArray? {
689
681
690
682
// If we're in a list, advance to the next element
691
683
if (listIterator != null && listIterator!! .hasNext()) {
692
- listIterator!! .next(). let { current = it.tags.toMutableList() to it }
684
+ currentElement = listIterator!! .next()
693
685
}
694
-
686
+
695
687
// Store collected tags for verification
696
- val collectedTags = if (current .tags.isEmpty()) null else current .tags.toULongArray()
697
-
688
+ val collectedTags = if (currentElement .tags.isEmpty()) null else currentElement .tags
689
+
698
690
// Verify tags if needed
699
691
if (verifyObjectTags) {
700
692
tags?.let {
701
693
verifyTagsAndThrow(it, collectedTags)
702
694
}
703
695
}
704
-
696
+
705
697
return collectedTags
706
698
}
707
-
699
+
708
700
override fun verifyTagsAndThrow (expected : ULongArray , actual : ULongArray? ) {
709
701
if (! expected.contentEquals(actual)) {
710
702
throw CborDecodingException (
711
703
" CBOR tags ${actual?.contentToString()} do not match expected tags ${expected.contentToString()} "
712
704
)
713
705
}
714
706
}
715
-
707
+
716
708
override fun skipElement (tags : ULongArray? ) {
717
709
// Process tags but don't do anything with the element
718
710
processTags(tags)
0 commit comments