private IEnumerable <HashTableElement> GetNextAvailableSpaceForKeyEnumerable(byte[] key)
        {
            int hash = key.GetHash();
            int initialIndexForKey   = hash % GetTableSize();
            HashTableElement element = GetElementAt(initialIndexForKey);

            yield return(element);

            while (!element.Key.EqualsBytes(NullKey) && element.Index < _simpleCollectionNextIndex.GetNextIndex()) //collision and still within the array's boundries
            {
                int nextIndex = GetNextIndexAfterCollision(element.Index);
                element = GetElementAt(nextIndex);
                if (element.Key.EqualsBytes(key)) //duplicate key
                {
                    throw new InvalidKeyException("That key already exsists in the table");
                }
                if (element.Index == initialIndexForKey) // we've looped all the way around
                {
                    throw new IndexOutOfRangeException("The hash table is full");
                }
                yield return(element);
            }
            if (element.Index >= _simpleCollectionNextIndex.GetNextIndex())
            {
                element = new HashTableElement(key, new byte[GetValueSize()], element.Index);
            }

            yield return(element);
        }
        private IEnumerable <HashTableElement> GetElementWithKeyEnumerable(byte[] key)
        {
            int hash = key.GetHash();
            int nextAvailableArrayIndex = hash % GetTableSize();
            HashTableElement element    = GetElementAt(nextAvailableArrayIndex);

            yield return(element);

            while (!element.Key.EqualsBytes(key) && !element.Key.EqualsBytes(NullKey))
            {
                int nextIndex = GetNextIndexAfterCollision(element.Index);
                while (nextIndex >= _simpleCollectionNextIndex.GetNextIndex()) //there's nothing past this so simulate a wrap around
                {
                    nextIndex = GetNextIndexAfterCollision(element.Index);
                }
                element = GetElementAt(nextIndex);
                //if (element.Key.EqualsBytes(key)) // we've looped all the way around
                //    throw new KeyNotFoundException("key not found");
                yield return(element);
            }
            if (element.Key.EqualsBytes(NullKey)) // key was not located before the null key was found
            {
                throw new KeyNotFoundException("key not found");
            }
        }
        public void Remove(byte[] key)
        {
            AssertValidKey(key);
            //find the element while adding to moveCandidates
            SortedSet <HashTableElement> moveCandidates  = new SortedSet <HashTableElement>();
            HashTableElement             removingElement = null;

            foreach (var hashTableElement in GetElementWithKeyEnumerable(key))
            {
                Debug.Assert(moveCandidates.Add(hashTableElement));
                removingElement = hashTableElement;
            }
            Debug.Assert(removingElement != null, "GetElementWithKeyEnumberable() should have returned at least one element or thrown an exception");

            moveCandidates.Remove(removingElement);

            //null out the element
            WipeArrayAt(removingElement.Index);

            //rehash the elements between the hash and the removed element
            foreach (var moveCandidate in moveCandidates)
            {
                Debug.Assert(!moveCandidate.Key.EqualsBytes(NullKey), "GetElementWithKeyEnumerable() should not return any null elements");
                WipeArrayAt(moveCandidate.Index);
                Put(moveCandidate.Key, moveCandidate.Value);
            }
        }
        private HashTableElement GetElementAt(int index)
        {
            byte[]          getResult = _simpleCollectionNextIndex.Get(index);
            HashTableHeader header    = GetHashTableHeader();

            return(HashTableElement.Deserialize(getResult, index, header.KeySize, header.ValueSize));
        }
        public void Put(byte[] key, byte[] value)
        {
            AssertValidKey(key);
            AssertValidValue(value);
            int putIndex             = GetNextAvailableSpaceForKey(key).Index;
            HashTableElement element = new HashTableElement(key, value, putIndex);

            PutElement(element);
        }
        //private class HashTableElementComparer : IComparer<HashTableElement>
        //{
        //    public int Compare(HashTableElement x, HashTableElement y)
        //    {
        //        return x.Key.GetHash() - y.Key.GetHash();
        //    }
        //}

        private void WipeArrayAt(int index)
        {
            HashTableElement element = new HashTableElement(NullKey, new byte[GetValueSize()], index);

            PutElement(element);
        }
 private void PutElement(HashTableElement element)
 {
     _simpleCollectionNextIndex.Put(element.Index, element.Key.Append(element.Value));
 }