internal int DecodeScalar(DataPacket packet)
        {
            int bits = (int)packet.TryPeekU64Bits(PrefixBitLength, out int bitCnt);

            if (bitCnt == 0)
            {
                return(-1);
            }

            // try to get the value from the prefix list...
            HuffmanNode node = PrefixList[bits];

            if (node != null)
            {
                packet.SkipBits(node.Length);
                return(node.Value);
            }

            // nope, not possible... run the tree
            bits = (int)packet.TryPeekU64Bits(MaxBits, out _);

            node = PrefixOverflowTree;
            do
            {
                if (node.Bits == (bits & node.Mask))
                {
                    packet.SkipBits(node.Length);
                    return(node.Value);
                }
            } while ((node = node.Next) != null);
            return(-1);
        }
        public static void Return(HuffmanNode node)
        {
            if (node == null)
            {
                return;
            }

            if (node.IsInUse)
            {
                node.IsInUse = false;

                lock (_mutex)
                {
                    Return(node.Next);
                    node.Next = null;

                    if (_pool.Count < MAX_NODES)
                    {
                        _pool.Push(node);
                    }
                }
            }
        }
        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    HuffmanPool.Return(PrefixOverflowTree);
                    PrefixOverflowTree = null;

                    for (int i = 0; i < PrefixList.Length; i++)
                    {
                        HuffmanPool.Return(PrefixList[i]);
                    }

                    Array.Clear(PrefixList, 0, PrefixList.Length);
                    PrefixList = null;

                    Lengths     = null;
                    LookupTable = null;
                }

                _disposed = true;
            }
        }
        static internal HuffmanNode[] BuildPrefixedLinkedList(
            Span <int> values, Span <int> lengthList, Span <int> codeList,
            out int tableBits, out HuffmanNode firstOverflowNode)
        {
            var list = new HuffmanNode[lengthList.Length];

            int maxLen = 0;

            for (int i = 0; i < lengthList.Length; i++)
            {
                int nodeLength = lengthList[i] <= 0 ? 99999 : lengthList[i];
                int mask       = (1 << lengthList[i]) - 1;
                list[i] = HuffmanPool.Rent(values[i], nodeLength, codeList[i], mask);

                if (lengthList[i] > 0 && maxLen < lengthList[i])
                {
                    maxLen = lengthList[i];
                }
            }

            tableBits = maxLen > MAX_TABLE_BITS ? MAX_TABLE_BITS : maxLen;
            var prefixList = new HuffmanNode[1 << tableBits];

            Array.Sort(list, 0, lengthList.Length);
            firstOverflowNode = null;

            for (int i = 0; i < lengthList.Length && list[i].Length < 99999; i++)
            {
                if (firstOverflowNode == null)
                {
                    HuffmanNode node = list[i];
                    node.IsLinked = true;

                    if (node.Length > tableBits)
                    {
                        firstOverflowNode = node;
                    }
                    else
                    {
                        int maxVal = 1 << (tableBits - node.Length);
                        for (int j = 0; j < maxVal; j++)
                        {
                            int idx = (j << node.Length) | node.Bits;
                            prefixList[idx] = node;
                        }
                    }
                }
                else
                {
                    list[i - 1].Next = list[i];
                    list[i].IsLinked = true;
                }
            }

            foreach (var node in list)
            {
                if (node != null && !node.IsLinked)
                {
                    HuffmanPool.Return(node);
                }
            }

            return(prefixList);
        }