-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
144 lines (111 loc) · 3.09 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//abstract out the patterns I'm using to group documents into levelup!
/**
patterns I am currently using:
~PREFIX~[2, group1, group2]
or
~PREFIX~KEY
so, if you get everything between
{start: '~PREFIX~', end: '~PREFIX~~'}
that will be everything in the bucket, note: never use '' or '~' as a key.
I'm using JSON arrays for reduce groups.
I make the first key the depth, so that you can request just the
that works because " (which ends a group) sorts before most characters (except !)
if there was a " in the string, then the order will be different.
gonna put this into the WHO CARES basket.
~ is the highest sorting ascii character
_ is not suitable, since it's in the middle.
! is the first, which is also acceptable,
**/
var order =
'7531902468AOEUIDHTNSPYFGCRLQJKXBMWVZaoeuidhtnspyfgcrlqjkxbmwv'
.split('').sort().join('')
function valid (name, key) {
if(/~/.test(key))
throw new Error(name +' may not include "~" character')
return key
}
function join() {
return '\xFF' + [].join.call(arguments, '~')
}
module.exports = function (bucket) {
var args = [].slice.call(arguments)
//remove any '~'
args.forEach(function (e) {
valid('bucket', e)
})
var bucket = args.join('~')
function fromArray (key) {
if(!Array.isArray(key))
return key
if(key.length > order.length)
throw new Error (
'group key too deep:'
+ JSON.stringify(key)
+ ' max depth is:'
+ order.length
)
var ary = []
key.forEach(valid.bind(null, 'group-key'))
var l = key.length
for(var i=0; i < l && true !== key[i]; i++)
ary.push(key[i])
var r = ary.slice()
r.unshift(order[l])
return r.join('\0')
}
function toKey (key) {
if(!key) return join(bucket)
var ary = [].map.call(arguments, function (key) {
valid('key', key)
return fromArray(key)
})
ary.unshift(bucket)
return join.apply(null, ary)
//return join(bucket, key)
}
toKey.range = function (start, end) {
//this should accept groups also
//the range for the whole bucket.
valid('start', start)
valid('end' , end)
var r = {
start: start ? toKey(start) : toKey()+'~',
end: end ? toKey(end) : (
Array.isArray(start) ? toKey(start)+'~' :toKey()+'~~'
),
within: function (k) {
return toKey.within(r, k)
}
}
return r
}
toKey.within = function (range, key) {
return (
(!range.start || range.start <= key)
&& (!range.end || key <= range.end)
)
}
toKey.unprefix = function (str) {
if(!toKey.range().within(str))
throw new Error(str + ' is not a member of ' + bucket)
return str.split('~').pop()
}
function degroup(key) {
if(key === '0')
return []
var a = order.indexOf(key[0])
try {
var l = key.substring(2).split('\0')
if(l.length == a) return l
} catch (err) {
return null
}
}
toKey.parse = function (str) {
var a = str.toString().substring(1).split('~')
var g = a.pop()
g = degroup(g) || g
return {key: g, prefix: a}
}
return toKey
}