diff --git a/example_test.go b/example_test.go index 8c3f3fb..ffae965 100644 --- a/example_test.go +++ b/example_test.go @@ -4,10 +4,11 @@ import "fmt" func ExampleGenerator() { prime := uint64(32452867) + offset := uint64(0) random := uint64(123456) bits := 30 - generator, err := NewGenerator(prime, random, bits) + generator, err := NewGenerator(prime, random, offset, bits) if err != nil { panic(err) } @@ -35,3 +36,38 @@ func ExampleGenerator() { // 8 => 259549784 => 8 // 9 => 292117339 => 9 } + +func ExampleGenerator_withOffset() { + prime := uint64(32452867) + offset := uint64(10_000_000) + random := uint64(123456) + bits := 30 + + generator, err := NewGenerator(prime, random, offset, bits) + if err != nil { + panic(err) + } + + for num := uint64(0); num < 10; num++ { + enc := generator.Encode(num) + dec := generator.Decode(enc) + + fmt.Printf("%d => %d => %d\n", num, enc, dec) + + if num != dec { + fmt.Printf("oops must be equal: %d != %d\n", num, dec) + } + } + + // Output: + // 0 => 10123456 => 0 + // 1 => 42428867 => 1 + // 2 => 74979014 => 2 + // 3 => 107284425 => 3 + // 4 => 139836620 => 4 + // 5 => 172142031 => 5 + // 6 => 204692178 => 6 + // 7 => 237259733 => 7 + // 8 => 269549784 => 8 + // 9 => 302117339 => 9 +} diff --git a/obfid.go b/obfid.go index 823e6d5..d10c747 100644 --- a/obfid.go +++ b/obfid.go @@ -22,11 +22,12 @@ type Generator struct { prime uint64 inverse uint64 random uint64 + offset uint64 mask uint64 } -// NewGenerator creates a new generator using the provided prime number and random. -func NewGenerator(prime, random uint64, bits int) (*Generator, error) { +// NewGenerator creates a new generator using the provided prime number, random and offset. +func NewGenerator(prime, random, offset uint64, bits int) (*Generator, error) { if bits == 0 || bits > 64 { return nil, ErrTooMuchBits } @@ -41,6 +42,7 @@ func NewGenerator(prime, random uint64, bits int) (*Generator, error) { prime: prime, inverse: inverse, random: random, + offset: offset, mask: mask, } return generator, nil @@ -48,12 +50,12 @@ func NewGenerator(prime, random uint64, bits int) (*Generator, error) { // Encode returns obfuscated number. func (g *Generator) Encode(number uint64) uint64 { - return ((number * g.prime) & g.mask) ^ g.random + return ((number * g.prime) & g.mask) ^ g.random + g.offset } // Decode returns the original (deobfuscated) number. func (g *Generator) Decode(obfuscated uint64) uint64 { - return ((obfuscated ^ g.random) * g.inverse) & g.mask + return (((obfuscated - g.offset) ^ g.random) * g.inverse) & g.mask } // inverse calculates the inverse of prime. diff --git a/obfid_test.go b/obfid_test.go index 61ad1fc..19a3b65 100644 --- a/obfid_test.go +++ b/obfid_test.go @@ -7,7 +7,7 @@ import ( ) func TestGenerator(t *testing.T) { - generator, err := NewGenerator(32452867, 123, 30) + generator, err := NewGenerator(32452867, 123, 0, 30) failIfErr(t, err) for num := uint64(0); num < 30; num++ { @@ -21,7 +21,7 @@ func TestGenerator(t *testing.T) { } func TestGenerator2(t *testing.T) { - generator, err := NewGenerator(32452867, 123, 30) + generator, err := NewGenerator(32452867, 123, 0, 30) failIfErr(t, err) for num := uint64(0); num < 30; num++ { @@ -35,7 +35,7 @@ func TestGenerator2(t *testing.T) { } func TestGeneratorSmall(t *testing.T) { - generator, err := NewGenerator(32452867, 123, 5) + generator, err := NewGenerator(32452867, 123, 0, 5) failIfErr(t, err) res := map[uint64]struct{}{} @@ -64,7 +64,7 @@ func Test_inverse(t *testing.T) { } func BenchmarkEncode(b *testing.B) { - generator, err := NewGenerator(32452867, 123, 30) + generator, err := NewGenerator(32452867, 123, 0, 30) failIfErr(b, err) var count uint64 @@ -76,7 +76,7 @@ func BenchmarkEncode(b *testing.B) { } func BenchmarkDecode(b *testing.B) { - generator, err := NewGenerator(32452867, 123, 30) + generator, err := NewGenerator(32452867, 123, 0, 30) failIfErr(b, err) var count uint64