Skip to content

Commit

Permalink
WIP Add NbtCapabilities.rootTagTypes
Browse files Browse the repository at this point in the history
  • Loading branch information
BenWoodworth committed Sep 17, 2024
1 parent c71a305 commit 8ff08cb
Show file tree
Hide file tree
Showing 11 changed files with 139 additions and 5 deletions.
5 changes: 1 addition & 4 deletions src/commonMain/kotlin/BedrockNbt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,13 @@ import net.benwoodworth.knbt.internal.*
import net.benwoodworth.knbt.internal.BedrockNbtReader
import net.benwoodworth.knbt.internal.NbtCapabilities
import net.benwoodworth.knbt.internal.NbtContext
import net.benwoodworth.knbt.internal.NbtReader
import net.benwoodworth.knbt.internal.NbtWriter
import okio.BufferedSink
import okio.BufferedSource
import okio.Sink
import okio.Source

private val bedrockNbtCapabilities = NbtCapabilities(
namedRoot = true,
definiteLengthEncoding = true,
rootTagTypes = NbtTagTypeSet(listOf(NbtTagType.TAG_List, NbtTagType.TAG_Compound)),
)

public class BedrockNbt internal constructor(
Expand Down
1 change: 1 addition & 0 deletions src/commonMain/kotlin/BedrockNetworkNbt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import okio.BufferedSource
private val bedrockNetworkNbtCapabilities = NbtCapabilities(
namedRoot = false,
definiteLengthEncoding = true,
rootTagTypes = NbtTagTypeSet(listOf(NbtTagType.TAG_List, NbtTagType.TAG_Compound)),
)

public class BedrockNetworkNbt internal constructor(
Expand Down
3 changes: 3 additions & 0 deletions src/commonMain/kotlin/JavaNbt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,21 @@ import kotlinx.serialization.SerializationException
import kotlinx.serialization.SerializationStrategy
import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.serializer
import net.benwoodworth.knbt.internal.*
import net.benwoodworth.knbt.internal.BinaryNbtReader
import net.benwoodworth.knbt.internal.BinaryNbtWriter
import net.benwoodworth.knbt.internal.JavaNbtReader
import net.benwoodworth.knbt.internal.JavaNbtWriter
import net.benwoodworth.knbt.internal.NbtCapabilities
import net.benwoodworth.knbt.internal.NbtContext
import net.benwoodworth.knbt.internal.NbtTagTypeSet
import okio.BufferedSink
import okio.BufferedSource

private val javaNbtCapabilities = NbtCapabilities(
namedRoot = true,
definiteLengthEncoding = true,
rootTagTypes = NbtTagTypeSet(listOf(NbtTagType.TAG_Compound)),
)

public class JavaNbt internal constructor(
Expand Down
1 change: 1 addition & 0 deletions src/commonMain/kotlin/JavaNetworkNbt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import okio.BufferedSource
private val javaNetworkNbtCapabilities = NbtCapabilities(
namedRoot = false,
definiteLengthEncoding = true,
rootTagTypes = NbtTagTypeSet(NbtTagType.entries),
)

public class JavaNetworkNbt internal constructor(
Expand Down
3 changes: 3 additions & 0 deletions src/commonMain/kotlin/Nbt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ import kotlinx.serialization.SerializationStrategy
import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.serializer
import net.benwoodworth.knbt.internal.NbtCapabilities
import net.benwoodworth.knbt.internal.NbtTagType
import net.benwoodworth.knbt.internal.NbtTagTypeSet

private val nbtCapabilities = NbtCapabilities(
namedRoot = true,
definiteLengthEncoding = true,
rootTagTypes = NbtTagTypeSet(NbtTagType.entries),
)

public open class Nbt internal constructor(
Expand Down
1 change: 1 addition & 0 deletions src/commonMain/kotlin/StringifiedNbt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import kotlin.native.concurrent.ThreadLocal
private val stringifiedNbtCapabilities = NbtCapabilities(
namedRoot = false,
definiteLengthEncoding = false,
rootTagTypes = NbtTagTypeSet(NbtTagType.entries - NbtTagType.TAG_End),
)

public open class StringifiedNbt internal constructor(
Expand Down
2 changes: 2 additions & 0 deletions src/commonMain/kotlin/internal/NbtCapabilities.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ internal data class NbtCapabilities(
* For deserialization, this means that [CompositeDecoder.decodeSequentially] can be enabled.
*/
val definiteLengthEncoding: Boolean,

val rootTagTypes: NbtTagTypeSet,
)
28 changes: 28 additions & 0 deletions src/commonMain/kotlin/internal/NbtTagTypeSet.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package net.benwoodworth.knbt.internal

internal class NbtTagTypeSet(
elements: Collection<NbtTagType>
) {
/**
* Bits indicating whether each [NbtTagType] in this set, with `1` indicating that it is contained, and
* [NbtTagType.bit] assigning bit positions.
*/
private val elementBits: Int =
elements.fold(0) { bits, tagType -> bits or tagType.bit }

private val NbtTagType.bit: Int
get() = 1 shl id.toInt()

operator fun contains(type: NbtTagType): Boolean =
(elementBits and type.bit) != 0

override fun equals(other: Any?): Boolean =
this === other || (other is NbtTagTypeSet && elementBits == other.elementBits)

override fun hashCode(): Int = elementBits

override fun toString(): String =
NbtTagType.entries
.filter { it in this }
.joinToString(prefix = "[", postfix = "]")
}
98 changes: 98 additions & 0 deletions src/commonTest/kotlin/internal/NbtTagTypeSetTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package net.benwoodworth.knbt.internal

import com.benwoodworth.parameterize.parameter
import net.benwoodworth.knbt.test.assume
import net.benwoodworth.knbt.test.parameterizeTest
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotEquals

class NbtTagTypeSetTest {
private class TestCase(
private val description: String,
val entries: List<NbtTagType>
) {
override fun toString(): String = "$description: $entries"
}

private val testCases = buildList {
add(TestCase("All", NbtTagType.entries))
add(TestCase("None", NbtTagType.entries))

NbtTagType.entries.forEach { tagType ->
add(TestCase("Only $tagType", listOf(tagType)))
}

NbtTagType.entries.forEach { tagType ->
add(TestCase("All except $tagType", NbtTagType.entries - tagType))
}
}

@Test
fun contains_should_be_correct() = parameterizeTest {
val testCase by parameter(testCases)
val element by parameter(NbtTagType.entries)

val set = NbtTagTypeSet(testCase.entries)

assertEquals(element in testCase.entries, element in set, "$element in $set")
}

@Test
fun equals_should_be_true_for_same_entries() = parameterizeTest {
val testCase by parameter(testCases)
val otherTestCase by parameter(testCases)
assume(testCase.entries.toSet() == otherTestCase.entries.toSet())

val set = NbtTagTypeSet(testCase.entries)
val otherSet = NbtTagTypeSet(testCase.entries)

assertEquals(set, otherSet)
}

@Test
fun equals_should_be_false_for_different_entries() = parameterizeTest {
val testCase by parameter(testCases)
val otherTestCase by parameter(testCases)
assume(testCase.entries.toSet() != otherTestCase.entries.toSet())

val set = NbtTagTypeSet(testCase.entries)
val otherSet = NbtTagTypeSet(otherTestCase.entries)

assertNotEquals(set, otherSet)
}

@Test
fun hash_code_should_be_the_same_if_equal() = parameterizeTest {
val testCase by parameter(testCases)
val otherTestCase by parameter(testCases)

val set = NbtTagTypeSet(testCase.entries)
val otherSet = NbtTagTypeSet(otherTestCase.entries)
assume(set == otherSet)

assertEquals(set.hashCode(), otherSet.hashCode())
}

@Test
fun hash_code_should_not_be_the_same_if_unequal() = parameterizeTest {
val testCase by parameter(testCases)
val otherTestCase by parameter(testCases)

val set = NbtTagTypeSet(testCase.entries)
val otherSet = NbtTagTypeSet(otherTestCase.entries)
assume(set != otherSet)

assertNotEquals(set.hashCode(), otherSet.hashCode())
}

@Test
fun to_string_should_be_the_same_as_a_set() = parameterizeTest {
val testCase by parameter(testCases)

assertEquals(
LinkedHashSet(testCase.entries.sortedBy { it.id }).toString(),
NbtTagTypeSet(testCase.entries).toString()
)
}
}
1 change: 0 additions & 1 deletion src/commonTest/kotlin/test/parameterizeTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ inline fun ParameterizeScope.assume(condition: Boolean) {
}
}


// The mapped parameters could be done more seamlessly with context parameters, with the `provideDelegate` and
// `getValue` operators taking the ParameterizeScope from the calling context instead of explicitly passing the scope
// and holding onto it. Maybe refactor later once context parameters are available in Kotlin.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ internal fun ParameterizeScope.parameterOfVerifyingNbt(
val baseCapabilities = NbtCapabilities(
namedRoot = false,
definiteLengthEncoding = false,
rootTagTypes = NbtTagTypeSet(NbtTagType.entries),
)

sequenceOf(
Expand Down

0 comments on commit 8ff08cb

Please sign in to comment.