// Returns existing pair or creates a new one.
        private Pair AddPair(int proxyId1, int proxyId2)
        {
            if (proxyId1 > proxyId2)
            {
                CommonMath.Swap(ref proxyId1, ref proxyId2);
            }

            int hash = (int)(Hash((uint)proxyId1, (uint)proxyId2) & TableMask);

            Pair pair = Find(proxyId1, proxyId2, (uint)hash);

            if (pair != null)
            {
                return(pair);
            }

            //Box2DXDebug.Assert(_pairCount < Settings.MaxPairs && _freePair != PairManager.NullPair);

            ushort pairIndex = _freePair;

            pair      = _pairs[pairIndex];
            _freePair = pair.Next;

            pair.ProxyId1 = (ushort)proxyId1;
            pair.ProxyId2 = (ushort)proxyId2;
            pair.Status   = 0;
            pair.UserData = null;
            pair.Next     = _hashTable[hash];

            _hashTable[hash] = pairIndex;

            ++_pairCount;

            return(pair);
        }
        // Removes a pair. The pair must exist.
        private object RemovePair(int proxyId1, int proxyId2)
        {
            //Box2DXDebug.Assert(_pairCount > 0);

            if (proxyId1 > proxyId2)
            {
                CommonMath.Swap(ref proxyId1, ref proxyId2);
            }

            int hash = (int)(Hash((uint)proxyId1, (uint)proxyId2) & TableMask);

            //uint16* node = &m_hashTable[hash];
            ushort node = _hashTable[hash];
            bool   ion  = false;
            int    ni   = 0;

            while (node != NullPair)
            {
                if (Equals(_pairs[node], proxyId1, proxyId2))
                {
                    //uint16 index = *node;
                    //*node = m_pairs[*node].next;

                    ushort index = node;
                    node = _pairs[node].Next;
                    if (ion)
                    {
                        _pairs[ni].Next = node;
                    }
                    else
                    {
                        _hashTable[hash] = node;
                    }

                    Pair   pair     = _pairs[index];
                    object userData = pair.UserData;

                    // Scrub
                    pair.Next     = _freePair;
                    pair.ProxyId1 = NullProxy;
                    pair.ProxyId2 = NullProxy;
                    pair.UserData = null;
                    pair.Status   = 0;

                    _freePair = index;
                    --_pairCount;
                    return(userData);
                }
                else
                {
                    //node = &m_pairs[*node].next;
                    ni   = node;
                    node = _pairs[ni].Next;
                    ion  = true;
                }
            }

            //Box2DXDebug.Assert(false);
            return(null);
        }
        private Pair Find(int proxyId1, int proxyId2)
        {
            if (proxyId1 > proxyId2)
            {
                CommonMath.Swap(ref proxyId1, ref proxyId2);
            }

            uint hash = (uint)(Hash((uint)proxyId1, (uint)proxyId2) & TableMask);

            return(Find(proxyId1, proxyId2, hash));
        }