public static IHashTrieNode?ModifyChildren( InternalNode node, byte h, ulong value, IEnumerable <byte[]> childrenHashes, byte[]?valueHash ) { if (node == null) { throw new ArgumentNullException(nameof(node)); } var was = node.GetChildByHash(h); if (was == value) { return(node); } List <byte[]> newHashes; var newNode = new InternalNode(); var pos = (int)BitsUtils.PositionOf(node.ChildrenMask, h); if (was == 0) { if (valueHash is null) { throw new ArgumentNullException(nameof(valueHash)); } newNode._children = new ulong[node._children.Length + 1]; for (var i = 0; i <= node._children.Length; ++i) { newNode._children[i] = i < pos ? node._children[i] : (i == pos ? value : node._children[i - 1]); } newNode.ChildrenMask = node.ChildrenMask | (1u << h); newHashes = childrenHashes.ToList(); newHashes.Insert(pos, valueHash); newNode.UpdateHash(newHashes, GetChildrenLabels(newNode.ChildrenMask)); return(newNode); } if (value == 0) { if (node._children.Length == 1) { return(null); } newNode._children = new ulong[node._children.Length - 1]; for (var i = 0; i + 1 < node._children.Length; ++i) { newNode._children[i] = i < pos ? node._children[i] : node._children[i + 1]; } newNode.ChildrenMask = node.ChildrenMask ^ (1u << h); newHashes = childrenHashes.ToList(); newHashes.RemoveAt(pos); newNode.UpdateHash(newHashes, GetChildrenLabels(newNode.ChildrenMask)); return(newNode); } newNode._children = node._children.ToArray(); newNode.ChildrenMask = node.ChildrenMask; newNode._children[pos] = value; newHashes = childrenHashes.ToList(); newHashes[pos] = valueHash ?? throw new ArgumentNullException(nameof(valueHash)); newNode.UpdateHash(newHashes, GetChildrenLabels(newNode.ChildrenMask)); return(newNode); }
public ulong GetChildByHash(byte h) { return((ChildrenMask & (1u << h)) == 0 ? 0ul : _children[BitsUtils.PositionOf(ChildrenMask, h)]); }