mirror of
https://github.com/AdrianKuta/Tree-Data-Structure.git
synced 2026-06-19 19:00:14 +02:00
feat: Kotlin 2.x/K2, version catalog, serialization & coroutines modules, docs
v3.4 modernization (continued): - Migrate to Kotlin 2.x (K2); introduce gradle/libs.versions.toml version catalog; simplify the JS/Wasm/Node and iOS source-set wiring for the K2 hierarchy template. - Apply binary-compatibility-validator and Kover plugins. - New published module tree-structure-serialization: @Serializable TreeNodeDto with toDto()/toTreeNode() round-trip (kotlinx.serialization). - New published module tree-structure-coroutines: asFlow()/pre/post/levelOrderFlow() (kotlinx.coroutines Flow traversal). - Docs: README examples for Sequence/navigation/functional APIs, class-level KDoc (thread-safety/complexity), and a CHANGELOG.md. - Ignore subproject build/ directories. - Bump version to 3.4.0. All JVM tests green (core + both modules).
This commit is contained in:
88
tree-structure-serialization/build.gradle.kts
Normal file
88
tree-structure-serialization/build.gradle.kts
Normal file
@@ -0,0 +1,88 @@
|
||||
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.kotlinMultiplatform)
|
||||
alias(libs.plugins.kotlinSerialization)
|
||||
alias(libs.plugins.dokka)
|
||||
alias(libs.plugins.mavenPublish)
|
||||
signing
|
||||
}
|
||||
|
||||
group = "com.github.adriankuta"
|
||||
version = rootProject.version
|
||||
|
||||
mavenPublishing {
|
||||
publishToMavenCentral(automaticRelease = false)
|
||||
signAllPublications()
|
||||
|
||||
coordinates("com.github.adriankuta", "tree-structure-serialization", version.toString())
|
||||
|
||||
pom {
|
||||
name.set("Tree Data Structure — kotlinx.serialization")
|
||||
description.set("kotlinx.serialization support (TreeNodeDto round-trip) for the tree-structure library.")
|
||||
url.set("https://github.com/AdrianKuta/Tree-Data-Structure")
|
||||
licenses {
|
||||
license {
|
||||
name.set("MIT License")
|
||||
url.set("https://opensource.org/licenses/MIT")
|
||||
distribution.set("repo")
|
||||
}
|
||||
}
|
||||
developers {
|
||||
developer {
|
||||
id.set("AdrianKuta")
|
||||
name.set("Adrian Kuta")
|
||||
email.set("adrian.kuta93@gmail.com")
|
||||
}
|
||||
}
|
||||
scm {
|
||||
url.set("https://github.com/AdrianKuta/Tree-Data-Structure")
|
||||
connection.set("scm:git:https://github.com/AdrianKuta/Tree-Data-Structure.git")
|
||||
developerConnection.set("scm:git:ssh://git@github.com/AdrianKuta/Tree-Data-Structure.git")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(21)
|
||||
|
||||
jvm()
|
||||
|
||||
js(IR) {
|
||||
browser()
|
||||
nodejs()
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalWasmDsl::class)
|
||||
wasmJs {
|
||||
browser()
|
||||
nodejs()
|
||||
}
|
||||
|
||||
iosX64()
|
||||
iosArm64()
|
||||
iosSimulatorArm64()
|
||||
|
||||
val hostOs = System.getProperty("os.name")
|
||||
val isMingwX64 = hostOs.startsWith("Windows")
|
||||
when {
|
||||
hostOs == "Mac OS X" -> macosX64("native")
|
||||
hostOs == "Linux" -> linuxX64("native")
|
||||
isMingwX64 -> mingwX64("native")
|
||||
else -> throw GradleException("Host OS is not supported in Kotlin/Native.")
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
commonMain.dependencies {
|
||||
api(project(":"))
|
||||
api(libs.kotlinx.serialization.json)
|
||||
}
|
||||
commonTest.dependencies {
|
||||
implementation(kotlin("test"))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.github.adriankuta.datastructure.tree.serialization
|
||||
|
||||
import com.github.adriankuta.datastructure.tree.TreeNode
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* A serializable, acyclic view of a [TreeNode] subtree. [TreeNode] itself holds a back-reference to
|
||||
* its parent (a cycle), so it cannot be `@Serializable` directly — convert to/from this DTO instead.
|
||||
*
|
||||
* ```
|
||||
* val json = Json.encodeToString(tree.toDto())
|
||||
* val restored = Json.decodeFromString<TreeNodeDto<String>>(json).toTreeNode()
|
||||
* ```
|
||||
*/
|
||||
@Serializable
|
||||
public data class TreeNodeDto<T>(
|
||||
val value: T,
|
||||
val children: List<TreeNodeDto<T>> = emptyList(),
|
||||
)
|
||||
|
||||
/** Converts this subtree into a serializable [TreeNodeDto], preserving values and shape. */
|
||||
public fun <T> TreeNode<T>.toDto(): TreeNodeDto<T> =
|
||||
TreeNodeDto(value, children.map { it.toDto() })
|
||||
|
||||
/** Rebuilds a mutable [TreeNode] tree from this DTO. */
|
||||
public fun <T> TreeNodeDto<T>.toTreeNode(): TreeNode<T> {
|
||||
val node = TreeNode(value)
|
||||
children.forEach { node.addChild(it.toTreeNode()) }
|
||||
return node
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.github.adriankuta.datastructure.tree.serialization
|
||||
|
||||
import com.github.adriankuta.datastructure.tree.structurallyEquals
|
||||
import com.github.adriankuta.datastructure.tree.tree
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class TreeNodeSerializationTest {
|
||||
|
||||
@Test
|
||||
fun roundTripsThroughJson() {
|
||||
val original = tree("World") {
|
||||
child("North America") { child("USA") }
|
||||
child("Europe") {
|
||||
child("Poland")
|
||||
child("Germany")
|
||||
}
|
||||
}
|
||||
|
||||
val json = Json.encodeToString(original.toDto())
|
||||
val restored = Json.decodeFromString<TreeNodeDto<String>>(json).toTreeNode()
|
||||
|
||||
assertTrue(original.structurallyEquals(restored))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun dtoMirrorsTreeShape() {
|
||||
val dto = tree(1) {
|
||||
child(2)
|
||||
child(3) { child(4) }
|
||||
}.toDto()
|
||||
|
||||
assertEquals(1, dto.value)
|
||||
assertEquals(2, dto.children.size)
|
||||
assertEquals(4, dto.children[1].children[0].value)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user