@@ -18,7 +18,7 @@ internal open class CborReader(override val cbor: Cbor, protected val parser: Cb
1818 override fun decodeCborElement (): CborElement =
1919 when (parser) {
2020 is CborParser -> CborTreeReader (cbor.configuration, parser).read()
21- is StructuredCborParser -> parser.layer.currentElement
21+ is StructuredCborParser -> parser.layer.current
2222 }
2323
2424
@@ -119,7 +119,9 @@ internal open class CborReader(override val cbor: Cbor, protected val parser: Cb
119119 @Suppress(" UNCHECKED_CAST" )
120120 return if (deserializer is CborSerializer ) {
121121 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
123125 } else if ((decodeByteArrayAsByteString || cbor.configuration.alwaysUseByteString)
124126 && deserializer.descriptor == ByteArraySerializer ().descriptor
125127 ) {
@@ -563,12 +565,15 @@ private fun Iterable<ByteArray>.flatten(): ByteArray {
563565 * Works for single elements (where current is directly set to the element) and for collections (where current
564566 * will be first set after `startMap` or `startArray`
565567 */
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 {
567572
568- lateinit var current: T
573+ lateinit var current: CborElement
569574 private set
570575
571- override fun next (): T = iter.next().also { current = it }
576+ override fun next (): CborElement = iter.next().also { current = it }
572577
573578 fun peek () = if (hasNext()) {
574579 val next = iter.next()
@@ -577,21 +582,13 @@ internal class PeekingIterator<T : Any>(private val iter: ListIterator<T>) : Ite
577582 } else null
578583
579584 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)
582590 }
583591}
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()
595592
596593/* *
597594 * 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()
600597internal class StructuredCborParser (internal val element : CborElement , private val verifyObjectTags : Boolean ) :
601598 CborParserInterface {
602599
603- internal var layer: CborLayer = false to PeekingIterator (element)
600+ internal var layer: PeekingIterator = PeekingIterator (element)
604601 private set
605602
606603
607- private val layerStack = ArrayDeque <CborLayer >()
604+ private val layerStack = ArrayDeque <PeekingIterator >()
608605
609606 // map needs special treatment because keys and values are laid out as a list alternating between key and value to
610607 // mirror the byte-layout of a cbor map.
611608 override fun isNull () =
612- if (layer.isMap ) layer.peek().let {
609+ if (layer.isStructure ) layer.peek().let {
613610 it is CborNull ||
614611 /* THIS IS NOT CBOR-COMPLIANT but KxS-proprietary handling of nullable classes*/
615612 (it is CborMap && it.isEmpty())
616- } else layer.currentElement is CborNull
613+ } else layer.current is CborNull
617614
618615 override fun isEnd () = ! layer.hasNext()
619616
@@ -624,80 +621,80 @@ internal class StructuredCborParser(internal val element: CborElement, private v
624621
625622 override fun startArray (tags : ULongArray? ): Int {
626623 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} " )
629626 }
630627 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())
633630 return list.size // we could just return -1 and let the current layer run out of elements to never run into inconsistencies
634631 // if we do keep it like this, any inconsistencies serve as a canary for implementation bugs
635632 }
636633
637634 override fun startMap (tags : ULongArray? ): Int {
638635 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} " )
641638 }
642639 layerStack + = layer
643640
644- val map = layer.currentElement as CborMap
641+ val map = layer.current as CborMap
645642 // zip key, value, key, value, ... pairs to mirror byte-layout of CBOR map, so decoding this here works the same
646643 // 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())
648645 return map.size// we could just return -1 and let the current layer run out of elements to never run into inconsistencies
649646 // if we do keep it like this, any inconsistencies serve as a canary for implementation bugs
650647 }
651648
652649 override fun nextNull (tags : ULongArray? ): Nothing? {
653650 processTags(tags)
654- if (layer.currentElement !is CborNull ) {
651+ if (layer.current !is CborNull ) {
655652 /* 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())
657654 return null
658- throw CborDecodingException (" Expected null, got ${layer.currentElement ::class .simpleName} " )
655+ throw CborDecodingException (" Expected null, got ${layer.current ::class .simpleName} " )
659656 }
660657 return null
661658 }
662659
663660 override fun nextBoolean (tags : ULongArray? ): Boolean {
664661 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} " )
667664 }
668- return (layer.currentElement as CborBoolean ).value
665+ return (layer.current as CborBoolean ).value
669666 }
670667
671668 override fun nextNumber (tags : ULongArray? ): Long {
672669 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} " )
677674 }
678675 }
679676
680677 override fun nextString (tags : ULongArray? ): String {
681678 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} " )
684681 }
685- return (layer.currentElement as CborString ).value
682+ return (layer.current as CborString ).value
686683 }
687684
688685 override fun nextByteString (tags : ULongArray? ): ByteArray {
689686 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} " )
692689 }
693- return (layer.currentElement as CborByteString ).value
690+ return (layer.current as CborByteString ).value
694691 }
695692
696693 override fun nextDouble (tags : ULongArray? ): Double {
697694 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} " )
701698 }
702699 }
703700
@@ -708,7 +705,7 @@ internal class StructuredCborParser(internal val element: CborElement, private v
708705 override fun nextTaggedStringOrNumber (): Triple <String ?, Long ?, ULongArray ?> {
709706 val tags = processTags(null )
710707
711- return when (val key = layer.currentElement ) {
708+ return when (val key = layer.current ) {
712709 is CborString -> Triple (key.value, null , tags)
713710 is CborPositiveInt -> Triple (null , key.value.toLong(), tags)
714711 is CborNegativeInt -> Triple (null , key.value, tags)
@@ -724,11 +721,11 @@ internal class StructuredCborParser(internal val element: CborElement, private v
724721 override fun processTags (tags : ULongArray? ): ULongArray? {
725722
726723 // If we're in a list/map, advance to the next element
727- if (layer.hasNext()) layer.nextElement ()
724+ if (layer.hasNext()) layer.next ()
728725 // if we're at a primitive, we only process tags
729726
730727 // 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
732729
733730 // Verify tags if needed
734731 if (verifyObjectTags) {
0 commit comments