Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Vindex for ReverseBits
package vindexes
import (
"bytes"
"encoding/binary"
"encoding/hex"
"fmt"
"math/bits"
"github.com/youtube/vitess/go/sqltypes"
)
var (
_ Functional = (*ReverseBits)(nil)
_ Reversible = (*ReverseBits)(nil)
)
// ReverseBits defines vindex that reverses the bits of a number.
// It's Unique, Reversible and Functional.
type ReverseBits struct {
name string
}
// NewReverseBits creates a new ReverseBits.
func NewReverseBits(name string, m map[string]string) (Vindex, error) {
return &ReverseBits{name: name}, nil
}
// String returns the name of the vindex.
func (vind *ReverseBits) String() string {
return vind.name
}
// Cost returns the cost of this index as 1.
func (vind *ReverseBits) Cost() int {
return 1
}
// Map returns the corresponding KeyspaceId values for the given ids.
func (vind *ReverseBits) Map(_ VCursor, ids []sqltypes.Value) ([][]byte, error) {
out := make([][]byte, 0, len(ids))
for _, id := range ids {
num, err := sqltypes.ToUint64(id)
if err != nil {
return nil, fmt.Errorf("ReverseBits.Map: %v", err)
}
out = append(out, reverse(num))
}
return out, nil
}
// Verify returns true if ids maps to ksids.
func (vind *ReverseBits) Verify(_ VCursor, ids []sqltypes.Value, ksids [][]byte) ([]bool, error) {
out := make([]bool, len(ids))
for i := range ids {
num, err := sqltypes.ToUint64(ids[i])
if err != nil {
return nil, fmt.Errorf("ReverseBits.Verify: %v", err)
}
out[i] = (bytes.Compare(reverse(num), ksids[i]) == 0)
}
return out, nil
}
// ReverseMap returns the ids from ksids.
func (vind *ReverseBits) ReverseMap(_ VCursor, ksids [][]byte) ([]sqltypes.Value, error) {
reverseIds := make([]sqltypes.Value, 0, len(ksids))
for _, keyspaceID := range ksids {
val, err := unreverse(keyspaceID)
if err != nil {
return reverseIds, err
}
reverseIds = append(reverseIds, sqltypes.NewUint64(val))
}
return reverseIds, nil
}
func init() {
Register("reverse_bits", NewReverseBits)
}
func reverse(shardKey uint64) []byte {
reversed := make([]byte, 8)
binary.BigEndian.PutUint64(reversed, bits.Reverse64(shardKey))
return reversed
}
func unreverse(k []byte) (uint64, error) {
if len(k) != 8 {
return 0, fmt.Errorf("invalid keyspace id: %v", hex.EncodeToString(k))
}
return bits.Reverse64(binary.BigEndian.Uint64(k)), nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment