I've got a sealed interface `NbtTag` that's implem...
# announcements
b
I've got a sealed interface
NbtTag
that's implemented by
NbtInt
,
NbtString
,
NbtList<T : NbtTag>
, etc. (for a kotlinx.serialization format library) NbtList can only contain one type of tag (so
T
can't be
NbtTag
), and I'm wondering if there's a better way to restrict that. Here's basically what I'm doing right now (which seems overly verbose):
Copy code
class NbtList<out T : NbtTag> internal constructor(
    val content: List<T>
) : NbtTag, List<T> by content

// Pseudo constructors to limit T to concrete types
fun NbtList(content: List<NbtInt>): NbtList<NbtInt> = NbtList<NbtInt>(content)
fun NbtList(content: List<NbtString>): NbtList<NbtString> = NbtList<NbtString>(content)
fun NbtList(content: List<NbtList<*>>): NbtList<NbtList<*>> = NbtList<NbtList<*>>(content)
// plus 9 more for the remaining tag types...
Are there any other ways I can accomplish this and limit the constructor/content?
d
I'd probably enforce this in the encoder/decoder. I don't think these restrictions are going to be easy to work with imo.
b
It's a restriction with the binary format so my thinking was to model the class similarly in a type-safe way (so all
NbtList
instances valid for serialization). Plus checks in the encoder in case any custom
@Serializable
types are invalid just in case
p
could you have a
sealed interface NbtItem : NbtTag
and have
NbtList
accept
NbtItem
as the constraint?
👍 1
e
runtime hack, but this may work:
Copy code
Json.encodeToString(NbtList(NbtInt(1), NbtInt(2))) // ok
Json.encodeToString(NbtList(NbtInt(1), NbtString("2"))) // throws
Json.encodeToString(NbtList(NbtList(NbtInt(1)), NbtList(NbtInt(2)))) // ok
Json.encodeToString(NbtList(NbtList(NbtInt(1)), NbtList(NbtString("2")))) // throws