func (i *InverseBloomFilter) index(data []byte) uint32 {
	hash := i.hashPool.Get().(hash.Hash32)
	hash.Write(data)
	index := hash.Sum32() % uint32(i.capacity)
	hash.Reset()
	i.hashPool.Put(hash)
	return index
}
index returns the array index for the given data.
package boom
import (
	"bytes"
	"encoding/binary"
	"encoding/gob"
	"hash"
	"hash/fnv"
	"io"
	"sync"
	"sync/atomic"
	"unsafe"
)
type InverseBloomFilter struct {
	array    []*[]byte
	hashPool *sync.Pool
	capacity uint
}
func NewInverseBloomFilter(capacity uint) *InverseBloomFilter {
	return &InverseBloomFilter{
		array:    make([]*[]byte, capacity),
		hashPool: &sync.Pool{New: func() interface{} { return fnv.New32() }},
		capacity: capacity,
	}
}
func (i *InverseBloomFilter) Test(data []byte) bool {
	index := i.index(data)
	indexPtr := (*unsafe.Pointer)(unsafe.Pointer(&i.array[index]))
	val := (*[]byte)(atomic.LoadPointer(indexPtr))
	if val == nil {
		return false
	}
	return bytes.Equal(*val, data)
}
func (i *InverseBloomFilter) Add(data []byte) Filter {
	index := i.index(data)
	i.getAndSet(index, data)
	return i
}
func (i *InverseBloomFilter) TestAndAdd(data []byte) bool {
	oldID := i.getAndSet(i.index(data), data)
	return bytes.Equal(oldID, data)
}
func (i *InverseBloomFilter) Capacity() uint {
	return i.capacity
}
func (i *InverseBloomFilter) getAndSet(index uint32, data []byte) []byte {
	indexPtr := (*unsafe.Pointer)(unsafe.Pointer(&i.array[index]))
	keyUnsafe := unsafe.Pointer(&data)
	var oldKey []byte
	for {
		oldKeyUnsafe := atomic.LoadPointer(indexPtr)
		if atomic.CompareAndSwapPointer(indexPtr, oldKeyUnsafe, keyUnsafe) {
			oldKeyPtr := (*[]byte)(oldKeyUnsafe)
			if oldKeyPtr != nil {
				oldKey = *oldKeyPtr
			}
			break
		}
	}
	return oldKey
}