github.com/scottcagno/storage@v1.8.0/pkg/_junk/_lsmtree/container/rbtree/rbtree.go (about)

     1  package rbtree
     2  
     3  import (
     4  	"container/list"
     5  	"encoding/binary"
     6  	"fmt"
     7  	"runtime"
     8  	"strconv"
     9  	"strings"
    10  )
    11  
    12  type rbNodeEntry struct {
    13  	key   string
    14  	value []byte
    15  }
    16  
    17  func (e rbNodeEntry) String() string {
    18  	return fmt.Sprintf("rbNodeEntry.key=%q, rbNodeEntry.value=%q\n", e.key, e.value)
    19  }
    20  
    21  var empty = *new(rbNodeEntry)
    22  
    23  func isempty(e rbNodeEntry) bool {
    24  	return e.key == ""
    25  }
    26  
    27  func compare(this, that rbNodeEntry) int {
    28  	if len(this.key) < len(that.key) {
    29  		return -1
    30  	}
    31  	if len(this.key) > len(that.key) {
    32  		return +1
    33  	}
    34  	if this.key < that.key {
    35  		return -1
    36  	}
    37  	if this.key > that.key {
    38  		return 1
    39  	}
    40  	return 0
    41  }
    42  
    43  const (
    44  	RED   = 0
    45  	BLACK = 1
    46  )
    47  
    48  type rbNode struct {
    49  	left   *rbNode
    50  	right  *rbNode
    51  	parent *rbNode
    52  	color  uint
    53  	entry  rbNodeEntry
    54  }
    55  
    56  func (n *rbNode) String() string {
    57  	left, right, parent := "", "", ""
    58  	if n.left != nil {
    59  		left = n.left.entry.key
    60  	}
    61  	if n.right != nil {
    62  		right = n.right.entry.key
    63  	}
    64  	if n.parent != nil {
    65  		parent = n.parent.entry.key
    66  	}
    67  	return fmt.Sprintf("node.key=%q, node.left=%q, node.right=%q, node.parent=%q",
    68  		n.entry.key, left, right, parent)
    69  
    70  }
    71  
    72  type RBTree = rbTree
    73  
    74  // rbTree is a struct representing a rbTree
    75  type rbTree struct {
    76  	NIL   *rbNode
    77  	root  *rbNode
    78  	count int
    79  	size  int64
    80  }
    81  
    82  func NewRBTree() *rbTree {
    83  	return newRBTree()
    84  }
    85  
    86  // NewTree creates and returns a new rbTree
    87  func newRBTree() *rbTree {
    88  	n := &rbNode{
    89  		left:   nil,
    90  		right:  nil,
    91  		parent: nil,
    92  		color:  BLACK,
    93  		entry:  empty,
    94  	}
    95  	return &rbTree{
    96  		NIL:   n,
    97  		root:  n,
    98  		count: 0,
    99  	}
   100  }
   101  
   102  // Has tests and returns a boolean value if the
   103  // provided key exists in the tree
   104  func (t *rbTree) Has(key string) bool {
   105  	_, ok := t.get(key)
   106  	return ok
   107  }
   108  
   109  // HasInt tests and returns a boolean value if the
   110  // provided key exists in the tree
   111  func (t *rbTree) HasInt(key int64) bool {
   112  	_, ok := t.get(IntToKey(key))
   113  	return ok
   114  }
   115  
   116  // Add adds the provided key and value only if it does not
   117  // already exist in the tree. It returns false if the key and
   118  // value was not able to be added, and true if it was added
   119  // successfully
   120  func (t *rbTree) Add(key string, value []byte) bool {
   121  	_, ok := t.get(key)
   122  	if ok {
   123  		// key already exists, so we are not adding
   124  		return false
   125  	}
   126  	t.put(key, value)
   127  	return true
   128  }
   129  
   130  // AddInt adds the provided key and value only if it does not
   131  // already exist in the tree. It returns false if the key and
   132  // value was not able to be added, and true if it was added
   133  // successfully
   134  func (t *rbTree) AddInt(key int64, value int64) bool {
   135  	_, ok := t.get(IntToKey(key))
   136  	if ok {
   137  		// key already exists, so we are not adding
   138  		return false
   139  	}
   140  	t.put(IntToKey(key), IntToVal(value))
   141  	return true
   142  }
   143  
   144  func (t *rbTree) Put(key string, value []byte) ([]byte, bool) {
   145  	return t.put(key, value)
   146  }
   147  
   148  func (t *rbTree) PutInt(key int64, value int64) (int64, bool) {
   149  	val, ok := t.put(IntToKey(key), IntToVal(value))
   150  	return ValToInt(val), ok
   151  }
   152  
   153  func (t *rbTree) put(key string, value []byte) ([]byte, bool) {
   154  	e := rbNodeEntry{key: key, value: value}
   155  	if isempty(e) {
   156  		return nil, false
   157  	}
   158  	// insert returns the node inserted
   159  	// and if the node returned already
   160  	// existed and/or was updated
   161  	ret, ok := t.insert(&rbNode{
   162  		left:   t.NIL,
   163  		right:  t.NIL,
   164  		parent: t.NIL,
   165  		color:  RED,
   166  		entry:  e,
   167  	})
   168  	return ret.entry.value, ok
   169  }
   170  
   171  func (t *rbTree) Get(key string) ([]byte, bool) {
   172  	return t.get(key)
   173  }
   174  
   175  // GetNearMin performs an approximate search for the specified key
   176  // and returns the closest key that is less than (the predecessor)
   177  // to the searched key as well as a boolean reporting true if an
   178  // exact match was found for the key, and false if it is unknown
   179  // or and exact match was not found
   180  func (t *rbTree) GetNearMin(key string) ([]byte, bool) {
   181  	e := rbNodeEntry{key: key}
   182  	if isempty(e) {
   183  		return nil, false
   184  	}
   185  	ret := t.searchApprox(&rbNode{
   186  		left:   t.NIL,
   187  		right:  t.NIL,
   188  		parent: t.NIL,
   189  		color:  RED,
   190  		entry:  e,
   191  	})
   192  	prev := t.predecessor(ret).entry.value
   193  	if prev == nil {
   194  		_, prev, _ = t.Min()
   195  	}
   196  	return prev, ret.entry.key == key
   197  }
   198  
   199  // GetNearMax performs an approximate search for the specified key
   200  // and returns the closest key that is greater than (the successor)
   201  // to the searched key as well as a boolean reporting true if an
   202  // exact match was found for the key, and false if it is unknown or
   203  // and exact match was not found
   204  func (t *rbTree) GetNearMax(key string) ([]byte, bool) {
   205  	e := rbNodeEntry{key: key}
   206  	if isempty(e) {
   207  		return nil, false
   208  	}
   209  	ret := t.searchApprox(&rbNode{
   210  		left:   t.NIL,
   211  		right:  t.NIL,
   212  		parent: t.NIL,
   213  		color:  RED,
   214  		entry:  e,
   215  	})
   216  	return t.successor(ret).entry.value, ret.entry.key == key
   217  }
   218  
   219  // GetApproxPrevNext performs an approximate search for the specified key
   220  // and returns the searched key, the predecessor, and the successor and a
   221  // boolean reporting true if an exact match was found for the key, and false
   222  // if it is unknown or and exact match was not found
   223  func (t *rbTree) GetApproxPrevNext(key string) ([]byte, []byte, []byte, bool) {
   224  	e := rbNodeEntry{key: key}
   225  	if isempty(e) {
   226  		return nil, nil, nil, false
   227  	}
   228  	ret := t.searchApprox(&rbNode{
   229  		left:   t.NIL,
   230  		right:  t.NIL,
   231  		parent: t.NIL,
   232  		color:  RED,
   233  		entry:  e,
   234  	})
   235  	return ret.entry.value,
   236  		t.predecessor(ret).entry.value,
   237  		t.successor(ret).entry.value,
   238  		ret.entry.key == key
   239  }
   240  
   241  // GetApproxKeyPrevNext performs an approximate search for the specified key
   242  // and returns the searched key, the predecessor, and the successor and a
   243  // boolean reporting true if an exact match was found for the key, and false
   244  // if it is unknown or and exact match was not found
   245  func (t *rbTree) GetApproxKeyPrevNext(key string) (string, string, string, bool) {
   246  	e := rbNodeEntry{key: key}
   247  	if isempty(e) {
   248  		return "", "", "", false
   249  	}
   250  	ret := t.searchApprox(&rbNode{
   251  		left:   t.NIL,
   252  		right:  t.NIL,
   253  		parent: t.NIL,
   254  		color:  RED,
   255  		entry:  e,
   256  	})
   257  	return ret.entry.key,
   258  		t.predecessor(ret).entry.key,
   259  		t.successor(ret).entry.key,
   260  		ret.entry.key == key
   261  }
   262  
   263  func (t *rbTree) GetInt(key int64) (int64, bool) {
   264  	val, ok := t.get(IntToKey(key))
   265  	return ValToInt(val), ok
   266  }
   267  
   268  func (t *rbTree) get(key string) ([]byte, bool) {
   269  	e := rbNodeEntry{key: key}
   270  	if isempty(e) {
   271  		return nil, false
   272  	}
   273  	ret := t.search(&rbNode{
   274  		left:   t.NIL,
   275  		right:  t.NIL,
   276  		parent: t.NIL,
   277  		color:  RED,
   278  		entry:  e,
   279  	})
   280  	return ret.entry.value, !isempty(ret.entry)
   281  }
   282  
   283  func (t *rbTree) Del(key string) ([]byte, bool) {
   284  	return t.del(key)
   285  }
   286  
   287  func (t *rbTree) DelInt(key int64) (int64, bool) {
   288  	val, ok := t.del(IntToKey(key))
   289  	return ValToInt(val), ok
   290  }
   291  
   292  func (t *rbTree) del(key string) ([]byte, bool) {
   293  	e := rbNodeEntry{key: key}
   294  	if isempty(e) {
   295  		return nil, false
   296  	}
   297  	cnt := t.count
   298  	ret := t.delete(&rbNode{
   299  		left:   t.NIL,
   300  		right:  t.NIL,
   301  		parent: t.NIL,
   302  		color:  RED,
   303  		entry:  e,
   304  	})
   305  	return ret.entry.value, cnt == t.count+1
   306  }
   307  
   308  func (t *rbTree) Len() int {
   309  	return t.count
   310  }
   311  
   312  // Size returns the size in bytes
   313  func (t *rbTree) Size() int64 {
   314  	return t.size
   315  }
   316  
   317  func (t *rbTree) Min() (string, []byte, bool) {
   318  	x := t.min(t.root)
   319  	if x == t.NIL {
   320  		return "", nil, false
   321  	}
   322  	return x.entry.key, x.entry.value, true
   323  }
   324  
   325  func (t *rbTree) Max() (string, []byte, bool) {
   326  	x := t.max(t.root)
   327  	if x == t.NIL {
   328  		return "", nil, false
   329  	}
   330  	return x.entry.key, x.entry.value, true
   331  }
   332  
   333  type Iterator func(key string, value []byte) bool
   334  
   335  func (t *rbTree) Scan(iter func(key string, value []byte) bool) {
   336  	t.ascend(t.root, t.min(t.root).entry, iter)
   337  }
   338  
   339  func (t *rbTree) ScanFront(iter Iterator) {
   340  	t.ascend(t.root, t.min(t.root).entry, iter)
   341  }
   342  
   343  func (t *rbTree) ScanBack(iter Iterator) {
   344  	t.descend(t.root, t.max(t.root).entry, iter)
   345  }
   346  
   347  func (t *rbTree) ScanRange(startKey, endKey string, iter Iterator) {
   348  	t.ascendRange(t.root, startKey, endKey, iter)
   349  }
   350  
   351  func (t *rbTree) ToList() (*list.List, error) {
   352  	if t.count < 1 {
   353  		return nil, fmt.Errorf("Error: there are not enough entrys in the tree\n")
   354  	}
   355  	li := list.New()
   356  	t.ascend(t.root, t.min(t.root).entry, func(key string, value []byte) bool {
   357  		li.PushBack(rbNodeEntry{key: key, value: value})
   358  		return true
   359  	})
   360  	return li, nil
   361  }
   362  
   363  func (t *rbTree) FromList(li *list.List) error {
   364  	for e := li.Front(); e != nil; e = e.Next() {
   365  		ent, ok := e.Value.(rbNodeEntry)
   366  		if !ok {
   367  			return fmt.Errorf("Error: cannot add to tree, element (%T) "+
   368  				"does not implement the rbNodeEntry interface\n", ent.value)
   369  		}
   370  		t.put(ent.key, ent.value)
   371  	}
   372  	return nil
   373  }
   374  
   375  func (t *rbTree) String() string {
   376  	var sb strings.Builder
   377  	t.ascend(t.root, t.min(t.root).entry, func(key string, value []byte) bool {
   378  		sb.WriteString(rbNodeEntry{key: key, value: value}.String())
   379  		return true
   380  	})
   381  	return sb.String()
   382  }
   383  
   384  func (t *rbTree) Close() {
   385  	t.NIL = nil
   386  	t.root = nil
   387  	t.count = 0
   388  	return
   389  }
   390  
   391  func (t *rbTree) Reset() {
   392  	t.NIL = nil
   393  	t.root = nil
   394  	t.count = 0
   395  	runtime.GC()
   396  	n := &rbNode{
   397  		left:   nil,
   398  		right:  nil,
   399  		parent: nil,
   400  		color:  BLACK,
   401  		entry:  empty,
   402  	}
   403  	t.NIL = n
   404  	t.root = n
   405  	t.count = 0
   406  }
   407  
   408  func (t *rbTree) insert(z *rbNode) (*rbNode, bool) {
   409  	x := t.root
   410  	y := t.NIL
   411  	for x != t.NIL {
   412  		y = x
   413  		if compare(z.entry, x.entry) == -1 {
   414  			x = x.left
   415  		} else if compare(x.entry, z.entry) == -1 {
   416  			x = x.right
   417  		} else {
   418  			t.size -= int64(len(x.entry.key) + len(x.entry.value))
   419  			t.size += int64(len(z.entry.key) + len(z.entry.value))
   420  			// originally we were just returning x
   421  			// without updating the rbNodeEntry, but if we
   422  			// want it to have similar behavior to
   423  			// a hashmap then we need to update any
   424  			// entries that already exist in the tree
   425  			x.entry = z.entry
   426  			return x, true // true means an existing
   427  			// value was found and updated. It should
   428  			// be noted that we don't need to re-balance
   429  			// the tree because they keys are not changing
   430  			// and the tree is balance is maintained by
   431  			// the keys and not their values.
   432  		}
   433  	}
   434  	z.parent = y
   435  	if y == t.NIL {
   436  		t.root = z
   437  	} else if compare(z.entry, y.entry) == -1 {
   438  		y.left = z
   439  	} else {
   440  		y.right = z
   441  	}
   442  	t.count++
   443  	t.size += int64(len(z.entry.key) + len(z.entry.value))
   444  	t.insertFixup(z)
   445  	return z, false
   446  }
   447  
   448  func (t *rbTree) leftRotate(x *rbNode) {
   449  	if x.right == t.NIL {
   450  		return
   451  	}
   452  	y := x.right
   453  	x.right = y.left
   454  	if y.left != t.NIL {
   455  		y.left.parent = x
   456  	}
   457  	y.parent = x.parent
   458  	if x.parent == t.NIL {
   459  		t.root = y
   460  	} else if x == x.parent.left {
   461  		x.parent.left = y
   462  	} else {
   463  		x.parent.right = y
   464  	}
   465  	y.left = x
   466  	x.parent = y
   467  }
   468  
   469  func (t *rbTree) rightRotate(x *rbNode) {
   470  	if x.left == t.NIL {
   471  		return
   472  	}
   473  	y := x.left
   474  	x.left = y.right
   475  	if y.right != t.NIL {
   476  		y.right.parent = x
   477  	}
   478  	y.parent = x.parent
   479  
   480  	if x.parent == t.NIL {
   481  		t.root = y
   482  	} else if x == x.parent.left {
   483  		x.parent.left = y
   484  	} else {
   485  		x.parent.right = y
   486  	}
   487  
   488  	y.right = x
   489  	x.parent = y
   490  }
   491  
   492  func (t *rbTree) insertFixup(z *rbNode) {
   493  	for z.parent.color == RED {
   494  		if z.parent == z.parent.parent.left {
   495  			y := z.parent.parent.right
   496  			if y.color == RED {
   497  				z.parent.color = BLACK
   498  				y.color = BLACK
   499  				z.parent.parent.color = RED
   500  				z = z.parent.parent
   501  			} else {
   502  				if z == z.parent.right {
   503  					z = z.parent
   504  					t.leftRotate(z)
   505  				}
   506  				z.parent.color = BLACK
   507  				z.parent.parent.color = RED
   508  				t.rightRotate(z.parent.parent)
   509  			}
   510  		} else {
   511  			y := z.parent.parent.left
   512  			if y.color == RED {
   513  				z.parent.color = BLACK
   514  				y.color = BLACK
   515  				z.parent.parent.color = RED
   516  				z = z.parent.parent
   517  			} else {
   518  				if z == z.parent.left {
   519  					z = z.parent
   520  					t.rightRotate(z)
   521  				}
   522  				z.parent.color = BLACK
   523  				z.parent.parent.color = RED
   524  				t.leftRotate(z.parent.parent)
   525  			}
   526  		}
   527  	}
   528  	t.root.color = BLACK
   529  }
   530  
   531  // trying out a slightly different search method
   532  // that (hopefully) will not return nil values and
   533  // instead will return approximate node matches
   534  func (t *rbTree) searchApprox(x *rbNode) *rbNode {
   535  	p := t.root
   536  	for p != t.NIL {
   537  		if compare(p.entry, x.entry) == -1 {
   538  			if p.right == t.NIL {
   539  				break
   540  			}
   541  			p = p.right
   542  		} else if compare(x.entry, p.entry) == -1 {
   543  			if p.left == t.NIL {
   544  				break
   545  			}
   546  			p = p.left
   547  		} else {
   548  			break
   549  		}
   550  	}
   551  	return p
   552  }
   553  
   554  func (t *rbTree) search(x *rbNode) *rbNode {
   555  	p := t.root
   556  	for p != t.NIL {
   557  		if compare(p.entry, x.entry) == -1 {
   558  			p = p.right
   559  		} else if compare(x.entry, p.entry) == -1 {
   560  			p = p.left
   561  		} else {
   562  			break
   563  		}
   564  	}
   565  	return p
   566  }
   567  
   568  // min traverses from root to left recursively until left is NIL
   569  func (t *rbTree) min(x *rbNode) *rbNode {
   570  	if x == t.NIL {
   571  		return t.NIL
   572  	}
   573  	for x.left != t.NIL {
   574  		x = x.left
   575  	}
   576  	return x
   577  }
   578  
   579  // max traverses from root to right recursively until right is NIL
   580  func (t *rbTree) max(x *rbNode) *rbNode {
   581  	if x == t.NIL {
   582  		return t.NIL
   583  	}
   584  	for x.right != t.NIL {
   585  		x = x.right
   586  	}
   587  	return x
   588  }
   589  
   590  func (t *rbTree) predecessor(x *rbNode) *rbNode {
   591  	if x == t.NIL {
   592  		return t.NIL
   593  	}
   594  	if x.left != t.NIL {
   595  		return t.max(x.left)
   596  	}
   597  	y := x.parent
   598  	for y != t.NIL && x == y.left {
   599  		x = y
   600  		y = y.parent
   601  	}
   602  	return y
   603  }
   604  
   605  func (t *rbTree) successor(x *rbNode) *rbNode {
   606  	if x == t.NIL {
   607  		return t.NIL
   608  	}
   609  	if x.right != t.NIL {
   610  		return t.min(x.right)
   611  	}
   612  	y := x.parent
   613  	for y != t.NIL && x == y.right {
   614  		x = y
   615  		y = y.parent
   616  	}
   617  	return y
   618  }
   619  
   620  func (t *rbTree) delete(key *rbNode) *rbNode {
   621  	z := t.search(key)
   622  	if z == t.NIL {
   623  		return t.NIL
   624  	}
   625  	ret := &rbNode{t.NIL, t.NIL, t.NIL, z.color, z.entry}
   626  	var y *rbNode
   627  	var x *rbNode
   628  	if z.left == t.NIL || z.right == t.NIL {
   629  		y = z
   630  	} else {
   631  		y = t.successor(z)
   632  	}
   633  	if y.left != t.NIL {
   634  		x = y.left
   635  	} else {
   636  		x = y.right
   637  	}
   638  	x.parent = y.parent
   639  
   640  	if y.parent == t.NIL {
   641  		t.root = x
   642  	} else if y == y.parent.left {
   643  		y.parent.left = x
   644  	} else {
   645  		y.parent.right = x
   646  	}
   647  	if y != z {
   648  		z.entry = y.entry
   649  	}
   650  	if y.color == BLACK {
   651  		t.deleteFixup(x)
   652  	}
   653  	t.size -= int64(len(ret.entry.key) + len(ret.entry.value))
   654  	t.count--
   655  	return ret
   656  }
   657  
   658  func (t *rbTree) deleteFixup(x *rbNode) {
   659  	for x != t.root && x.color == BLACK {
   660  		if x == x.parent.left {
   661  			w := x.parent.right
   662  			if w.color == RED {
   663  				w.color = BLACK
   664  				x.parent.color = RED
   665  				t.leftRotate(x.parent)
   666  				w = x.parent.right
   667  			}
   668  			if w.left.color == BLACK && w.right.color == BLACK {
   669  				w.color = RED
   670  				x = x.parent
   671  			} else {
   672  				if w.right.color == BLACK {
   673  					w.left.color = BLACK
   674  					w.color = RED
   675  					t.rightRotate(w)
   676  					w = x.parent.right
   677  				}
   678  				w.color = x.parent.color
   679  				x.parent.color = BLACK
   680  				w.right.color = BLACK
   681  				t.leftRotate(x.parent)
   682  				// this is to exit while loop
   683  				x = t.root
   684  			}
   685  		} else {
   686  			w := x.parent.left
   687  			if w.color == RED {
   688  				w.color = BLACK
   689  				x.parent.color = RED
   690  				t.rightRotate(x.parent)
   691  				w = x.parent.left
   692  			}
   693  			if w.left.color == BLACK && w.right.color == BLACK {
   694  				w.color = RED
   695  				x = x.parent
   696  			} else {
   697  				if w.left.color == BLACK {
   698  					w.right.color = BLACK
   699  					w.color = RED
   700  					t.leftRotate(w)
   701  					w = x.parent.left
   702  				}
   703  				w.color = x.parent.color
   704  				x.parent.color = BLACK
   705  				w.left.color = BLACK
   706  				t.rightRotate(x.parent)
   707  				x = t.root
   708  			}
   709  		}
   710  	}
   711  	x.color = BLACK
   712  }
   713  
   714  func (t *rbTree) ascend(x *rbNode, entry rbNodeEntry, iter Iterator) bool {
   715  	if x == t.NIL {
   716  		return true
   717  	}
   718  	if !(compare(x.entry, entry) == -1) {
   719  		if !t.ascend(x.left, entry, iter) {
   720  			return false
   721  		}
   722  		if !iter(x.entry.key, x.entry.value) {
   723  			return false
   724  		}
   725  	}
   726  	return t.ascend(x.right, entry, iter)
   727  }
   728  
   729  func (t *rbTree) Descend(pivot rbNodeEntry, iter Iterator) {
   730  	t.descend(t.root, pivot, iter)
   731  }
   732  
   733  func (t *rbTree) descend(x *rbNode, pivot rbNodeEntry, iter Iterator) bool {
   734  	if x == t.NIL {
   735  		return true
   736  	}
   737  	if !(compare(pivot, x.entry) == -1) {
   738  		if !t.descend(x.right, pivot, iter) {
   739  			return false
   740  		}
   741  		if !iter(x.entry.key, x.entry.value) {
   742  			return false
   743  		}
   744  	}
   745  	return t.descend(x.left, pivot, iter)
   746  }
   747  
   748  func (t *rbTree) ascendRange(x *rbNode, inf, sup string, iter Iterator) bool {
   749  	if x == t.NIL {
   750  		return true
   751  	}
   752  	if !(compare(x.entry, rbNodeEntry{key: sup}) == -1) {
   753  		return t.ascendRange(x.left, inf, sup, iter)
   754  	}
   755  	if compare(x.entry, rbNodeEntry{key: inf}) == -1 {
   756  		return t.ascendRange(x.right, inf, sup, iter)
   757  	}
   758  	if !t.ascendRange(x.left, inf, sup, iter) {
   759  		return false
   760  	}
   761  	if !iter(x.entry.key, x.entry.value) {
   762  		return false
   763  	}
   764  	return t.ascendRange(x.right, inf, sup, iter)
   765  }
   766  
   767  func IntToKey(key int64) string {
   768  	return "i" + strconv.FormatInt(key, 10)
   769  }
   770  
   771  func KeyToInt(key string) int64 {
   772  	if len(key) != 11 || key[0] != 'i' {
   773  		return -1
   774  	}
   775  	ikey, err := strconv.ParseInt(key[1:], 10, 0)
   776  	if err != nil {
   777  		return -1
   778  	}
   779  	return ikey
   780  }
   781  
   782  func IntToVal(val int64) []byte {
   783  	buf := make([]byte, 1+binary.MaxVarintLen64)
   784  	buf[0] = 'i'
   785  	_ = binary.PutVarint(buf[1:], val)
   786  	return buf
   787  }
   788  
   789  func ValToInt(val []byte) int64 {
   790  	if len(val) != 11 || val[0] != 'i' {
   791  		return -1
   792  	}
   793  	ival, n := binary.Varint(val[1:])
   794  	if ival == 0 && n <= 0 {
   795  		return -1
   796  	}
   797  	return ival
   798  }