@@ -18,7 +18,7 @@ internal open class CborReader(override val cbor: Cbor, protected val parser: Cb
18
18
override fun decodeCborElement (): CborElement =
19
19
when (parser) {
20
20
is CborParser -> CborTreeReader (cbor.configuration, parser).read()
21
- is StructuredCborParser -> parser.layer.currentElement
21
+ is StructuredCborParser -> parser.layer.current
22
22
}
23
23
24
24
@@ -119,7 +119,9 @@ internal open class CborReader(override val cbor: Cbor, protected val parser: Cb
119
119
@Suppress(" UNCHECKED_CAST" )
120
120
return if (deserializer is CborSerializer ) {
121
121
val tags = parser.processTags(tags)
122
- decodeCborElement().also { /* this is a NOOP for structured parser but not from bytes */ it.tags = tags ? : ulongArrayOf() } as T
122
+ decodeCborElement().also { /* this is a NOOP for structured parser but not from bytes */ it.tags =
123
+ tags ? : ulongArrayOf()
124
+ } as T
123
125
} else if ((decodeByteArrayAsByteString || cbor.configuration.alwaysUseByteString)
124
126
&& deserializer.descriptor == ByteArraySerializer ().descriptor
125
127
) {
@@ -563,12 +565,15 @@ private fun Iterable<ByteArray>.flatten(): ByteArray {
563
565
* Works for single elements (where current is directly set to the element) and for collections (where current
564
566
* will be first set after `startMap` or `startArray`
565
567
*/
566
- internal class PeekingIterator <T : Any >(private val iter : ListIterator <T >) : Iterator<T> by iter {
568
+ internal class PeekingIterator private constructor(
569
+ internal val isStructure : Boolean ,
570
+ private val iter : ListIterator <CborElement >
571
+ ) : Iterator<CborElement> by iter {
567
572
568
- lateinit var current: T
573
+ lateinit var current: CborElement
569
574
private set
570
575
571
- override fun next (): T = iter.next().also { current = it }
576
+ override fun next (): CborElement = iter.next().also { current = it }
572
577
573
578
fun peek () = if (hasNext()) {
574
579
val next = iter.next()
@@ -577,21 +582,13 @@ internal class PeekingIterator<T : Any>(private val iter: ListIterator<T>) : Ite
577
582
} else null
578
583
579
584
companion object {
580
- operator fun invoke (single : CborElement ): PeekingIterator <CborElement > =
581
- PeekingIterator (listOf (single).listIterator()).also { it.next() }
585
+ operator fun invoke (single : CborElement ): PeekingIterator =
586
+ PeekingIterator (false , listOf (single).listIterator()).also { it.next() }
587
+
588
+ operator fun invoke (iter : ListIterator <CborElement >): PeekingIterator =
589
+ PeekingIterator (true , iter)
582
590
}
583
591
}
584
- /* * Maps are a bit special for nullability checks, so we need to check whether we're in a map or not*/
585
- private typealias CborLayer = Pair <Boolean , PeekingIterator <CborElement >>
586
-
587
- // TODO get rid of this!
588
- private val CborLayer .isMap get() = first
589
-
590
- /* * current element reference inside a layer. If the layer is a primitive then the current element is the layer itself*/
591
- private val CborLayer .currentElement get() = second.current
592
- private fun CborLayer.peek () = second.peek()
593
- private fun CborLayer.hasNext () = second.hasNext()
594
- private fun CborLayer.nextElement () = second.next()
595
592
596
593
/* *
597
594
* CBOR parser that operates on [CborElement] instead of bytes. Closely mirrors the behaviour of [CborParser], so the
@@ -600,20 +597,20 @@ private fun CborLayer.nextElement() = second.next()
600
597
internal class StructuredCborParser (internal val element : CborElement , private val verifyObjectTags : Boolean ) :
601
598
CborParserInterface {
602
599
603
- internal var layer: CborLayer = false to PeekingIterator (element)
600
+ internal var layer: PeekingIterator = PeekingIterator (element)
604
601
private set
605
602
606
603
607
- private val layerStack = ArrayDeque <CborLayer >()
604
+ private val layerStack = ArrayDeque <PeekingIterator >()
608
605
609
606
// map needs special treatment because keys and values are laid out as a list alternating between key and value to
610
607
// mirror the byte-layout of a cbor map.
611
608
override fun isNull () =
612
- if (layer.isMap ) layer.peek().let {
609
+ if (layer.isStructure ) layer.peek().let {
613
610
it is CborNull ||
614
611
/* THIS IS NOT CBOR-COMPLIANT but KxS-proprietary handling of nullable classes*/
615
612
(it is CborMap && it.isEmpty())
616
- } else layer.currentElement is CborNull
613
+ } else layer.current is CborNull
617
614
618
615
override fun isEnd () = ! layer.hasNext()
619
616
@@ -624,80 +621,80 @@ internal class StructuredCborParser(internal val element: CborElement, private v
624
621
625
622
override fun startArray (tags : ULongArray? ): Int {
626
623
processTags(tags)
627
- if (layer.currentElement !is CborList ) {
628
- throw CborDecodingException (" Expected array, got ${layer.currentElement ::class .simpleName} " )
624
+ if (layer.current !is CborList ) {
625
+ throw CborDecodingException (" Expected array, got ${layer.current ::class .simpleName} " )
629
626
}
630
627
layerStack + = layer
631
- val list = layer.currentElement as CborList
632
- layer = true to PeekingIterator (list.listIterator())
628
+ val list = layer.current as CborList
629
+ layer = PeekingIterator (list.listIterator())
633
630
return list.size // we could just return -1 and let the current layer run out of elements to never run into inconsistencies
634
631
// if we do keep it like this, any inconsistencies serve as a canary for implementation bugs
635
632
}
636
633
637
634
override fun startMap (tags : ULongArray? ): Int {
638
635
processTags(tags)
639
- if (layer.currentElement !is CborMap ) {
640
- throw CborDecodingException (" Expected map, got ${layer.currentElement ::class .simpleName} " )
636
+ if (layer.current !is CborMap ) {
637
+ throw CborDecodingException (" Expected map, got ${layer.current ::class .simpleName} " )
641
638
}
642
639
layerStack + = layer
643
640
644
- val map = layer.currentElement as CborMap
641
+ val map = layer.current as CborMap
645
642
// zip key, value, key, value, ... pairs to mirror byte-layout of CBOR map, so decoding this here works the same
646
643
// as decoding from bytes
647
- layer = true to PeekingIterator (map.entries.flatMap { listOf (it.key, it.value) }.listIterator())
644
+ layer = PeekingIterator (map.entries.flatMap { listOf (it.key, it.value) }.listIterator())
648
645
return map.size// we could just return -1 and let the current layer run out of elements to never run into inconsistencies
649
646
// if we do keep it like this, any inconsistencies serve as a canary for implementation bugs
650
647
}
651
648
652
649
override fun nextNull (tags : ULongArray? ): Nothing? {
653
650
processTags(tags)
654
- if (layer.currentElement !is CborNull ) {
651
+ if (layer.current !is CborNull ) {
655
652
/* THIS IS NOT CBOR-COMPLIANT but KxS-proprietary handling of nullable classes*/
656
- if (layer.currentElement is CborMap && (layer.currentElement as CborMap ).isEmpty())
653
+ if (layer.current is CborMap && (layer.current as CborMap ).isEmpty())
657
654
return null
658
- throw CborDecodingException (" Expected null, got ${layer.currentElement ::class .simpleName} " )
655
+ throw CborDecodingException (" Expected null, got ${layer.current ::class .simpleName} " )
659
656
}
660
657
return null
661
658
}
662
659
663
660
override fun nextBoolean (tags : ULongArray? ): Boolean {
664
661
processTags(tags)
665
- if (layer.currentElement !is CborBoolean ) {
666
- throw CborDecodingException (" Expected boolean, got ${layer.currentElement ::class .simpleName} " )
662
+ if (layer.current !is CborBoolean ) {
663
+ throw CborDecodingException (" Expected boolean, got ${layer.current ::class .simpleName} " )
667
664
}
668
- return (layer.currentElement as CborBoolean ).value
665
+ return (layer.current as CborBoolean ).value
669
666
}
670
667
671
668
override fun nextNumber (tags : ULongArray? ): Long {
672
669
processTags(tags)
673
- return when (layer.currentElement ) {
674
- is CborPositiveInt -> (layer.currentElement as CborPositiveInt ).value.toLong()
675
- is CborNegativeInt -> (layer.currentElement as CborNegativeInt ).value
676
- else -> throw CborDecodingException (" Expected number, got ${layer.currentElement ::class .simpleName} " )
670
+ return when (layer.current ) {
671
+ is CborPositiveInt -> (layer.current as CborPositiveInt ).value.toLong()
672
+ is CborNegativeInt -> (layer.current as CborNegativeInt ).value
673
+ else -> throw CborDecodingException (" Expected number, got ${layer.current ::class .simpleName} " )
677
674
}
678
675
}
679
676
680
677
override fun nextString (tags : ULongArray? ): String {
681
678
processTags(tags)
682
- if (layer.currentElement !is CborString ) {
683
- throw CborDecodingException (" Expected string, got ${layer.currentElement ::class .simpleName} " )
679
+ if (layer.current !is CborString ) {
680
+ throw CborDecodingException (" Expected string, got ${layer.current ::class .simpleName} " )
684
681
}
685
- return (layer.currentElement as CborString ).value
682
+ return (layer.current as CborString ).value
686
683
}
687
684
688
685
override fun nextByteString (tags : ULongArray? ): ByteArray {
689
686
processTags(tags)
690
- if (layer.currentElement !is CborByteString ) {
691
- throw CborDecodingException (" Expected byte string, got ${layer.currentElement ::class .simpleName} " )
687
+ if (layer.current !is CborByteString ) {
688
+ throw CborDecodingException (" Expected byte string, got ${layer.current ::class .simpleName} " )
692
689
}
693
- return (layer.currentElement as CborByteString ).value
690
+ return (layer.current as CborByteString ).value
694
691
}
695
692
696
693
override fun nextDouble (tags : ULongArray? ): Double {
697
694
processTags(tags)
698
- return when (layer.currentElement ) {
699
- is CborDouble -> (layer.currentElement as CborDouble ).value
700
- else -> throw CborDecodingException (" Expected double, got ${layer.currentElement ::class .simpleName} " )
695
+ return when (layer.current ) {
696
+ is CborDouble -> (layer.current as CborDouble ).value
697
+ else -> throw CborDecodingException (" Expected double, got ${layer.current ::class .simpleName} " )
701
698
}
702
699
}
703
700
@@ -708,7 +705,7 @@ internal class StructuredCborParser(internal val element: CborElement, private v
708
705
override fun nextTaggedStringOrNumber (): Triple <String ?, Long ?, ULongArray ?> {
709
706
val tags = processTags(null )
710
707
711
- return when (val key = layer.currentElement ) {
708
+ return when (val key = layer.current ) {
712
709
is CborString -> Triple (key.value, null , tags)
713
710
is CborPositiveInt -> Triple (null , key.value.toLong(), tags)
714
711
is CborNegativeInt -> Triple (null , key.value, tags)
@@ -724,11 +721,11 @@ internal class StructuredCborParser(internal val element: CborElement, private v
724
721
override fun processTags (tags : ULongArray? ): ULongArray? {
725
722
726
723
// If we're in a list/map, advance to the next element
727
- if (layer.hasNext()) layer.nextElement ()
724
+ if (layer.hasNext()) layer.next ()
728
725
// if we're at a primitive, we only process tags
729
726
730
727
// Store collected tags for verification
731
- val collectedTags = if (layer.currentElement .tags.isEmpty()) null else layer.currentElement .tags
728
+ val collectedTags = if (layer.current .tags.isEmpty()) null else layer.current .tags
732
729
733
730
// Verify tags if needed
734
731
if (verifyObjectTags) {
0 commit comments