diff --git a/CHANGELOG.md b/CHANGELOG.md index b386db5f2a3..636a3d92034 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## 0.9.9 +* `Versions`: + * `Klock`: `2.5.1` -> `2.5.2` +* `Common`: + * Add new diff tool - `applyDiff` + ## 0.9.8 * `Versions`: diff --git a/common/src/commonMain/kotlin/dev/inmo/micro_utils/common/DiffUtils.kt b/common/src/commonMain/kotlin/dev/inmo/micro_utils/common/DiffUtils.kt index af15eb4ca00..49274f986ed 100644 --- a/common/src/commonMain/kotlin/dev/inmo/micro_utils/common/DiffUtils.kt +++ b/common/src/commonMain/kotlin/dev/inmo/micro_utils/common/DiffUtils.kt @@ -153,3 +153,22 @@ inline fun StrictDiff(old: Iterable, new: Iterable) = old.calculateDif inline fun Iterable.calculateStrictDiff( other: Iterable ) = calculateDiff(other, strictComparison = true) + +/** + * This method call [calculateDiff] with strict mode [strictComparison] and then apply differences to [this] + * mutable list + */ +fun MutableList.applyDiff( + source: Iterable, + strictComparison: Boolean = false +) = calculateDiff(source, strictComparison).let { + for (i in it.removed.indices.sortedDescending()) { + removeAt(it.removed[i].index) + } + it.replaced.forEach { (_, new) -> + set(new.index, new.value) + } + it.added.forEach { (i, t) -> + add(i, t) + } +} diff --git a/common/src/commonTest/kotlin/dev/inmo/micro_utils/common/DiffUtilsTests.kt b/common/src/commonTest/kotlin/dev/inmo/micro_utils/common/DiffUtilsTests.kt index 3cfb9d4add3..251c750026b 100644 --- a/common/src/commonTest/kotlin/dev/inmo/micro_utils/common/DiffUtilsTests.kt +++ b/common/src/commonTest/kotlin/dev/inmo/micro_utils/common/DiffUtilsTests.kt @@ -54,7 +54,7 @@ class DiffUtilsTests { val oldList = (0 until 10).map { it.toString() } val withIndex = oldList.withIndex() - for (step in 0 until oldList.size) { + for (step in oldList.indices) { for ((i, v) in withIndex) { val mutable = oldList.toMutableList() val changes = ( @@ -73,4 +73,78 @@ class DiffUtilsTests { } } } + + @Test + fun testThatSimpleRemoveApplyWorks() { + val oldList = (0 until 10).toList() + val withIndex = oldList.withIndex() + + for (count in 1 .. (floor(oldList.size.toFloat() / 2).toInt())) { + for ((i, _) in withIndex) { + if (i + count > oldList.lastIndex) { + continue + } + val removedSublist = oldList.subList(i, i + count) + val mutableOldList = oldList.toMutableList() + val targetList = oldList - removedSublist + + mutableOldList.applyDiff(targetList) + + assertEquals( + targetList, + mutableOldList + ) + } + } + } + + @Test + fun testThatSimpleAddApplyWorks() { + val oldList = (0 until 10).map { it.toString() } + val withIndex = oldList.withIndex() + + for (count in 1 .. (floor(oldList.size.toFloat() / 2).toInt())) { + for ((i, v) in withIndex) { + if (i + count > oldList.lastIndex) { + continue + } + val addedSublist = oldList.subList(i, i + count).map { "added$it" } + val mutable = oldList.toMutableList() + mutable.addAll(i, addedSublist) + val mutableOldList = oldList.toMutableList() + + mutableOldList.applyDiff(mutable) + + assertEquals( + mutable, + mutableOldList + ) + } + } + } + + @Test + fun testThatSimpleChangesApplyWorks() { + val oldList = (0 until 10).map { it.toString() } + val withIndex = oldList.withIndex() + + for (step in oldList.indices) { + for ((i, v) in withIndex) { + val mutable = oldList.toMutableList() + val changes = ( + if (step == 0) i until oldList.size else (i until oldList.size step step) + ).map { index -> + IndexedValue(index, mutable[index]) to IndexedValue(index, "changed$index").also { + mutable[index] = it.value + } + } + val mutableOldList = oldList.toMutableList() + mutableOldList.applyDiff(mutable) + assertEquals( + mutable, + mutableOldList + ) + } + } + } } diff --git a/gradle.properties b/gradle.properties index 28f1699a489..5a55491619f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,7 +14,7 @@ kotlin_exposed_version=0.37.3 ktor_version=1.6.7 -klockVersion=2.5.1 +klockVersion=2.5.2 github_release_plugin_version=2.2.12