Skip to content

Commit

Permalink
Fix the implementation of CompactFragmentSerializer for value childre…
Browse files Browse the repository at this point in the history
…n (in this case they are not a structure)
  • Loading branch information
pdvrieze committed Feb 24, 2024
1 parent 38c9320 commit b510b5b
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 14 deletions.
4 changes: 4 additions & 0 deletions core/api/android/core.api
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,8 @@ public final class nl/adaptivity/xmlutil/XmlEvent$EndDocumentEvent : nl/adaptivi

public final class nl/adaptivity/xmlutil/XmlEvent$EndElementEvent : nl/adaptivity/xmlutil/XmlEvent$NamedEvent {
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lnl/adaptivity/xmlutil/IterableNamespaceContext;)V
public fun <init> (Ljavax/xml/namespace/QName;Lnl/adaptivity/xmlutil/IterableNamespaceContext;Lnl/adaptivity/xmlutil/XmlReader$LocationInfo;)V
public synthetic fun <init> (Ljavax/xml/namespace/QName;Lnl/adaptivity/xmlutil/IterableNamespaceContext;Lnl/adaptivity/xmlutil/XmlReader$LocationInfo;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Lnl/adaptivity/xmlutil/XmlReader$LocationInfo;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lnl/adaptivity/xmlutil/IterableNamespaceContext;)V
public fun getEventType ()Lnl/adaptivity/xmlutil/EventType;
public final fun getNamespaceContext ()Lnl/adaptivity/xmlutil/IterableNamespaceContext;
Expand Down Expand Up @@ -528,6 +530,8 @@ public final class nl/adaptivity/xmlutil/XmlEvent$StartElementEvent : nl/adaptiv
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Lnl/adaptivity/xmlutil/XmlEvent$Attribute;Ljava/util/List;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Lnl/adaptivity/xmlutil/XmlEvent$Attribute;Lnl/adaptivity/xmlutil/IterableNamespaceContext;Ljava/util/List;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lnl/adaptivity/xmlutil/IterableNamespaceContext;)V
public fun <init> (Ljavax/xml/namespace/QName;Lnl/adaptivity/xmlutil/IterableNamespaceContext;Lnl/adaptivity/xmlutil/XmlReader$LocationInfo;)V
public synthetic fun <init> (Ljavax/xml/namespace/QName;Lnl/adaptivity/xmlutil/IterableNamespaceContext;Lnl/adaptivity/xmlutil/XmlReader$LocationInfo;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Lnl/adaptivity/xmlutil/XmlReader$LocationInfo;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Lnl/adaptivity/xmlutil/XmlEvent$Attribute;Lnl/adaptivity/xmlutil/IterableNamespaceContext;Ljava/util/List;)V
public final fun getAttributes ()[Lnl/adaptivity/xmlutil/XmlEvent$Attribute;
public fun getEventType ()Lnl/adaptivity/xmlutil/EventType;
Expand Down
4 changes: 4 additions & 0 deletions core/api/jvm/core.api
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,8 @@ public final class nl/adaptivity/xmlutil/XmlEvent$EndDocumentEvent : nl/adaptivi

public final class nl/adaptivity/xmlutil/XmlEvent$EndElementEvent : nl/adaptivity/xmlutil/XmlEvent$NamedEvent {
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lnl/adaptivity/xmlutil/IterableNamespaceContext;)V
public fun <init> (Ljavax/xml/namespace/QName;Lnl/adaptivity/xmlutil/IterableNamespaceContext;Lnl/adaptivity/xmlutil/XmlReader$LocationInfo;)V
public synthetic fun <init> (Ljavax/xml/namespace/QName;Lnl/adaptivity/xmlutil/IterableNamespaceContext;Lnl/adaptivity/xmlutil/XmlReader$LocationInfo;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Lnl/adaptivity/xmlutil/XmlReader$LocationInfo;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lnl/adaptivity/xmlutil/IterableNamespaceContext;)V
public fun getEventType ()Lnl/adaptivity/xmlutil/EventType;
public final fun getNamespaceContext ()Lnl/adaptivity/xmlutil/IterableNamespaceContext;
Expand Down Expand Up @@ -551,6 +553,8 @@ public final class nl/adaptivity/xmlutil/XmlEvent$StartElementEvent : nl/adaptiv
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Lnl/adaptivity/xmlutil/XmlEvent$Attribute;Ljava/util/List;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Lnl/adaptivity/xmlutil/XmlEvent$Attribute;Lnl/adaptivity/xmlutil/IterableNamespaceContext;Ljava/util/List;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lnl/adaptivity/xmlutil/IterableNamespaceContext;)V
public fun <init> (Ljavax/xml/namespace/QName;Lnl/adaptivity/xmlutil/IterableNamespaceContext;Lnl/adaptivity/xmlutil/XmlReader$LocationInfo;)V
public synthetic fun <init> (Ljavax/xml/namespace/QName;Lnl/adaptivity/xmlutil/IterableNamespaceContext;Lnl/adaptivity/xmlutil/XmlReader$LocationInfo;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Lnl/adaptivity/xmlutil/XmlReader$LocationInfo;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Lnl/adaptivity/xmlutil/XmlEvent$Attribute;Lnl/adaptivity/xmlutil/IterableNamespaceContext;Ljava/util/List;)V
public final fun getAttributes ()[Lnl/adaptivity/xmlutil/XmlEvent$Attribute;
public fun getEventType ()Lnl/adaptivity/xmlutil/EventType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ public class XmlBufferReader(private val buffer: List<XmlEvent>) : XmlReader {
override val depth: Int get() = namespaceHolder.depth

override val namespaceURI: String
get() = current<StartElementEvent>().namespaceUri
get() = current<NamedEvent>().namespaceUri

override val localName: String
get() = current<StartElementEvent>().localName
get() = current<NamedEvent>().localName

override val prefix: String
get() = current<StartElementEvent>().prefix
get() = current<NamedEvent>().prefix

override val isStarted: Boolean
get() = currentPos >= 0
Expand Down
14 changes: 14 additions & 0 deletions core/src/commonMain/kotlin/nl/adaptivity/xmlutil/XmlEvent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,14 @@ public sealed class XmlEvent(public val extLocationInfo: XmlReader.LocationInfo?
prefix: String,
namespaceContext: IterableNamespaceContext,
) : NamedEvent(extLocationInfo, namespaceUri, localName, prefix) {

public constructor(
name: QName,
parentNamespaceContext: IterableNamespaceContext,
extLocationInfo: XmlReader.LocationInfo? = null
) : this(extLocationInfo, name.namespaceURI, name.localPart, name.prefix, parentNamespaceContext)


public constructor(
locationInfo: String, namespaceUri: String,
localName: String,
Expand Down Expand Up @@ -206,6 +214,12 @@ public sealed class XmlEvent(public val extLocationInfo: XmlReader.LocationInfo?

private val namespaceHolder: SimpleNamespaceContext = SimpleNamespaceContext(namespaceDecls.asIterable())

public constructor(
name: QName,
parentNamespaceContext: IterableNamespaceContext,
extLocationInfo: XmlReader.LocationInfo? = null
) : this(extLocationInfo, name.namespaceURI, name.localPart, name.prefix, emptyArray(), parentNamespaceContext, emptyList())

public constructor(
namespaceUri: String,
localName: String,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023.
* Copyright (c) 2024.
*
* This file is part of xmlutil.
*
Expand Down Expand Up @@ -42,9 +42,16 @@ public object CompactFragmentSerializer : XmlSerializer<CompactFragment> {
previousValue: CompactFragment?,
isValueChild: Boolean
): CompactFragment {
return decoder.decodeStructure(descriptor) {
input.next()
input.siblingsToFragment()
return when {
isValueChild -> {
input.next()
input.siblingsToFragment()
}

else -> decoder.decodeStructure(descriptor) {
input.next()
input.siblingsToFragment()
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -744,8 +744,18 @@ internal open class XmlDecoderBase internal constructor(
}

val result: T = when (effectiveDeserializer) {
is XmlDeserializationStrategy -> effectiveDeserializer
.deserializeXML(decoder, input, previousValue, xmlDescriptor.getValueChild() == index)
is XmlDeserializationStrategy -> {
val current = input.eventType.createEvent(input)
val i = when (val p = input.peek()) {
// if the element is actually closed we synthesize the reader (needed for compactFragments),
// this stops the end event to be consumed
is XmlEvent.EndElementEvent -> XmlBufferReader(listOf(current, p)).also { it.next() }

else -> input
}
effectiveDeserializer
.deserializeXML(decoder, i, previousValue, xmlDescriptor.getValueChild() == index)
}

is AbstractCollectionSerializer<*, T, *> ->
effectiveDeserializer.merge(decoder, previousValue)
Expand Down Expand Up @@ -1021,7 +1031,7 @@ internal open class XmlDecoderBase internal constructor(
if (valueChild >= 0 && input.peek() is XmlEvent.EndElementEvent && !seenItems[valueChild]) {
val valueChildDesc = xmlDescriptor.getElementDescriptor(valueChild)
// Lists/maps need to be empty (treated as null/missing)
if (valueChildDesc.kind !is StructureKind.LIST && valueChildDesc.kind !is StructureKind.MAP) {
if ((! valueChildDesc.isNullable) && valueChildDesc.kind !is StructureKind.LIST && valueChildDesc.kind !is StructureKind.MAP) {
// This code can rely on seenItems to avoid infinite item loops as it only triggers on an empty tag.
seenItems[valueChild] = true
return valueChild
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,30 @@ class EmptyTagWithValueChild {

@Test
fun testSerializeCF() {
val actual = XML.encodeToString(OuterFrag(InnerFrag(emptyList())))
val actual = XML.encodeToString(OuterFrag(InnerFrag(CompactFragment(""))))
assertXmlEquals("<Outer><Inner /></Outer>", actual)
}

@Test
fun testDeserializeCF() {
val expected = OuterFrag(InnerFrag(emptyList()))
val expected = OuterFrag(InnerFrag(CompactFragment("")))
val actual = XML.decodeFromString<OuterFrag>("<Outer><Inner /></Outer>")
assertEquals(expected, actual)
}

@Test
fun testSerializeCFlist() {
val actual = XML.encodeToString(OuterFrags(InnerFrags(emptyList())))
assertXmlEquals("<Outer><Inner /></Outer>", actual)
}

@Test
fun testDeserializeCFlist() {
val expected = OuterFrags(InnerFrags(emptyList()))
val actual = XML.decodeFromString<OuterFrags>("<Outer><Inner /></Outer>")
assertEquals(expected, actual)
}

@Test
fun testDeserializeStr() {
val expected = OuterStr(InnerStr(""))
Expand All @@ -69,9 +82,17 @@ class EmptyTagWithValueChild {

@Serializable
@SerialName("Outer")
private data class OuterFrag(val inner: InnerFrag)
private data class OuterFrags(val inner: InnerFrags)

@Serializable
@SerialName("Inner")
private data class InnerFrags(@XmlValue val values: List<CompactFragment>)

@Serializable
@SerialName("Inner")
private data class InnerFrag(@XmlValue val values: List<CompactFragment>)
private data class InnerFrag(@XmlValue val value: CompactFragment)

@Serializable
@SerialName("Outer")
private data class OuterFrag(val inner: InnerFrag)
}

0 comments on commit b510b5b

Please sign in to comment.