All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.internal.TreeNbtReader.kt Maven / Gradle / Ivy

The newest version!
package net.benwoodworth.knbt.internal

import net.benwoodworth.knbt.*
import net.benwoodworth.knbt.internal.NbtReader.*

internal class TreeNbtReader(tag: NbtTag) : NbtReader {
    private var reader: NbtTagReader = RootNbtTagReader(tag)

    override fun beginRootTag(): RootTagInfo = reader.beginRootTag()
    override fun beginCompound() = reader.beginCompound()
    override fun beginCompoundEntry(): CompoundEntryInfo = reader.beginCompoundEntry()
    override fun endCompound() = reader.endCompound()
    override fun beginList(): ListInfo = reader.beginList()
    override fun beginListEntry(): Boolean = reader.beginListEntry()
    override fun endList() = reader.endList()
    override fun beginByteArray(): ArrayInfo = reader.beginByteArray()
    override fun beginByteArrayEntry(): Boolean = reader.beginByteArrayEntry()
    override fun endByteArray() = reader.endByteArray()
    override fun beginIntArray(): ArrayInfo = reader.beginIntArray()
    override fun beginIntArrayEntry(): Boolean = reader.beginIntArrayEntry()
    override fun endIntArray() = reader.endIntArray()
    override fun beginLongArray(): ArrayInfo = reader.beginLongArray()
    override fun beginLongArrayEntry(): Boolean = reader.beginLongArrayEntry()
    override fun endLongArray() = reader.endLongArray()
    override fun readByte(): Byte = reader.readByte()
    override fun readShort(): Short = reader.readShort()
    override fun readInt(): Int = reader.readInt()
    override fun readLong(): Long = reader.readLong()
    override fun readFloat(): Float = reader.readFloat()
    override fun readDouble(): Double = reader.readDouble()
    override fun readString(): String = reader.readString()

    private sealed interface NbtTagReader {
        fun beginRootTag(): RootTagInfo = error("${this::class} does not support beginRootTag()")
        fun beginCompound(): Unit = error("${this::class} does not support beginCompound()")
        fun beginCompoundEntry(): CompoundEntryInfo = error("${this::class} does not support beginCompoundEntry()")
        fun endCompound(): Unit = error("${this::class} does not support endCompound()")
        fun beginList(): ListInfo = error("${this::class} does not support beginList()")
        fun beginListEntry(): Boolean = error("${this::class} does not support beginListEntry()")
        fun endList(): Unit = error("${this::class} does not support endList()")
        fun beginByteArray(): ArrayInfo = error("${this::class} does not support beginByteArray()")
        fun beginByteArrayEntry(): Boolean = error("${this::class} does not support beginByteArrayEntry()")
        fun endByteArray(): Unit = error("${this::class} does not support endByteArray()")
        fun beginIntArray(): ArrayInfo = error("${this::class} does not support beginIntArray()")
        fun beginIntArrayEntry(): Boolean = error("${this::class} does not support beginIntArrayEntry()")
        fun endIntArray(): Unit = error("${this::class} does not support endIntArray()")
        fun beginLongArray(): ArrayInfo = error("${this::class} does not support beginLongArray()")
        fun beginLongArrayEntry(): Boolean = error("${this::class} does not support beginLongArrayEntry()")
        fun endLongArray(): Unit = error("${this::class} does not support endLongArray()")
        fun readByte(): Byte = error("${this::class} does not support readByte()")
        fun readShort(): Short = error("${this::class} does not support readShort()")
        fun readInt(): Int = error("${this::class} does not support readInt()")
        fun readLong(): Long = error("${this::class} does not support readLong()")
        fun readFloat(): Float = error("${this::class} does not support readFloat()")
        fun readDouble(): Double = error("${this::class} does not support readDouble()")
        fun readString(): String = error("${this::class} does not support readString()")
    }

    private inner class RootNbtTagReader(private val tag: NbtTag) : NbtTagReader {
        override fun beginRootTag(): RootTagInfo = RootTagInfo(tag.type)

        override fun beginCompound() {
            reader = NbtCompoundReader(this, tag as NbtCompound)
        }

        override fun beginList(): ListInfo {
            reader = NbtListReader(this, tag as NbtList<*>)
            return ListInfo(tag.elementType, tag.size)
        }

        override fun beginByteArray(): ArrayInfo {
            reader = NbtByteArrayReader(this, tag as NbtByteArray)
            return ArrayInfo(tag.size)
        }

        override fun beginIntArray(): ArrayInfo {
            reader = NbtIntArrayReader(this, tag as NbtIntArray)
            return ArrayInfo(tag.size)
        }

        override fun beginLongArray(): ArrayInfo {
            reader = NbtLongArrayReader(this, tag as NbtLongArray)
            return ArrayInfo(tag.size)
        }

        override fun readByte(): Byte = (tag as NbtByte).value
        override fun readShort(): Short = (tag as NbtShort).value
        override fun readInt(): Int = (tag as NbtInt).value
        override fun readLong(): Long = (tag as NbtLong).value
        override fun readFloat(): Float = (tag as NbtFloat).value
        override fun readDouble(): Double = (tag as NbtDouble).value
        override fun readString(): String = (tag as NbtString).value
    }

    private inner class NbtCompoundReader(val parent: NbtTagReader, tag: NbtCompound) : NbtTagReader {
        private val iterator = tag.iterator()
        private var next = if (iterator.hasNext()) iterator.next() else null

        private inline fun  readEntry(): T {
            return (next!!.value as T)
                .also { next = if (iterator.hasNext()) iterator.next() else null }
        }

        override fun beginCompoundEntry(): CompoundEntryInfo =
            next?.let { (name, tag) -> CompoundEntryInfo(tag.type, name) } ?: CompoundEntryInfo.End

        override fun endCompound() {
            reader = parent
        }

        override fun beginCompound() {
            val entry = readEntry()
            reader = NbtCompoundReader(this, entry)
        }

        override fun beginList(): ListInfo {
            val entry = readEntry>()
            reader = NbtListReader(this, entry)
            return ListInfo(entry.elementType, entry.size)
        }

        override fun beginByteArray(): ArrayInfo {
            val entry = readEntry()
            reader = NbtByteArrayReader(this, entry)
            return ArrayInfo(entry.size)
        }

        override fun beginIntArray(): ArrayInfo {
            val entry = readEntry()
            reader = NbtIntArrayReader(this, entry)
            return ArrayInfo(entry.size)
        }

        override fun beginLongArray(): ArrayInfo {
            val entry = readEntry()
            reader = NbtLongArrayReader(this, entry)
            return ArrayInfo(entry.size)
        }

        override fun readByte(): Byte = readEntry().value
        override fun readShort(): Short = readEntry().value
        override fun readInt(): Int = readEntry().value
        override fun readLong(): Long = readEntry().value
        override fun readFloat(): Float = readEntry().value
        override fun readDouble(): Double = readEntry().value
        override fun readString(): String = readEntry().value
    }

    private inner class NbtListReader(val parent: NbtTagReader, tag: NbtList<*>) : NbtTagReader {
        private val iterator = tag.iterator()
        private var next = if (iterator.hasNext()) iterator.next() else null

        private inline fun  readEntry(): T {
            return (next as T)
                .also { next = if (iterator.hasNext()) iterator.next() else null }
        }

        override fun beginListEntry(): Boolean = next != null

        override fun endList() {
            reader = parent
        }

        override fun beginCompound() {
            val entry = readEntry()
            reader = NbtCompoundReader(this, entry)
        }

        override fun beginList(): ListInfo {
            val entry = readEntry>()
            reader = NbtListReader(this, entry)
            return ListInfo(entry.elementType, entry.size)
        }

        override fun beginByteArray(): ArrayInfo {
            val entry = readEntry()
            reader = NbtByteArrayReader(this, entry)
            return ArrayInfo(entry.size)
        }

        override fun beginIntArray(): ArrayInfo {
            val entry = readEntry()
            reader = NbtIntArrayReader(this, entry)
            return ArrayInfo(entry.size)
        }

        override fun beginLongArray(): ArrayInfo {
            val entry = readEntry()
            reader = NbtLongArrayReader(this, entry)
            return ArrayInfo(entry.size)
        }

        override fun readByte(): Byte = readEntry().value
        override fun readShort(): Short = readEntry().value
        override fun readInt(): Int = readEntry().value
        override fun readLong(): Long = readEntry().value
        override fun readFloat(): Float = readEntry().value
        override fun readDouble(): Double = readEntry().value
        override fun readString(): String = readEntry().value
    }

    private inner class NbtByteArrayReader(val parent: NbtTagReader, tag: NbtByteArray) : NbtTagReader {
        private val array = tag
        private var index = 0

        override fun beginByteArrayEntry(): Boolean = index <= array.lastIndex

        override fun endByteArray() {
            reader = parent
        }

        override fun readByte(): Byte = array[index++]
    }


    private inner class NbtIntArrayReader(val parent: NbtTagReader, tag: NbtIntArray) : NbtTagReader {
        private val array = tag
        private var index = 0

        override fun beginIntArrayEntry(): Boolean = index <= array.lastIndex

        override fun endIntArray() {
            reader = parent
        }

        override fun readInt(): Int = array[index++]
    }


    private inner class NbtLongArrayReader(val parent: NbtTagReader, tag: NbtLongArray) : NbtTagReader {
        private val array = tag
        private var index = 0

        override fun beginLongArrayEntry(): Boolean = index <= array.lastIndex

        override fun endLongArray() {
            reader = parent
        }

        override fun readLong(): Long = array[index++]
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy