diff --git a/src/Utils/Data/Immutable/ImmutableTree.cs b/src/Utils/Data/Immutable/ImmutableTree.cs index 7e84f759..cd6a4424 100644 --- a/src/Utils/Data/Immutable/ImmutableTree.cs +++ b/src/Utils/Data/Immutable/ImmutableTree.cs @@ -408,11 +408,12 @@ private ImmutableTree CheckCollision(int hash, TKey key, TValue va return new ImmutableTree(hash, this.storedKey!, this.storedValue!, this.leftNode!, this.rightNode!, ImmutableBucket.Empty.Add(key, value)); - var @new = updateDelegate == null || forceUpdate + var collision = byRef ? this.collisions.GetOrDefaultByRef(key) : this.collisions.GetOrDefaultByValue(key); + var @new = collision == null || updateDelegate == null || forceUpdate ? value - : updateDelegate(this.storedValue!, value); + : updateDelegate(collision, value); - if (ReferenceEquals(@new, this.storedValue)) + if (ReferenceEquals(@new, collision)) return this; return new ImmutableTree(hash, this.storedKey!, this.storedValue!, this.leftNode!, this.rightNode!, @@ -738,4 +739,4 @@ internal class ImmutableRefTreeDebugView where TValue : class [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] public TValue[] Items => tree.Walk().ToArray(); -} \ No newline at end of file +} diff --git a/test/DataTests/TreeTests.cs b/test/DataTests/TreeTests.cs index 5c58648a..5a3e9f30 100644 --- a/test/DataTests/TreeTests.cs +++ b/test/DataTests/TreeTests.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Stashbox.Tests.Utils; using Stashbox.Utils.Data; using Stashbox.Utils.Data.Immutable; @@ -17,38 +18,38 @@ public void Test_Collision_Check() var a = new A(); var b = new B(); var c = new C(); - var imTree = ImmutableTree.Empty; - var tree = new HashTree(); + var imTree = ImmutableTree>.Empty; + var tree = new HashTree>(); - imTree = imTree.AddOrUpdate(key1, a, false); - imTree = imTree.AddOrUpdate(key2, b, false); - tree.Add(key1, a); - tree.Add(key2, b); - - Assert.Equal(a, imTree.GetOrDefaultByValue(key1)); - Assert.Equal(b, imTree.GetOrDefaultByValue(key2)); - Assert.Equal(a, tree.GetOrDefault(key1)); - Assert.Equal(b, tree.GetOrDefault(key2)); + imTree = imTree.AddOrUpdate(key1, [a], false); + imTree = imTree.AddOrUpdate(key2, [b], false); + tree.Add(key1, [a]); + tree.Add(key2, [b]); + + Assert.Equal([a], imTree.GetOrDefaultByValue(key1)); + Assert.Equal([b], imTree.GetOrDefaultByValue(key2)); + Assert.Equal([a], tree.GetOrDefault(key1)); + Assert.Equal([b], tree.GetOrDefault(key2)); - imTree = imTree.AddOrUpdate(key2, c, false, (_, n) => n); + imTree = imTree.AddOrUpdate(key2, [c], false, (list, n) => [..list, ..n]); - Assert.Equal(a, imTree.GetOrDefaultByValue(key1)); - Assert.Equal(c, imTree.GetOrDefaultByValue(key2)); + Assert.Equal([a], imTree.GetOrDefaultByValue(key1)); + Assert.Equal([b, c], imTree.GetOrDefaultByValue(key2)); - imTree = imTree.AddOrUpdate(key2, b, false, true); + imTree = imTree.AddOrUpdate(key2, [b], false, true); - Assert.Equal(a, imTree.GetOrDefaultByValue(key1)); - Assert.Equal(b, imTree.GetOrDefaultByValue(key2)); + Assert.Equal([a], imTree.GetOrDefaultByValue(key1)); + Assert.Equal([b], imTree.GetOrDefaultByValue(key2)); - imTree = imTree.UpdateIfExists(key2, false, _ => c); + imTree = imTree.UpdateIfExists(key2, false, list => [..list, c]); - Assert.Equal(a, imTree.GetOrDefaultByValue(key1)); - Assert.Equal(c, imTree.GetOrDefaultByValue(key2)); + Assert.Equal([a], imTree.GetOrDefaultByValue(key1)); + Assert.Equal([b, c], imTree.GetOrDefaultByValue(key2)); - imTree = imTree.UpdateIfExists(key2, b, false); + imTree = imTree.UpdateIfExists(key2, [b], false); - Assert.Equal(a, imTree.GetOrDefaultByValue(key1)); - Assert.Equal(b, imTree.GetOrDefaultByValue(key2)); + Assert.Equal([a], imTree.GetOrDefaultByValue(key1)); + Assert.Equal([b], imTree.GetOrDefaultByValue(key2)); } [Fact] @@ -59,38 +60,38 @@ public void Test_Ref_Collision_Check() var a = new A(); var b = new B(); var c = new C(); - var imTree = ImmutableTree.Empty; - var tree = new HashTree(); + var imTree = ImmutableTree>.Empty; + var tree = new HashTree>(); - imTree = imTree.AddOrUpdate(key1, a, true); - imTree = imTree.AddOrUpdate(key2, b, true); - tree.Add(key1, a); - tree.Add(key2, b); - - Assert.Equal(a, imTree.GetOrDefaultByRef(key1)); - Assert.Equal(b, imTree.GetOrDefaultByRef(key2)); - Assert.Equal(a, tree.GetOrDefault(key1)); - Assert.Equal(b, tree.GetOrDefault(key2)); + imTree = imTree.AddOrUpdate(key1, [a], true); + imTree = imTree.AddOrUpdate(key2, [b], true); + tree.Add(key1, [a]); + tree.Add(key2, [b]); + + Assert.Equal([a], imTree.GetOrDefaultByRef(key1)); + Assert.Equal([b], imTree.GetOrDefaultByRef(key2)); + Assert.Equal([a], tree.GetOrDefault(key1)); + Assert.Equal([b], tree.GetOrDefault(key2)); - imTree = imTree.AddOrUpdate(key2, c, true, (_, n) => n); + imTree = imTree.AddOrUpdate(key2, [c], true, (list, n) => [..list, ..n]); - Assert.Equal(a, imTree.GetOrDefaultByRef(key1)); - Assert.Equal(c, imTree.GetOrDefaultByRef(key2)); + Assert.Equal([a], imTree.GetOrDefaultByRef(key1)); + Assert.Equal([b, c], imTree.GetOrDefaultByRef(key2)); - imTree = imTree.AddOrUpdate(key2, b, true, true); + imTree = imTree.AddOrUpdate(key2, [b], true, true); - Assert.Equal(a, imTree.GetOrDefaultByRef(key1)); - Assert.Equal(b, imTree.GetOrDefaultByRef(key2)); + Assert.Equal([a], imTree.GetOrDefaultByRef(key1)); + Assert.Equal([b], imTree.GetOrDefaultByRef(key2)); - imTree = imTree.UpdateIfExists(key2, true, _ => c); + imTree = imTree.UpdateIfExists(key2, true, list => [..list, c]); - Assert.Equal(a, imTree.GetOrDefaultByRef(key1)); - Assert.Equal(c, imTree.GetOrDefaultByRef(key2)); + Assert.Equal([a], imTree.GetOrDefaultByRef(key1)); + Assert.Equal([b, c], imTree.GetOrDefaultByRef(key2)); - imTree = imTree.UpdateIfExists(key2, b, true); + imTree = imTree.UpdateIfExists(key2, [b], true); - Assert.Equal(a, imTree.GetOrDefaultByRef(key1)); - Assert.Equal(b, imTree.GetOrDefaultByRef(key2)); + Assert.Equal([a], imTree.GetOrDefaultByRef(key1)); + Assert.Equal([b], imTree.GetOrDefaultByRef(key2)); } [Fact]