Skip to content

Commit

Permalink
Merge pull request #5 from yourbasic/tip
Browse files Browse the repository at this point in the history
Adds binary format
  • Loading branch information
korthaj authored May 23, 2017
2 parents 05de11b + 828a5e2 commit 5a59d5e
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 4 deletions.
48 changes: 48 additions & 0 deletions binary.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package bloom

import (
"bytes"
"encoding/gob"
)

const binVer0 = 0

// Data to be included in binary representation of Filter.
type marshalFilter struct {
Version int
Data []uint64
Lookups int
Count int64
}

// MarshalBinary returns a binary representation of the filter.
//
// This method implements the encoding.BinaryMarshaler interface.
// The packages encoding/gob, encoding/json, and encoding/xml
// all check for this interface.
func (f *Filter) MarshalBinary() ([]byte, error) {
mf := marshalFilter{
Version: binVer0,
Data: f.data,
Lookups: f.lookups,
Count: f.count,
}
var b bytes.Buffer
err := gob.NewEncoder(&b).Encode(mf)
return b.Bytes(), err
}

// UnmarshalBinary imports binary data created by MarshalBinary
// into an empty filter. If the filter is not empty, all previous
// entries are overwritten.
func (f *Filter) UnmarshalBinary(data []byte) error {
var mf marshalFilter
err := gob.NewDecoder(bytes.NewBuffer(data)).Decode(&mf)
if err != nil {
return err
}
f.data = mf.Data
f.lookups = mf.Lookups
f.count = mf.Count
return nil
}
30 changes: 30 additions & 0 deletions example_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package bloom_test

import (
"bytes"
"encoding/gob"
"fmt"
"github.com/yourbasic/bloom"
"log"
"math/rand"
"strconv"
)
Expand Down Expand Up @@ -72,3 +75,30 @@ func ExampleFilter_Union() {
fmt.Println("f1 ∪ f2:", f1.Union(f2).Count())
// Output: f1 ∪ f2: 505
}

// Send a filter over a network using the encoding/gob package.
func ExampleFilter_MarshalBinary_network() {
// Create a mock network and a new Filter.
var network bytes.Buffer
f1 := bloom.New(1000, 100)
f1.Add("Hello, filter!")

// Create an encoder and send the filter to the network.
enc := gob.NewEncoder(&network)
if err := enc.Encode(f1); err != nil {
log.Fatal("encode error:", err)
}

// Create a decoder and receive the filter from the network.
dec := gob.NewDecoder(&network)
var f2 bloom.Filter
if err := dec.Decode(&f2); err != nil {
log.Fatal("decode error:", err)
}

// Check that we got the same filter back.
if f2.Test("Hello, filter!") {
fmt.Println("Filter arrived safely.")
}
// Output: Filter arrived safely.
}
9 changes: 5 additions & 4 deletions filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@
// A Bloom filter is a fast and space-efficient probabilistic data structure
// used to test set membership.
//
// A membership test returns either
// ”likely member” or ”definitely not a member”. Only false positives
// can occur: an element that has been added to the filter
// will be identified as ”likely member”.
// A membership test returns either ”likely member” or ”definitely not
// a member”. Only false positives can occur: an element that has been added
// to the filter will always be identified as ”likely member”.
//
// Elements can be added, but not removed. With more elements in the filter,
// the probability of false positives increases.
Expand Down Expand Up @@ -97,11 +96,13 @@ func (f *Filter) add(h1, h2 uint64) bool {
}

// TestByte tells if b is a likely member of the filter.
// If true, b is probably a member; if false, b is definitely not a member.
func (f *Filter) TestByte(b []byte) bool {
return f.test(hash(b))
}

// Test tells if s is a likely member of the filter.
// If true, s is probably a member; if false, s is definitely not a member.
func (f *Filter) Test(s string) bool {
return f.test(hashString(s))
}
Expand Down
24 changes: 24 additions & 0 deletions filter_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package bloom

import (
"bytes"
"encoding/gob"
"reflect"
"testing"
)

Expand Down Expand Up @@ -140,6 +143,27 @@ func TestUnion(t *testing.T) {
}
}

func TestMarshal(t *testing.T) {
var network bytes.Buffer
f1 := New(10000, 100)
f1.Add("Hello, filter!")

enc := gob.NewEncoder(&network)
if err := enc.Encode(f1); err != nil {
t.Errorf("Encode->err = %v; want nil\n", err)
}

dec := gob.NewDecoder(&network)
var f2 *Filter
if err := dec.Decode(&f2); err != nil {
t.Errorf("Decode->err = %v; want nil\n", err)
}

if !reflect.DeepEqual(f1, f2) {
t.Errorf("Encode(Code(f)) = %v; want %v\n", f1, f2)
}
}

var fox string = "The quick brown fox jumps over the lazy dog."

func BenchmarkAdd(b *testing.B) {
Expand Down

0 comments on commit 5a59d5e

Please sign in to comment.