private void MakeStack(ShaMapInner root, Hash256 index)
        {
            _inners = new LinkedList <ShaMapInner>();
            var top = root;

            while (true)
            {
                _inners.AddLast(top);
                var existing = top.GetBranch(index);
                if (existing == null)
                {
                    break;
                }
                if (existing.IsLeaf)
                {
                    Leaf     = existing.AsLeaf();
                    _matched = Leaf.Index.Equals(index);
                    break;
                }
                if (existing.IsInner)
                {
                    top = existing.AsInner();
                }
            }
        }
 // Descend into the tree, find the leaf matching this index
 // and if the tree has it.
 protected internal void SetLeaf(ShaMapLeaf leaf)
 {
     if (leaf.Version == -1)
     {
         leaf.Version = Version;
     }
     SetBranch(leaf.Index, leaf);
 }
        public bool AddLeaf(ShaMapLeaf leaf)
        {
            var stack = PathToIndex(leaf.Index);

            if (stack.HasMatchedLeaf())
            {
                return(false);
            }
            var top = stack.DirtyOrCopyInners();

            top.AddLeafToTerminalInner(leaf);
            return(true);
        }
        public bool UpdateLeaf(ShaMapLeaf leaf)
        {
            var stack = PathToIndex(leaf.Index);

            if (!stack.HasMatchedLeaf())
            {
                return(false);
            }
            var top = stack.DirtyOrCopyInners();

            // Why not update in place? Because of structural sharing
            top.SetLeaf(leaf);
            return(true);
        }
        public void CollapseOnlyLeafChildInners()
        {
            Debug.Assert(_dirtied != null);
            ShaMapLeaf onlyChild = null;

            for (var i = _dirtied.Length - 1; i >= 0; i--)
            {
                var next = _dirtied[i];
                if (onlyChild != null)
                {
                    next.SetLeaf(onlyChild);
                }
                onlyChild = next.OnlyChildLeaf();
                if (onlyChild == null)
                {
                    break;
                }
            }
        }
        /// <summary>
        /// This should only be called on the deepest inners, as it
        /// does not do any dirtying. </summary>
        /// <param name="leaf"> to add to inner </param>
        internal void AddLeafToTerminalInner(ShaMapLeaf leaf)
        {
            var branch = GetBranch(leaf.Index);

            if (branch == null)
            {
                SetLeaf(leaf);
            }
            else if (branch.IsInner)
            {
                throw new InvalidOperationException();
            }
            else if (branch.IsLeaf)
            {
                var inner = MakeInnerChild();
                SetBranch(leaf.Index, inner);
                inner.AddLeafToTerminalInner(leaf);
                inner.AddLeafToTerminalInner(branch.AsLeaf());
            }
        }
        /// <returns> the `only child` leaf or null if other children </returns>
        public ShaMapLeaf OnlyChildLeaf()
        {
            ShaMapLeaf leaf   = null;
            var        leaves = 0;

            foreach (var branch in Branches.Where(branch => branch != null))
            {
                if (branch.IsInner)
                {
                    leaf = null;
                    break;
                }
                if (++leaves == 1)
                {
                    leaf = branch.AsLeaf();
                }
                else
                {
                    leaf = null;
                    break;
                }
            }
            return(leaf);
        }