zlmdb 25.12.3__cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- zlmdb/__init__.py +416 -0
- zlmdb/_database.py +990 -0
- zlmdb/_errors.py +31 -0
- zlmdb/_flatc/__init__.py +112 -0
- zlmdb/_flatc/bin/flatc +0 -0
- zlmdb/_lmdb_vendor/__init__.py +37 -0
- zlmdb/_lmdb_vendor/__main__.py +25 -0
- zlmdb/_lmdb_vendor/_config.py +10 -0
- zlmdb/_lmdb_vendor/_lmdb_cffi.cpython-312-aarch64-linux-gnu.so +0 -0
- zlmdb/_lmdb_vendor/cffi.py +2606 -0
- zlmdb/_lmdb_vendor/tool.py +670 -0
- zlmdb/_meta.py +27 -0
- zlmdb/_pmap.py +1667 -0
- zlmdb/_schema.py +137 -0
- zlmdb/_transaction.py +181 -0
- zlmdb/_types.py +1596 -0
- zlmdb/_version.py +27 -0
- zlmdb/cli.py +41 -0
- zlmdb/flatbuffers/__init__.py +60 -0
- zlmdb/flatbuffers/_git_version.py +24 -0
- zlmdb/flatbuffers/_version.py +17 -0
- zlmdb/flatbuffers/builder.py +824 -0
- zlmdb/flatbuffers/compat.py +89 -0
- zlmdb/flatbuffers/encode.py +43 -0
- zlmdb/flatbuffers/flexbuffers.py +1570 -0
- zlmdb/flatbuffers/number_types.py +182 -0
- zlmdb/flatbuffers/packer.py +42 -0
- zlmdb/flatbuffers/reflection/AdvancedFeatures.py +10 -0
- zlmdb/flatbuffers/reflection/BaseType.py +25 -0
- zlmdb/flatbuffers/reflection/Enum.py +252 -0
- zlmdb/flatbuffers/reflection/EnumVal.py +144 -0
- zlmdb/flatbuffers/reflection/Field.py +325 -0
- zlmdb/flatbuffers/reflection/KeyValue.py +84 -0
- zlmdb/flatbuffers/reflection/Object.py +260 -0
- zlmdb/flatbuffers/reflection/RPCCall.py +195 -0
- zlmdb/flatbuffers/reflection/Schema.py +301 -0
- zlmdb/flatbuffers/reflection/SchemaFile.py +112 -0
- zlmdb/flatbuffers/reflection/Service.py +213 -0
- zlmdb/flatbuffers/reflection/Type.py +148 -0
- zlmdb/flatbuffers/reflection/__init__.py +0 -0
- zlmdb/flatbuffers/reflection.bfbs +0 -0
- zlmdb/flatbuffers/reflection.fbs +156 -0
- zlmdb/flatbuffers/table.py +129 -0
- zlmdb/flatbuffers/util.py +47 -0
- zlmdb/py.typed +0 -0
- zlmdb/tests/conftest.py +9 -0
- zlmdb/tests/lmdb/__init__.py +0 -0
- zlmdb/tests/lmdb/address_book.py +287 -0
- zlmdb/tests/lmdb/crash_test.py +339 -0
- zlmdb/tests/lmdb/cursor_test.py +333 -0
- zlmdb/tests/lmdb/env_test.py +919 -0
- zlmdb/tests/lmdb/getmulti_test.py +92 -0
- zlmdb/tests/lmdb/iteration_test.py +258 -0
- zlmdb/tests/lmdb/package_test.py +70 -0
- zlmdb/tests/lmdb/test_lmdb.py +188 -0
- zlmdb/tests/lmdb/testlib.py +185 -0
- zlmdb/tests/lmdb/tool_test.py +60 -0
- zlmdb/tests/lmdb/txn_test.py +575 -0
- zlmdb/tests/orm/MNodeLog.py +853 -0
- zlmdb/tests/orm/__init__.py +0 -0
- zlmdb/tests/orm/_schema_fbs.py +215 -0
- zlmdb/tests/orm/_schema_mnode_log.py +1202 -0
- zlmdb/tests/orm/_schema_py2.py +250 -0
- zlmdb/tests/orm/_schema_py3.py +307 -0
- zlmdb/tests/orm/_test_flatbuffers.py +144 -0
- zlmdb/tests/orm/_test_serialization.py +144 -0
- zlmdb/tests/orm/test_basic.py +217 -0
- zlmdb/tests/orm/test_etcd.py +275 -0
- zlmdb/tests/orm/test_pmap_indexes.py +466 -0
- zlmdb/tests/orm/test_pmap_types.py +90 -0
- zlmdb/tests/orm/test_pmaps.py +295 -0
- zlmdb/tests/orm/test_select.py +619 -0
- zlmdb-25.12.3.dist-info/METADATA +277 -0
- zlmdb-25.12.3.dist-info/RECORD +78 -0
- zlmdb-25.12.3.dist-info/WHEEL +6 -0
- zlmdb-25.12.3.dist-info/entry_points.txt +3 -0
- zlmdb-25.12.3.dist-info/licenses/LICENSE +167 -0
- zlmdb-25.12.3.dist-info/licenses/NOTICE +41 -0
zlmdb/_types.py
ADDED
|
@@ -0,0 +1,1596 @@
|
|
|
1
|
+
###############################################################################
|
|
2
|
+
#
|
|
3
|
+
# The MIT License (MIT)
|
|
4
|
+
#
|
|
5
|
+
# Copyright (c) typedef int GmbH
|
|
6
|
+
#
|
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
# furnished to do so, subject to the following conditions:
|
|
13
|
+
#
|
|
14
|
+
# The above copyright notice and this permission notice shall be included in
|
|
15
|
+
# all copies or substantial portions of the Software.
|
|
16
|
+
#
|
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23
|
+
# THE SOFTWARE.
|
|
24
|
+
#
|
|
25
|
+
###############################################################################
|
|
26
|
+
|
|
27
|
+
import struct
|
|
28
|
+
import random
|
|
29
|
+
import binascii
|
|
30
|
+
import pickle
|
|
31
|
+
import os
|
|
32
|
+
import uuid
|
|
33
|
+
import json
|
|
34
|
+
|
|
35
|
+
import cbor2
|
|
36
|
+
import flatbuffers
|
|
37
|
+
from time import time_ns
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
import numpy as np
|
|
41
|
+
except ImportError:
|
|
42
|
+
HAS_NUMPY = False
|
|
43
|
+
else:
|
|
44
|
+
HAS_NUMPY = True
|
|
45
|
+
|
|
46
|
+
CHARSET = "345679ACEFGHJKLMNPQRSTUVWXY"
|
|
47
|
+
"""
|
|
48
|
+
Charset from which to generate random key IDs.
|
|
49
|
+
|
|
50
|
+
.. note::
|
|
51
|
+
|
|
52
|
+
We take out the following 9 chars (leaving 27), because there is visual ambiguity: 0/O/D, 1/I, 8/B, 2/Z.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
CHAR_GROUPS = 4
|
|
56
|
+
CHARS_PER_GROUP = 6
|
|
57
|
+
GROUP_SEP = "-"
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _random_string():
|
|
61
|
+
"""
|
|
62
|
+
Generate a globally unique serial / product code of the form ``u'YRAC-EL4X-FQQE-AW4T-WNUV-VN6T'``.
|
|
63
|
+
The generated value is cryptographically strong and has (at least) 114 bits of entropy.
|
|
64
|
+
|
|
65
|
+
:return: new random string key
|
|
66
|
+
"""
|
|
67
|
+
rng = random.SystemRandom()
|
|
68
|
+
token_value = "".join(
|
|
69
|
+
rng.choice(CHARSET) for _ in range(CHAR_GROUPS * CHARS_PER_GROUP)
|
|
70
|
+
)
|
|
71
|
+
if CHARS_PER_GROUP > 1:
|
|
72
|
+
return GROUP_SEP.join(map("".join, zip(*[iter(token_value)] * CHARS_PER_GROUP)))
|
|
73
|
+
else:
|
|
74
|
+
return token_value
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def dt_to_bytes(dt):
|
|
78
|
+
"""
|
|
79
|
+
Serialize a timestamp in big-endian byte order.
|
|
80
|
+
|
|
81
|
+
:param dt: Timestamp to serialize.
|
|
82
|
+
:return: Serialized bytes.
|
|
83
|
+
"""
|
|
84
|
+
assert isinstance(dt, np.datetime64)
|
|
85
|
+
|
|
86
|
+
data = bytearray(dt.tobytes())
|
|
87
|
+
# FIXME: this must depend on host CPU arch
|
|
88
|
+
data.reverse()
|
|
89
|
+
return bytes(data)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def bytes_to_dt(data):
|
|
93
|
+
"""
|
|
94
|
+
Deserialize a timestamp from big-endian byte order data.
|
|
95
|
+
|
|
96
|
+
:param data: Data to deserialize.
|
|
97
|
+
:return: Deserialized timestamp.
|
|
98
|
+
"""
|
|
99
|
+
assert type(data) == bytes
|
|
100
|
+
|
|
101
|
+
data = bytearray(data)
|
|
102
|
+
# FIXME: this must depend on host CPU arch
|
|
103
|
+
data.reverse()
|
|
104
|
+
dt = np.frombuffer(bytes(data), dtype="datetime64[ns]")[0]
|
|
105
|
+
return dt
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
#
|
|
109
|
+
# Key Types
|
|
110
|
+
#
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class _OidKeysMixin(object):
|
|
114
|
+
MAX_OID = 9007199254740992
|
|
115
|
+
"""
|
|
116
|
+
Valid OID are from the integer range [0, MAX_OID].
|
|
117
|
+
|
|
118
|
+
The upper bound 2**53 is chosen since it is the maximum integer that can be
|
|
119
|
+
represented as a IEEE double such that all smaller integers are representable as well.
|
|
120
|
+
|
|
121
|
+
Hence, IDs can be safely used with languages that use IEEE double as their
|
|
122
|
+
main (or only) number type (JavaScript, Lua, etc).
|
|
123
|
+
"""
|
|
124
|
+
|
|
125
|
+
@staticmethod
|
|
126
|
+
def new_key(secure=False):
|
|
127
|
+
if secure:
|
|
128
|
+
while True:
|
|
129
|
+
data = os.urandom(8)
|
|
130
|
+
key = struct.unpack(">Q", data)[0]
|
|
131
|
+
if key <= _OidKeysMixin.MAX_OID:
|
|
132
|
+
return key
|
|
133
|
+
else:
|
|
134
|
+
random.randint(0, _OidKeysMixin.MAX_OID)
|
|
135
|
+
|
|
136
|
+
def _serialize_key(self, key):
|
|
137
|
+
assert type(key) == int
|
|
138
|
+
assert key >= 0 and key <= _OidKeysMixin.MAX_OID
|
|
139
|
+
return struct.pack(">Q", key)
|
|
140
|
+
|
|
141
|
+
def _deserialize_key(self, data):
|
|
142
|
+
return struct.unpack(">Q", data)[0]
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class _OidOidKeysMixin(object):
|
|
146
|
+
@staticmethod
|
|
147
|
+
def new_key(secure=False):
|
|
148
|
+
return _OidKeysMixin.new_key(secure=secure), _OidKeysMixin.new_key(
|
|
149
|
+
secure=secure
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
def _serialize_key(self, keys):
|
|
153
|
+
assert type(keys) == tuple
|
|
154
|
+
assert len(keys) == 2
|
|
155
|
+
key1, key2 = keys
|
|
156
|
+
assert type(key1) == int
|
|
157
|
+
assert key1 >= 0 and key1 <= _OidKeysMixin.MAX_OID
|
|
158
|
+
assert type(key2) == int
|
|
159
|
+
assert key2 >= 0 and key2 <= _OidKeysMixin.MAX_OID
|
|
160
|
+
return struct.pack(">QQ", key1, key2)
|
|
161
|
+
|
|
162
|
+
def _deserialize_key(self, data):
|
|
163
|
+
assert len(data) == 16
|
|
164
|
+
return struct.unpack(">QQ", data)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
class _Oid3KeysMixin(object):
|
|
168
|
+
@staticmethod
|
|
169
|
+
def new_key(secure=False):
|
|
170
|
+
return (
|
|
171
|
+
_OidKeysMixin.new_key(secure=secure),
|
|
172
|
+
_OidKeysMixin.new_key(secure=secure),
|
|
173
|
+
_OidKeysMixin.new_key(secure=secure),
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
def _serialize_key(self, keys):
|
|
177
|
+
assert type(keys) == tuple
|
|
178
|
+
assert len(keys) == 3
|
|
179
|
+
key1, key2, key3 = keys
|
|
180
|
+
assert type(key1) == int
|
|
181
|
+
assert key1 >= 0 and key1 <= _OidKeysMixin.MAX_OID
|
|
182
|
+
assert type(key2) == int
|
|
183
|
+
assert key2 >= 0 and key2 <= _OidKeysMixin.MAX_OID
|
|
184
|
+
assert type(key3) == int
|
|
185
|
+
assert key3 >= 0 and key3 <= _OidKeysMixin.MAX_OID
|
|
186
|
+
return struct.pack(">QQQ", key1, key2, key3)
|
|
187
|
+
|
|
188
|
+
def _deserialize_key(self, data):
|
|
189
|
+
assert len(data) == 24
|
|
190
|
+
return struct.unpack(">QQQ", data)
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
class _OidTimestampKeysMixin(object):
|
|
194
|
+
@staticmethod
|
|
195
|
+
def new_key(secure=False):
|
|
196
|
+
return _OidKeysMixin.new_key(secure=secure), 0
|
|
197
|
+
|
|
198
|
+
def _serialize_key(self, keys):
|
|
199
|
+
assert type(keys) == tuple
|
|
200
|
+
assert len(keys) == 2
|
|
201
|
+
key1, key2 = keys
|
|
202
|
+
assert type(key1) == int
|
|
203
|
+
assert key1 >= 0 and key1 <= _OidKeysMixin.MAX_OID
|
|
204
|
+
assert isinstance(key2, np.datetime64)
|
|
205
|
+
return struct.pack(">Q", key1) + key2.tobytes()
|
|
206
|
+
|
|
207
|
+
def _deserialize_key(self, data):
|
|
208
|
+
assert len(data) == 16
|
|
209
|
+
key1, key2 = struct.unpack(">Q>Q", data)
|
|
210
|
+
key2 = np.datetime64(key2, "ns")
|
|
211
|
+
return key1, key2
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
class _OidTimestampStringKeysMixin(object):
|
|
215
|
+
@staticmethod
|
|
216
|
+
def new_key(secure=False):
|
|
217
|
+
return _OidKeysMixin.new_key(secure=secure), 0, ""
|
|
218
|
+
|
|
219
|
+
def _serialize_key(self, keys):
|
|
220
|
+
assert type(keys) == tuple
|
|
221
|
+
assert len(keys) == 3
|
|
222
|
+
key1, key2, key3 = keys
|
|
223
|
+
assert type(key1) == int
|
|
224
|
+
assert key1 >= 0 and key1 <= _OidKeysMixin.MAX_OID
|
|
225
|
+
assert isinstance(key2, np.datetime64)
|
|
226
|
+
assert type(key3) == str
|
|
227
|
+
return struct.pack(">Q", key1) + key2.tobytes() + key3.encode("utf8")
|
|
228
|
+
|
|
229
|
+
def _deserialize_key(self, data):
|
|
230
|
+
assert type(data) == bytes
|
|
231
|
+
assert len(data) > 16
|
|
232
|
+
|
|
233
|
+
oid, ts = struct.unpack(">Q>Q", data[:16])
|
|
234
|
+
ts = np.datetime64(ts, "ns")
|
|
235
|
+
s = data[16:]
|
|
236
|
+
return oid, ts, s
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
class _OidStringKeysMixin(object):
|
|
240
|
+
@staticmethod
|
|
241
|
+
def new_key(secure=False):
|
|
242
|
+
return _OidKeysMixin.new_key(secure=secure), ""
|
|
243
|
+
|
|
244
|
+
def _serialize_key(self, key1_key2):
|
|
245
|
+
assert type(key1_key2) == tuple and len(key1_key2) == 2
|
|
246
|
+
key1, key2 = key1_key2
|
|
247
|
+
|
|
248
|
+
assert type(key1) == int
|
|
249
|
+
assert type(key2) == str
|
|
250
|
+
|
|
251
|
+
return struct.pack(">Q", key1) + key2.encode("utf8")
|
|
252
|
+
|
|
253
|
+
def _deserialize_key(self, data):
|
|
254
|
+
assert type(data) == bytes
|
|
255
|
+
assert len(data) > 8
|
|
256
|
+
oid = struct.unpack(">Q", data[:8])[0]
|
|
257
|
+
data = data[8:]
|
|
258
|
+
s = data.decode("utf8")
|
|
259
|
+
return oid, s
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
class _StringOidKeysMixin(object):
|
|
263
|
+
@staticmethod
|
|
264
|
+
def new_key(secure=False):
|
|
265
|
+
return _random_string(), _OidKeysMixin.new_key(secure=secure)
|
|
266
|
+
|
|
267
|
+
def _serialize_key(self, key1_key2):
|
|
268
|
+
assert type(key1_key2) == tuple and len(key1_key2) == 2
|
|
269
|
+
key1, key2 = key1_key2
|
|
270
|
+
|
|
271
|
+
assert type(key1) == str
|
|
272
|
+
assert type(key2) == int
|
|
273
|
+
|
|
274
|
+
return key1.encode("utf8") + struct.pack(">Q", key2)
|
|
275
|
+
|
|
276
|
+
def _deserialize_key(self, data):
|
|
277
|
+
assert type(data) == bytes
|
|
278
|
+
assert len(data) > 8
|
|
279
|
+
oid = struct.unpack(">Q", data[-8:])[0]
|
|
280
|
+
data = data[0:8]
|
|
281
|
+
s = data.decode("utf8")
|
|
282
|
+
return s, oid
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
class _StringKeysMixin(object):
|
|
286
|
+
@staticmethod
|
|
287
|
+
def new_key():
|
|
288
|
+
return _random_string()
|
|
289
|
+
|
|
290
|
+
def _serialize_key(self, key):
|
|
291
|
+
assert type(key) == str
|
|
292
|
+
|
|
293
|
+
return key.encode("utf8")
|
|
294
|
+
|
|
295
|
+
def _deserialize_key(self, data):
|
|
296
|
+
assert type(data) == bytes
|
|
297
|
+
|
|
298
|
+
return data.decode("utf8")
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
class _StringStringKeysMixin(object):
|
|
302
|
+
@staticmethod
|
|
303
|
+
def new_key():
|
|
304
|
+
return _random_string(), _random_string()
|
|
305
|
+
|
|
306
|
+
def _serialize_key(self, key1_key2):
|
|
307
|
+
assert type(key1_key2) == tuple and len(key1_key2) == 2
|
|
308
|
+
key1, key2 = key1_key2
|
|
309
|
+
|
|
310
|
+
assert type(key1) == str
|
|
311
|
+
assert type(key2) == str
|
|
312
|
+
|
|
313
|
+
return key1.encode("utf8") + b"\x00" + key2.encode("utf8")
|
|
314
|
+
|
|
315
|
+
def _deserialize_key(self, data):
|
|
316
|
+
assert type(data) == bytes
|
|
317
|
+
assert len(data) > 0
|
|
318
|
+
d = data.split(b"\x00")
|
|
319
|
+
assert len(d) == 2
|
|
320
|
+
return d[0], d[1]
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
class _StringStringStringKeysMixin(object):
|
|
324
|
+
@staticmethod
|
|
325
|
+
def new_key():
|
|
326
|
+
return _random_string(), _random_string(), _random_string()
|
|
327
|
+
|
|
328
|
+
def _serialize_key(self, key1_key2_key3):
|
|
329
|
+
assert type(key1_key2_key3) == tuple and len(key1_key2_key3) == 3
|
|
330
|
+
key1, key2, key3 = key1_key2_key3
|
|
331
|
+
|
|
332
|
+
assert type(key1) == str
|
|
333
|
+
assert type(key2) == str
|
|
334
|
+
assert type(key3) == str
|
|
335
|
+
|
|
336
|
+
return (
|
|
337
|
+
key1.encode("utf8")
|
|
338
|
+
+ b"\x00"
|
|
339
|
+
+ key2.encode("utf8")
|
|
340
|
+
+ b"\x00"
|
|
341
|
+
+ key3.encode("utf8")
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
def _deserialize_key(self, data):
|
|
345
|
+
assert type(data) == bytes
|
|
346
|
+
assert len(data) > 0
|
|
347
|
+
d = data.split(b"\x00")
|
|
348
|
+
assert len(d) == 3
|
|
349
|
+
return d[0], d[1], d[2]
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
class _UuidKeysMixin(object):
|
|
353
|
+
@staticmethod
|
|
354
|
+
def new_key():
|
|
355
|
+
# https: // docs.python.org / 3 / library / uuid.html # uuid.uuid4
|
|
356
|
+
# return uuid.UUID(bytes=os.urandom(16))
|
|
357
|
+
return uuid.uuid4()
|
|
358
|
+
|
|
359
|
+
def _serialize_key(self, key):
|
|
360
|
+
assert isinstance(key, uuid.UUID), 'key must be an UUID, but was "{}"'.format(
|
|
361
|
+
key
|
|
362
|
+
)
|
|
363
|
+
|
|
364
|
+
# The UUID as a 16-byte string (containing the six integer fields in big-endian byte order).
|
|
365
|
+
# https://docs.python.org/3/library/uuid.html#uuid.UUID.bytes
|
|
366
|
+
return key.bytes
|
|
367
|
+
|
|
368
|
+
def _deserialize_key(self, data):
|
|
369
|
+
assert type(data) == bytes
|
|
370
|
+
|
|
371
|
+
return uuid.UUID(bytes=data)
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
class _UuidUuidKeysMixin(object):
|
|
375
|
+
def _serialize_key(self, key1_key2):
|
|
376
|
+
assert type(key1_key2) == tuple and len(key1_key2) == 2
|
|
377
|
+
key1, key2 = key1_key2
|
|
378
|
+
|
|
379
|
+
if key1 is None:
|
|
380
|
+
key1 = uuid.UUID(bytes=b"\x00" * 16)
|
|
381
|
+
if key2 is None:
|
|
382
|
+
key2 = uuid.UUID(bytes=b"\x00" * 16)
|
|
383
|
+
|
|
384
|
+
assert isinstance(key1, uuid.UUID)
|
|
385
|
+
assert isinstance(key2, uuid.UUID)
|
|
386
|
+
|
|
387
|
+
return key1.bytes + key2.bytes
|
|
388
|
+
|
|
389
|
+
def _deserialize_key(self, data):
|
|
390
|
+
assert type(data) == bytes
|
|
391
|
+
assert len(data) == 32
|
|
392
|
+
|
|
393
|
+
data1, data2 = data[0:16], data[16:32]
|
|
394
|
+
return uuid.UUID(bytes=data1), uuid.UUID(bytes=data2)
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
class _UuidUuidUuidKeysMixin(object):
|
|
398
|
+
def _serialize_key(self, key1_key2_key3):
|
|
399
|
+
assert type(key1_key2_key3) == tuple and len(key1_key2_key3) == 3
|
|
400
|
+
key1, key2, key3 = key1_key2_key3
|
|
401
|
+
|
|
402
|
+
if key1 is None:
|
|
403
|
+
key1 = uuid.UUID(bytes=b"\x00" * 16)
|
|
404
|
+
if key2 is None:
|
|
405
|
+
key2 = uuid.UUID(bytes=b"\x00" * 16)
|
|
406
|
+
if key3 is None:
|
|
407
|
+
key3 = uuid.UUID(bytes=b"\x00" * 16)
|
|
408
|
+
|
|
409
|
+
assert isinstance(key1, uuid.UUID)
|
|
410
|
+
assert isinstance(key2, uuid.UUID)
|
|
411
|
+
assert isinstance(key3, uuid.UUID)
|
|
412
|
+
|
|
413
|
+
return key1.bytes + key2.bytes + key3.bytes
|
|
414
|
+
|
|
415
|
+
def _deserialize_key(self, data):
|
|
416
|
+
assert type(data) == bytes
|
|
417
|
+
assert len(data) == 48
|
|
418
|
+
|
|
419
|
+
data1, data2, data3 = data[0:16], data[16:32], data[32:48]
|
|
420
|
+
return uuid.UUID(bytes=data1), uuid.UUID(bytes=data2), uuid.UUID(bytes=data3)
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
class _UuidUuidUuidUuidKeysMixin(object):
|
|
424
|
+
def _serialize_key(self, key1_key2_key3_key4):
|
|
425
|
+
assert type(key1_key2_key3_key4) == tuple and len(key1_key2_key3_key4) == 4
|
|
426
|
+
key1, key2, key3, key4 = key1_key2_key3_key4
|
|
427
|
+
|
|
428
|
+
if key1 is None:
|
|
429
|
+
key1 = uuid.UUID(bytes=b"\x00" * 16)
|
|
430
|
+
if key2 is None:
|
|
431
|
+
key2 = uuid.UUID(bytes=b"\x00" * 16)
|
|
432
|
+
if key3 is None:
|
|
433
|
+
key3 = uuid.UUID(bytes=b"\x00" * 16)
|
|
434
|
+
if key4 is None:
|
|
435
|
+
key4 = uuid.UUID(bytes=b"\x00" * 16)
|
|
436
|
+
|
|
437
|
+
assert isinstance(key1, uuid.UUID)
|
|
438
|
+
assert isinstance(key2, uuid.UUID)
|
|
439
|
+
assert isinstance(key3, uuid.UUID)
|
|
440
|
+
assert isinstance(key4, uuid.UUID)
|
|
441
|
+
|
|
442
|
+
return key1.bytes + key2.bytes + key3.bytes + key4.bytes
|
|
443
|
+
|
|
444
|
+
def _deserialize_key(self, data):
|
|
445
|
+
assert type(data) == bytes
|
|
446
|
+
assert len(data) == 64
|
|
447
|
+
|
|
448
|
+
data1, data2, data3, data4 = data[0:16], data[16:32], data[32:48], data[48:64]
|
|
449
|
+
return (
|
|
450
|
+
uuid.UUID(bytes=data1),
|
|
451
|
+
uuid.UUID(bytes=data2),
|
|
452
|
+
uuid.UUID(bytes=data3),
|
|
453
|
+
uuid.UUID(bytes=data4),
|
|
454
|
+
)
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
class _Uint16UuidTimestampKeysMixin(object):
|
|
458
|
+
@staticmethod
|
|
459
|
+
def new_key():
|
|
460
|
+
return random.randint(0, 2**16), uuid.uuid4(), np.datetime64(time_ns(), "ns")
|
|
461
|
+
|
|
462
|
+
def _serialize_key(self, key1_key2_key3):
|
|
463
|
+
assert type(key1_key2_key3) == tuple and len(key1_key2_key3) == 3
|
|
464
|
+
key1, key2, key3 = key1_key2_key3
|
|
465
|
+
|
|
466
|
+
if key1 is None:
|
|
467
|
+
key1 = 0
|
|
468
|
+
if key2 is None:
|
|
469
|
+
key2 = uuid.UUID(bytes=b"\x00" * 16)
|
|
470
|
+
if key3 is None:
|
|
471
|
+
key3 = np.datetime64(0, "ns")
|
|
472
|
+
|
|
473
|
+
assert type(key1) == int and key1 >= 0 and key1 < 2**16
|
|
474
|
+
assert isinstance(key2, uuid.UUID)
|
|
475
|
+
assert isinstance(key3, np.datetime64)
|
|
476
|
+
|
|
477
|
+
return struct.pack("H", key1) + key2.bytes + dt_to_bytes(key3)
|
|
478
|
+
|
|
479
|
+
def _deserialize_key(self, data):
|
|
480
|
+
assert type(data) == bytes and len(data) == (2 + 16 + 8)
|
|
481
|
+
|
|
482
|
+
data1, data2, data3 = (
|
|
483
|
+
data[0:2],
|
|
484
|
+
data[2:18],
|
|
485
|
+
data[18:26],
|
|
486
|
+
)
|
|
487
|
+
return struct.unpack("H", data1), uuid.UUID(bytes=data2), bytes_to_dt(data3)
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
class _UuidBytes20Uint8KeysMixin(object):
|
|
491
|
+
@staticmethod
|
|
492
|
+
def new_key():
|
|
493
|
+
return uuid.uuid4(), os.urandom(20), random.randint(0, 255)
|
|
494
|
+
|
|
495
|
+
def _serialize_key(self, key1_key2_key3):
|
|
496
|
+
assert type(key1_key2_key3) == tuple and len(key1_key2_key3) == 3
|
|
497
|
+
key1, key2, key3 = key1_key2_key3
|
|
498
|
+
|
|
499
|
+
if key1 is None:
|
|
500
|
+
key1 = uuid.UUID(bytes=b"\x00" * 16)
|
|
501
|
+
if key2 is None:
|
|
502
|
+
key2 = b"\x00" * 20
|
|
503
|
+
if key3 is None:
|
|
504
|
+
key3 = 0
|
|
505
|
+
|
|
506
|
+
assert isinstance(key1, uuid.UUID)
|
|
507
|
+
assert type(key2) == bytes and len(key2) == 20
|
|
508
|
+
|
|
509
|
+
# FIXME: workaround to process eg (3,)
|
|
510
|
+
if type(key3) == tuple and len(key3) == 1:
|
|
511
|
+
key3 = key3[0]
|
|
512
|
+
assert type(key3) == int and key3 >= 0 and key3 < 256
|
|
513
|
+
|
|
514
|
+
return key1.bytes + key2 + struct.pack("B", key3)
|
|
515
|
+
|
|
516
|
+
def _deserialize_key(self, data):
|
|
517
|
+
assert type(data) == bytes and len(data) == (16 + 20 + 1)
|
|
518
|
+
|
|
519
|
+
data1, data2, data3 = (
|
|
520
|
+
data[0:16],
|
|
521
|
+
data[16:36],
|
|
522
|
+
data[36:37],
|
|
523
|
+
)
|
|
524
|
+
return uuid.UUID(bytes=data1), data2, struct.unpack("B", data3)
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
class _UuidBytes20Uint8UuidKeysMixin(object):
|
|
528
|
+
@staticmethod
|
|
529
|
+
def new_key():
|
|
530
|
+
return uuid.uuid4(), os.urandom(20), random.randint(0, 255), uuid.uuid4()
|
|
531
|
+
|
|
532
|
+
def _serialize_key(self, key1_key2_key3_key4):
|
|
533
|
+
assert type(key1_key2_key3_key4) == tuple and len(key1_key2_key3_key4) == 4
|
|
534
|
+
key1, key2, key3, key4 = key1_key2_key3_key4
|
|
535
|
+
|
|
536
|
+
if key1 is None:
|
|
537
|
+
key1 = uuid.UUID(bytes=b"\x00" * 16)
|
|
538
|
+
if key2 is None:
|
|
539
|
+
key2 = b"\x00" * 20
|
|
540
|
+
if key3 is None:
|
|
541
|
+
key3 = 0
|
|
542
|
+
if key4 is None:
|
|
543
|
+
key4 = uuid.UUID(bytes=b"\x00" * 16)
|
|
544
|
+
|
|
545
|
+
assert isinstance(key1, uuid.UUID)
|
|
546
|
+
assert type(key2) == bytes and len(key2) == 20
|
|
547
|
+
assert type(key3) == int and key3 >= 0 and key3 < 256
|
|
548
|
+
assert isinstance(key4, uuid.UUID)
|
|
549
|
+
|
|
550
|
+
return key1.bytes + key2 + struct.pack("B", key3) + key4.bytes
|
|
551
|
+
|
|
552
|
+
def _deserialize_key(self, data):
|
|
553
|
+
assert type(data) == bytes and len(data) == (16 + 20 + 1 + 16)
|
|
554
|
+
|
|
555
|
+
data1, data2, data3, data4 = data[0:16], data[16:36], data[36:37], data[37:53]
|
|
556
|
+
return (
|
|
557
|
+
uuid.UUID(bytes=data1),
|
|
558
|
+
data2,
|
|
559
|
+
struct.unpack("B", data3),
|
|
560
|
+
uuid.UUID(bytes=data4),
|
|
561
|
+
)
|
|
562
|
+
|
|
563
|
+
|
|
564
|
+
class _UuidBytes20Bytes20Uint8UuidKeysMixin(object):
|
|
565
|
+
@staticmethod
|
|
566
|
+
def new_key():
|
|
567
|
+
return (
|
|
568
|
+
uuid.uuid4(),
|
|
569
|
+
os.urandom(20),
|
|
570
|
+
os.urandom(20),
|
|
571
|
+
random.randint(0, 255),
|
|
572
|
+
uuid.uuid4(),
|
|
573
|
+
)
|
|
574
|
+
|
|
575
|
+
def _serialize_key(self, key1_key2_key3_key4_key5):
|
|
576
|
+
assert (
|
|
577
|
+
type(key1_key2_key3_key4_key5) == tuple
|
|
578
|
+
and len(key1_key2_key3_key4_key5) == 5
|
|
579
|
+
)
|
|
580
|
+
key1, key2, key3, key4, key5 = key1_key2_key3_key4_key5
|
|
581
|
+
|
|
582
|
+
if key1 is None:
|
|
583
|
+
key1 = uuid.UUID(bytes=b"\x00" * 16)
|
|
584
|
+
if key2 is None:
|
|
585
|
+
key2 = b"\x00" * 20
|
|
586
|
+
if key3 is None:
|
|
587
|
+
key3 = b"\x00" * 20
|
|
588
|
+
if key4 is None:
|
|
589
|
+
key4 = 0
|
|
590
|
+
if key5 is None:
|
|
591
|
+
key5 = uuid.UUID(bytes=b"\x00" * 16)
|
|
592
|
+
|
|
593
|
+
assert isinstance(key1, uuid.UUID)
|
|
594
|
+
assert type(key2) == bytes and len(key2) == 20
|
|
595
|
+
assert type(key3) == bytes and len(key2) == 20
|
|
596
|
+
assert type(key4) == int and key4 >= 0 and key4 < 256
|
|
597
|
+
assert isinstance(key5, uuid.UUID)
|
|
598
|
+
|
|
599
|
+
return key1.bytes + key2 + key3 + struct.pack("B", key4) + key5.bytes
|
|
600
|
+
|
|
601
|
+
def _deserialize_key(self, data):
|
|
602
|
+
assert type(data) == bytes and len(data) == (16 + 20 + 20 + 1 + 16)
|
|
603
|
+
|
|
604
|
+
data1, data2, data3, data4, data5 = (
|
|
605
|
+
data[0:16],
|
|
606
|
+
data[16:36],
|
|
607
|
+
data[36:56],
|
|
608
|
+
data[56:57],
|
|
609
|
+
data[57:73],
|
|
610
|
+
)
|
|
611
|
+
return (
|
|
612
|
+
uuid.UUID(bytes=data1),
|
|
613
|
+
data2,
|
|
614
|
+
data3,
|
|
615
|
+
struct.unpack("B", data4),
|
|
616
|
+
uuid.UUID(bytes=data5),
|
|
617
|
+
)
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
class _TimestampKeysMixin(object):
|
|
621
|
+
@staticmethod
|
|
622
|
+
def new_key():
|
|
623
|
+
return np.datetime64(time_ns(), "ns")
|
|
624
|
+
|
|
625
|
+
def _serialize_key(self, key1):
|
|
626
|
+
assert isinstance(key1, np.datetime64)
|
|
627
|
+
|
|
628
|
+
return dt_to_bytes(key1)
|
|
629
|
+
|
|
630
|
+
def _deserialize_key(self, data):
|
|
631
|
+
assert type(data) == bytes
|
|
632
|
+
assert len(data) == 8
|
|
633
|
+
|
|
634
|
+
return bytes_to_dt(data[0:8])
|
|
635
|
+
|
|
636
|
+
|
|
637
|
+
class _TimestampUuidKeysMixin(object):
|
|
638
|
+
@staticmethod
|
|
639
|
+
def new_key():
|
|
640
|
+
return np.datetime64(time_ns(), "ns"), uuid.uuid4()
|
|
641
|
+
|
|
642
|
+
def _serialize_key(self, key1_key2):
|
|
643
|
+
assert type(key1_key2) == tuple and len(key1_key2) == 2
|
|
644
|
+
key1, key2 = key1_key2
|
|
645
|
+
|
|
646
|
+
if key1 is None:
|
|
647
|
+
key1 = np.datetime64(0, "ns")
|
|
648
|
+
if key2 is None:
|
|
649
|
+
key2 = uuid.UUID(bytes=b"\x00" * 16)
|
|
650
|
+
|
|
651
|
+
assert isinstance(key1, np.datetime64)
|
|
652
|
+
assert isinstance(key2, uuid.UUID)
|
|
653
|
+
|
|
654
|
+
return dt_to_bytes(key1) + key2.bytes
|
|
655
|
+
|
|
656
|
+
def _deserialize_key(self, data):
|
|
657
|
+
assert type(data) == bytes
|
|
658
|
+
assert len(data) == 24
|
|
659
|
+
|
|
660
|
+
data1, data2 = data[0:8], data[8:24]
|
|
661
|
+
|
|
662
|
+
key1 = bytes_to_dt(data1)
|
|
663
|
+
key2 = uuid.UUID(bytes=data2)
|
|
664
|
+
return key1, key2
|
|
665
|
+
|
|
666
|
+
|
|
667
|
+
class _UuidTimestampUuidKeysMixin(object):
|
|
668
|
+
@staticmethod
|
|
669
|
+
def new_key():
|
|
670
|
+
return uuid.uuid4(), np.datetime64(time_ns(), "ns"), uuid.uuid4()
|
|
671
|
+
|
|
672
|
+
def _serialize_key(self, key1_key2_key3):
|
|
673
|
+
assert type(key1_key2_key3) == tuple and len(key1_key2_key3) == 3
|
|
674
|
+
key1, key2, key3 = key1_key2_key3
|
|
675
|
+
|
|
676
|
+
if key1 is None:
|
|
677
|
+
key1 = uuid.UUID(bytes=b"\x00" * 16)
|
|
678
|
+
if key2 is None:
|
|
679
|
+
key2 = np.datetime64(0, "ns")
|
|
680
|
+
if key3 is None:
|
|
681
|
+
key3 = uuid.UUID(bytes=b"\x00" * 16)
|
|
682
|
+
|
|
683
|
+
assert isinstance(key1, uuid.UUID)
|
|
684
|
+
assert isinstance(key2, np.datetime64)
|
|
685
|
+
assert isinstance(key3, uuid.UUID)
|
|
686
|
+
|
|
687
|
+
return key1.bytes + dt_to_bytes(key2) + key3.bytes
|
|
688
|
+
|
|
689
|
+
def _deserialize_key(self, data):
|
|
690
|
+
assert type(data) == bytes
|
|
691
|
+
assert len(data) == 32
|
|
692
|
+
|
|
693
|
+
data1, data2, data3 = data[0:16], data[16:24], data[24:32]
|
|
694
|
+
|
|
695
|
+
key1 = uuid.UUID(bytes=data1)
|
|
696
|
+
key2 = bytes_to_dt(data2)
|
|
697
|
+
key3 = uuid.UUID(bytes=data3)
|
|
698
|
+
return key1, key2, key3
|
|
699
|
+
|
|
700
|
+
|
|
701
|
+
class _TimestampUuidStringKeysMixin(object):
|
|
702
|
+
@staticmethod
|
|
703
|
+
def new_key():
|
|
704
|
+
return np.datetime64(time_ns(), "ns"), uuid.uuid4(), ""
|
|
705
|
+
|
|
706
|
+
def _serialize_key(self, key1_key2_key3):
|
|
707
|
+
assert type(key1_key2_key3) == tuple and len(key1_key2_key3) == 3
|
|
708
|
+
key1, key2, key3 = key1_key2_key3
|
|
709
|
+
|
|
710
|
+
if key1 is None:
|
|
711
|
+
key1 = np.datetime64(0, "ns")
|
|
712
|
+
if key2 is None:
|
|
713
|
+
key2 = uuid.UUID(bytes=b"\x00" * 16)
|
|
714
|
+
if key3 is None:
|
|
715
|
+
key3 = ""
|
|
716
|
+
|
|
717
|
+
assert isinstance(key1, np.datetime64)
|
|
718
|
+
assert isinstance(key2, uuid.UUID)
|
|
719
|
+
assert type(key3) == str
|
|
720
|
+
|
|
721
|
+
return dt_to_bytes(key1) + key2.bytes + key3.encode("utf8")
|
|
722
|
+
|
|
723
|
+
def _deserialize_key(self, data):
|
|
724
|
+
assert type(data) == bytes
|
|
725
|
+
assert len(data) >= 24
|
|
726
|
+
|
|
727
|
+
data1, data2, data3 = data[0:8], data[8:24], data[24:]
|
|
728
|
+
|
|
729
|
+
key1 = bytes_to_dt(data1)
|
|
730
|
+
key2 = uuid.UUID(bytes=data2)
|
|
731
|
+
key3 = data3.decode("utf8") if data3 else ""
|
|
732
|
+
return key1, key2, key3
|
|
733
|
+
|
|
734
|
+
|
|
735
|
+
class _TimestampBytes32KeysMixin(object):
|
|
736
|
+
@staticmethod
|
|
737
|
+
def new_key():
|
|
738
|
+
return np.datetime64(time_ns(), "ns"), os.urandom(32)
|
|
739
|
+
|
|
740
|
+
def _serialize_key(self, key1_key2):
|
|
741
|
+
assert type(key1_key2) == tuple and len(key1_key2) == 2
|
|
742
|
+
key1, key2 = key1_key2
|
|
743
|
+
|
|
744
|
+
if key1 is None:
|
|
745
|
+
key1 = np.datetime64(0, "ns")
|
|
746
|
+
if key2 is None:
|
|
747
|
+
key2 = b"\x00" * 32
|
|
748
|
+
|
|
749
|
+
assert isinstance(key1, np.datetime64)
|
|
750
|
+
assert isinstance(key2, bytes)
|
|
751
|
+
assert isinstance(key2, bytes) and len(key2) == 32
|
|
752
|
+
|
|
753
|
+
return dt_to_bytes(key1) + key2
|
|
754
|
+
|
|
755
|
+
def _deserialize_key(self, data):
|
|
756
|
+
assert type(data) == bytes, "data must be binary, but got {}".format(type(data))
|
|
757
|
+
assert len(data) == 40, "data must have len 40, but got {}".format(len(data))
|
|
758
|
+
|
|
759
|
+
data1, data2 = data[0:8], data[8:40]
|
|
760
|
+
|
|
761
|
+
key1 = bytes_to_dt(data1)
|
|
762
|
+
key2 = data2
|
|
763
|
+
return key1, key2
|
|
764
|
+
|
|
765
|
+
|
|
766
|
+
class _TimestampStringKeysMixin(object):
|
|
767
|
+
@staticmethod
|
|
768
|
+
def new_key():
|
|
769
|
+
return np.datetime64(time_ns(), "ns"), _StringKeysMixin.new_key()
|
|
770
|
+
|
|
771
|
+
def _serialize_key(self, key1_key2):
|
|
772
|
+
assert type(key1_key2) == tuple and len(key1_key2) == 2
|
|
773
|
+
key1, key2 = key1_key2
|
|
774
|
+
|
|
775
|
+
if key1 is None:
|
|
776
|
+
key1 = np.datetime64(0, "ns")
|
|
777
|
+
if key2 is None:
|
|
778
|
+
key2 = ""
|
|
779
|
+
|
|
780
|
+
assert isinstance(key1, np.datetime64)
|
|
781
|
+
assert type(key2) == str
|
|
782
|
+
|
|
783
|
+
return dt_to_bytes(key1) + key2.encode("utf8")
|
|
784
|
+
|
|
785
|
+
def _deserialize_key(self, data):
|
|
786
|
+
assert type(data) == bytes
|
|
787
|
+
assert len(data) > 8
|
|
788
|
+
|
|
789
|
+
data1, data2 = data[0:8], data[8:]
|
|
790
|
+
key1 = bytes_to_dt(data1)
|
|
791
|
+
key2 = data2.decode("utf8")
|
|
792
|
+
return key1, key2
|
|
793
|
+
|
|
794
|
+
|
|
795
|
+
class _StringTimestampKeysMixin(object):
|
|
796
|
+
@staticmethod
|
|
797
|
+
def new_key():
|
|
798
|
+
return _StringKeysMixin.new_key(), np.datetime64(time_ns(), "ns")
|
|
799
|
+
|
|
800
|
+
def _serialize_key(self, key1_key2):
|
|
801
|
+
assert type(key1_key2) == tuple and len(key1_key2) == 2
|
|
802
|
+
key1, key2 = key1_key2
|
|
803
|
+
|
|
804
|
+
if key1 is None:
|
|
805
|
+
key1 = ""
|
|
806
|
+
if key2 is None:
|
|
807
|
+
key2 = np.datetime64(0, "ns")
|
|
808
|
+
|
|
809
|
+
assert type(key1) == str
|
|
810
|
+
assert isinstance(key2, np.datetime64)
|
|
811
|
+
|
|
812
|
+
return key1.encode("utf8") + dt_to_bytes(key2)
|
|
813
|
+
|
|
814
|
+
def _deserialize_key(self, data):
|
|
815
|
+
assert type(data) == bytes
|
|
816
|
+
assert len(data) > 8
|
|
817
|
+
|
|
818
|
+
slen = len(data) - 8
|
|
819
|
+
data1, data2 = data[0:slen], data[slen:]
|
|
820
|
+
key1 = data1.decode("utf8")
|
|
821
|
+
key2 = bytes_to_dt(data2)
|
|
822
|
+
return key1, key2
|
|
823
|
+
|
|
824
|
+
|
|
825
|
+
class _UuidTimestampKeysMixin(object):
|
|
826
|
+
@staticmethod
|
|
827
|
+
def new_key():
|
|
828
|
+
return uuid.uuid4(), np.datetime64(time_ns(), "ns")
|
|
829
|
+
|
|
830
|
+
def _serialize_key(self, key1_key2):
|
|
831
|
+
assert type(key1_key2) == tuple and len(key1_key2) == 2
|
|
832
|
+
key1, key2 = key1_key2
|
|
833
|
+
|
|
834
|
+
if key1 is None:
|
|
835
|
+
key1 = uuid.UUID(bytes=b"\x00" * 16)
|
|
836
|
+
if key2 is None:
|
|
837
|
+
key2 = np.datetime64(0, "ns")
|
|
838
|
+
|
|
839
|
+
assert isinstance(key1, uuid.UUID)
|
|
840
|
+
assert isinstance(key2, np.datetime64)
|
|
841
|
+
|
|
842
|
+
return key1.bytes + dt_to_bytes(key2)
|
|
843
|
+
|
|
844
|
+
def _deserialize_key(self, data):
|
|
845
|
+
assert type(data) == bytes
|
|
846
|
+
assert len(data) == 24
|
|
847
|
+
|
|
848
|
+
data1, data2 = data[0:16], data[16:24]
|
|
849
|
+
key1 = uuid.UUID(bytes=data1)
|
|
850
|
+
key2 = bytes_to_dt(data2)
|
|
851
|
+
return key1, key2
|
|
852
|
+
|
|
853
|
+
|
|
854
|
+
class _Uint64TimestampKeysMixin(object):
|
|
855
|
+
@staticmethod
|
|
856
|
+
def new_key():
|
|
857
|
+
return random.randint(1, 2**64 - 1), np.datetime64(time_ns(), "ns")
|
|
858
|
+
|
|
859
|
+
def _serialize_key(self, key1_key2):
|
|
860
|
+
assert type(key1_key2) == tuple and len(key1_key2) == 2
|
|
861
|
+
key1, key2 = key1_key2
|
|
862
|
+
|
|
863
|
+
if key1 is None:
|
|
864
|
+
key1 = 0
|
|
865
|
+
if key2 is None:
|
|
866
|
+
key2 = np.datetime64(0, "ns")
|
|
867
|
+
|
|
868
|
+
assert type(key1) == int, "key1 must be int, but was {}".format(type(key1))
|
|
869
|
+
assert isinstance(key2, np.datetime64), (
|
|
870
|
+
"key2 must be np.datetime64, but was {}".format(type(key2))
|
|
871
|
+
)
|
|
872
|
+
|
|
873
|
+
return struct.pack(">Q", key1) + dt_to_bytes(key2)
|
|
874
|
+
|
|
875
|
+
def _deserialize_key(self, data):
|
|
876
|
+
assert type(data) == bytes
|
|
877
|
+
assert len(data) == 16
|
|
878
|
+
|
|
879
|
+
data1, data2 = data[0:8], data[8:16]
|
|
880
|
+
key1 = struct.unpack(">Q", data1)[0]
|
|
881
|
+
key2 = bytes_to_dt(data2)
|
|
882
|
+
return key1, key2
|
|
883
|
+
|
|
884
|
+
|
|
885
|
+
class _UuidStringKeysMixin(object):
|
|
886
|
+
def _serialize_key(self, key1_key2):
|
|
887
|
+
assert type(key1_key2) == tuple and len(key1_key2) == 2
|
|
888
|
+
key1, key2 = key1_key2
|
|
889
|
+
|
|
890
|
+
if key1 is None:
|
|
891
|
+
key1 = uuid.UUID(bytes=b"\x00" * 16)
|
|
892
|
+
if key2 is None:
|
|
893
|
+
key2 = ""
|
|
894
|
+
|
|
895
|
+
assert isinstance(key1, uuid.UUID), (
|
|
896
|
+
"key1 must be of type UUID, but was {}".format(type(key1))
|
|
897
|
+
)
|
|
898
|
+
assert type(key2) == str, "key2 must be of type string, but was {}".format(
|
|
899
|
+
type(key2)
|
|
900
|
+
)
|
|
901
|
+
|
|
902
|
+
# The UUID as a 16-byte string (containing the six integer fields in big-endian byte order).
|
|
903
|
+
# https://docs.python.org/3/library/uuid.html#uuid.UUID.bytes
|
|
904
|
+
return key1.bytes + key2.encode("utf8")
|
|
905
|
+
|
|
906
|
+
def _deserialize_key(self, data):
|
|
907
|
+
assert type(data) == bytes
|
|
908
|
+
assert len(data) >= 16
|
|
909
|
+
data1 = data[:16]
|
|
910
|
+
if len(data) > 16:
|
|
911
|
+
data2 = data[16:]
|
|
912
|
+
else:
|
|
913
|
+
data2 = b""
|
|
914
|
+
return uuid.UUID(bytes=data1), data2.decode("utf8")
|
|
915
|
+
|
|
916
|
+
|
|
917
|
+
class _SlotUuidKeysMixin(object):
|
|
918
|
+
def _serialize_key(self, key1_key2):
|
|
919
|
+
assert type(key1_key2) == tuple and len(key1_key2) == 2
|
|
920
|
+
key1, key2 = key1_key2
|
|
921
|
+
|
|
922
|
+
assert type(key1) == int
|
|
923
|
+
assert key1 >= 0 and key1 < 2**16
|
|
924
|
+
assert isinstance(key2, uuid.UUID)
|
|
925
|
+
|
|
926
|
+
return struct.pack(">H", key1) + key2.bytes
|
|
927
|
+
|
|
928
|
+
def _deserialize_key(self, data):
|
|
929
|
+
assert type(data) == bytes
|
|
930
|
+
assert len(data) == (2 + 16)
|
|
931
|
+
data1, data2 = data[:2], data[2:]
|
|
932
|
+
|
|
933
|
+
return struct.unpack(">H", data1)[0], uuid.UUID(bytes=data2)
|
|
934
|
+
|
|
935
|
+
|
|
936
|
+
class _Bytes32KeysMixin(object):
|
|
937
|
+
@staticmethod
|
|
938
|
+
def new_key():
|
|
939
|
+
return os.urandom(32)
|
|
940
|
+
|
|
941
|
+
def _serialize_key(self, key):
|
|
942
|
+
assert type(key) == bytes, 'key must be bytes[32], was "{}"'.format(key)
|
|
943
|
+
assert len(key) == 32
|
|
944
|
+
|
|
945
|
+
return key
|
|
946
|
+
|
|
947
|
+
def _deserialize_key(self, data):
|
|
948
|
+
assert type(data) == bytes, 'data must be bytes[32], was "{}"'.format(data)
|
|
949
|
+
assert len(data) == 32
|
|
950
|
+
|
|
951
|
+
return data
|
|
952
|
+
|
|
953
|
+
|
|
954
|
+
class _Bytes32Bytes32KeysMixin(object):
|
|
955
|
+
def _serialize_key(self, key1_key2):
|
|
956
|
+
assert type(key1_key2) == tuple and len(key1_key2) == 2
|
|
957
|
+
key1, key2 = key1_key2
|
|
958
|
+
|
|
959
|
+
assert type(key1) == bytes
|
|
960
|
+
assert len(key1) == 32
|
|
961
|
+
|
|
962
|
+
assert type(key2) == bytes
|
|
963
|
+
assert len(key2) == 32
|
|
964
|
+
|
|
965
|
+
return key1 + key2
|
|
966
|
+
|
|
967
|
+
def _deserialize_key(self, data):
|
|
968
|
+
assert type(data) == bytes
|
|
969
|
+
assert len(data) == 64
|
|
970
|
+
|
|
971
|
+
data1, data2 = data[0:32], data[32:64]
|
|
972
|
+
return data1, data2
|
|
973
|
+
|
|
974
|
+
|
|
975
|
+
class _Bytes32UuidKeysMixin(object):
|
|
976
|
+
def _serialize_key(self, key1_key2):
|
|
977
|
+
assert type(key1_key2) == tuple and len(key1_key2) == 2
|
|
978
|
+
key1, key2 = key1_key2
|
|
979
|
+
|
|
980
|
+
assert type(key1) == bytes
|
|
981
|
+
assert len(key1) == 32
|
|
982
|
+
|
|
983
|
+
assert isinstance(key2, uuid.UUID)
|
|
984
|
+
|
|
985
|
+
return key1 + key2.bytes
|
|
986
|
+
|
|
987
|
+
def _deserialize_key(self, data):
|
|
988
|
+
assert type(data) == bytes
|
|
989
|
+
assert len(data) == 48
|
|
990
|
+
|
|
991
|
+
data1, data2 = data[0:32], data[32:48]
|
|
992
|
+
return data1, uuid.UUID(bytes=data2)
|
|
993
|
+
|
|
994
|
+
|
|
995
|
+
class _UuidBytes32KeysMixin(object):
|
|
996
|
+
def _serialize_key(self, key1_key2):
|
|
997
|
+
assert type(key1_key2) == tuple and len(key1_key2) == 2
|
|
998
|
+
key1, key2 = key1_key2
|
|
999
|
+
|
|
1000
|
+
assert isinstance(key1, uuid.UUID)
|
|
1001
|
+
|
|
1002
|
+
assert type(key2) == bytes
|
|
1003
|
+
assert len(key2) == 32
|
|
1004
|
+
|
|
1005
|
+
return key2.bytes + key1
|
|
1006
|
+
|
|
1007
|
+
def _deserialize_key(self, data):
|
|
1008
|
+
assert type(data) == bytes
|
|
1009
|
+
assert len(data) == 48
|
|
1010
|
+
|
|
1011
|
+
data1, data2 = data[0:16], data[16:48]
|
|
1012
|
+
return uuid.UUID(bytes=data1), data2
|
|
1013
|
+
|
|
1014
|
+
|
|
1015
|
+
class _Bytes32StringKeysMixin(object):
|
|
1016
|
+
def _serialize_key(self, key1_key2):
|
|
1017
|
+
assert type(key1_key2) == tuple and len(key1_key2) == 2
|
|
1018
|
+
key1, key2 = key1_key2
|
|
1019
|
+
|
|
1020
|
+
assert type(key1) == bytes
|
|
1021
|
+
assert len(key1) == 32
|
|
1022
|
+
|
|
1023
|
+
assert type(key2) == str
|
|
1024
|
+
assert len(key2) > 0
|
|
1025
|
+
|
|
1026
|
+
return key1 + key2.encode("utf8")
|
|
1027
|
+
|
|
1028
|
+
def _deserialize_key(self, data):
|
|
1029
|
+
assert type(data) == bytes
|
|
1030
|
+
assert len(data) > 32
|
|
1031
|
+
|
|
1032
|
+
data1, data2 = data[:32], data[32:]
|
|
1033
|
+
return data1, data2.decode("utf8")
|
|
1034
|
+
|
|
1035
|
+
|
|
1036
|
+
class _UuidUuidStringKeysMixin(object):
|
|
1037
|
+
def _serialize_key(self, key1_key2_key3):
|
|
1038
|
+
assert type(key1_key2_key3) == tuple and len(key1_key2_key3) == 3
|
|
1039
|
+
key1, key2, key3 = key1_key2_key3
|
|
1040
|
+
|
|
1041
|
+
assert isinstance(key1, uuid.UUID)
|
|
1042
|
+
assert isinstance(key2, uuid.UUID)
|
|
1043
|
+
assert type(key3) == str
|
|
1044
|
+
|
|
1045
|
+
return key1.bytes + key2.bytes + key3.encode("utf8")
|
|
1046
|
+
|
|
1047
|
+
def _deserialize_key(self, data):
|
|
1048
|
+
assert type(data) == bytes
|
|
1049
|
+
assert len(data) > 32
|
|
1050
|
+
|
|
1051
|
+
data1, data2, data3 = data[:16], data[16:32], data[32:]
|
|
1052
|
+
return uuid.UUID(bytes=data1), uuid.UUID(bytes=data2), data3.decode("utf8")
|
|
1053
|
+
|
|
1054
|
+
|
|
1055
|
+
class _UuidUuidUuidStringKeysMixin(object):
|
|
1056
|
+
def _serialize_key(self, key1_key2_key3_key4):
|
|
1057
|
+
assert type(key1_key2_key3_key4) == tuple and len(key1_key2_key3_key4) == 4
|
|
1058
|
+
key1, key2, key3, key4 = key1_key2_key3_key4
|
|
1059
|
+
|
|
1060
|
+
assert isinstance(key1, uuid.UUID), "key1 must be a UUID, was {}: {}".format(
|
|
1061
|
+
type(key1), key1
|
|
1062
|
+
)
|
|
1063
|
+
assert isinstance(key2, uuid.UUID), "key2 must be a UUID, was {}: {}".format(
|
|
1064
|
+
type(key2), key2
|
|
1065
|
+
)
|
|
1066
|
+
assert isinstance(key3, uuid.UUID), "key3 must be a UUID, was {}: {}".format(
|
|
1067
|
+
type(key3), key3
|
|
1068
|
+
)
|
|
1069
|
+
assert type(key4) == str, "key4 must be a str, was {}: {}".format(
|
|
1070
|
+
type(key4), key4
|
|
1071
|
+
)
|
|
1072
|
+
|
|
1073
|
+
return key1.bytes + key2.bytes + key3.bytes + key4.encode("utf8")
|
|
1074
|
+
|
|
1075
|
+
def _deserialize_key(self, data):
|
|
1076
|
+
assert type(data) == bytes
|
|
1077
|
+
assert len(data) >= 48
|
|
1078
|
+
|
|
1079
|
+
data1, data2, data3, data4 = data[:16], data[16:32], data[32:48], data[48:]
|
|
1080
|
+
return (
|
|
1081
|
+
uuid.UUID(bytes=data1),
|
|
1082
|
+
uuid.UUID(bytes=data2),
|
|
1083
|
+
uuid.UUID(bytes=data3),
|
|
1084
|
+
data4.decode("utf8"),
|
|
1085
|
+
)
|
|
1086
|
+
|
|
1087
|
+
|
|
1088
|
+
class _Bytes20KeysMixin(object):
|
|
1089
|
+
@staticmethod
|
|
1090
|
+
def new_key():
|
|
1091
|
+
return os.urandom(20)
|
|
1092
|
+
|
|
1093
|
+
def _serialize_key(self, key):
|
|
1094
|
+
assert type(key) == bytes and len(key) == 20, (
|
|
1095
|
+
'key must be bytes[20], was "{}"'.format(key)
|
|
1096
|
+
)
|
|
1097
|
+
|
|
1098
|
+
return key
|
|
1099
|
+
|
|
1100
|
+
def _deserialize_key(self, data):
|
|
1101
|
+
assert type(data) == bytes and len(data) == 20, (
|
|
1102
|
+
'data must be bytes[20], was "{}"'.format(data)
|
|
1103
|
+
)
|
|
1104
|
+
|
|
1105
|
+
return data
|
|
1106
|
+
|
|
1107
|
+
|
|
1108
|
+
class _Bytes16KeysMixin(object):
|
|
1109
|
+
@staticmethod
|
|
1110
|
+
def new_key():
|
|
1111
|
+
return os.urandom(16)
|
|
1112
|
+
|
|
1113
|
+
def _serialize_key(self, key):
|
|
1114
|
+
assert type(key) == bytes and len(key) == 16, (
|
|
1115
|
+
'key must be bytes[16], was "{}"'.format(key)
|
|
1116
|
+
)
|
|
1117
|
+
|
|
1118
|
+
return key
|
|
1119
|
+
|
|
1120
|
+
def _deserialize_key(self, data):
|
|
1121
|
+
assert type(data) == bytes and len(data) == 16, (
|
|
1122
|
+
'data must be bytes[16], was "{}"'.format(data)
|
|
1123
|
+
)
|
|
1124
|
+
|
|
1125
|
+
return data
|
|
1126
|
+
|
|
1127
|
+
|
|
1128
|
+
class _Bytes20Bytes20KeysMixin(object):
|
|
1129
|
+
@staticmethod
|
|
1130
|
+
def new_key():
|
|
1131
|
+
return os.urandom(20), os.urandom(20)
|
|
1132
|
+
|
|
1133
|
+
def _serialize_key(self, key1_key2):
|
|
1134
|
+
assert type(key1_key2) == tuple and len(key1_key2) == 2
|
|
1135
|
+
key1, key2 = key1_key2
|
|
1136
|
+
|
|
1137
|
+
assert type(key1) == bytes
|
|
1138
|
+
assert len(key1) == 20
|
|
1139
|
+
|
|
1140
|
+
assert type(key2) == bytes
|
|
1141
|
+
assert len(key2) == 20
|
|
1142
|
+
|
|
1143
|
+
return key1 + key2
|
|
1144
|
+
|
|
1145
|
+
def _deserialize_key(self, data):
|
|
1146
|
+
assert type(data) == bytes
|
|
1147
|
+
assert len(data) == 40
|
|
1148
|
+
|
|
1149
|
+
data1, data2 = data[0:20], data[20:40]
|
|
1150
|
+
return data1, data2
|
|
1151
|
+
|
|
1152
|
+
|
|
1153
|
+
class _Bytes20StringKeysMixin(object):
|
|
1154
|
+
@staticmethod
|
|
1155
|
+
def new_key():
|
|
1156
|
+
return os.urandom(20), binascii.b2a_base64(os.urandom(8)).decode().strip()
|
|
1157
|
+
|
|
1158
|
+
def _serialize_key(self, key1_key2):
|
|
1159
|
+
assert type(key1_key2) == tuple and len(key1_key2) == 2
|
|
1160
|
+
key1, key2 = key1_key2
|
|
1161
|
+
|
|
1162
|
+
assert type(key1) == bytes
|
|
1163
|
+
assert len(key1) == 20
|
|
1164
|
+
|
|
1165
|
+
assert type(key2) == str
|
|
1166
|
+
assert len(key2) > 0
|
|
1167
|
+
|
|
1168
|
+
return key1 + key2.encode("utf8")
|
|
1169
|
+
|
|
1170
|
+
def _deserialize_key(self, data):
|
|
1171
|
+
assert type(data) == bytes
|
|
1172
|
+
assert len(data) > 20
|
|
1173
|
+
data1, data2 = data[:20], data[20:]
|
|
1174
|
+
|
|
1175
|
+
return data1, data2.decode("utf8")
|
|
1176
|
+
|
|
1177
|
+
|
|
1178
|
+
class _Bytes20TimestampKeysMixin(object):
|
|
1179
|
+
@staticmethod
|
|
1180
|
+
def new_key():
|
|
1181
|
+
return os.urandom(20), np.datetime64(time_ns(), "ns")
|
|
1182
|
+
|
|
1183
|
+
def _serialize_key(self, keys):
|
|
1184
|
+
assert type(keys) == tuple, (
|
|
1185
|
+
'keys in {}._serialize_key must be a tuple, was: "{}"'.format(
|
|
1186
|
+
self.__class__.__name__, keys
|
|
1187
|
+
)
|
|
1188
|
+
)
|
|
1189
|
+
assert len(keys) == 2
|
|
1190
|
+
key1, key2 = keys
|
|
1191
|
+
|
|
1192
|
+
if not key1:
|
|
1193
|
+
key1 = b"\x00" * 20
|
|
1194
|
+
|
|
1195
|
+
assert key1 is None or (type(key1) == bytes and len(key1) == 20)
|
|
1196
|
+
assert isinstance(key2, np.datetime64)
|
|
1197
|
+
|
|
1198
|
+
return key1 + dt_to_bytes(key2)
|
|
1199
|
+
|
|
1200
|
+
def _deserialize_key(self, data):
|
|
1201
|
+
assert data is None or (type(data) == bytes and len(data) == 28)
|
|
1202
|
+
|
|
1203
|
+
if data:
|
|
1204
|
+
key1 = data[:20]
|
|
1205
|
+
key2 = bytes_to_dt(data[20:])
|
|
1206
|
+
else:
|
|
1207
|
+
key1 = b"\x00" * 20
|
|
1208
|
+
key2 = np.datetime64(0, "ns")
|
|
1209
|
+
|
|
1210
|
+
return key1, key2
|
|
1211
|
+
|
|
1212
|
+
|
|
1213
|
+
class _Bytes16TimestampKeysMixin(object):
|
|
1214
|
+
@staticmethod
|
|
1215
|
+
def new_key():
|
|
1216
|
+
return os.urandom(20), np.datetime64(time_ns(), "ns")
|
|
1217
|
+
|
|
1218
|
+
def _serialize_key(self, keys):
|
|
1219
|
+
assert type(keys) == tuple, (
|
|
1220
|
+
'keys in {}._serialize_key must be a tuple, was: "{}"'.format(
|
|
1221
|
+
self.__class__.__name__, keys
|
|
1222
|
+
)
|
|
1223
|
+
)
|
|
1224
|
+
assert len(keys) == 2
|
|
1225
|
+
key1, key2 = keys
|
|
1226
|
+
|
|
1227
|
+
if not key1:
|
|
1228
|
+
key1 = b"\x00" * 16
|
|
1229
|
+
|
|
1230
|
+
assert key1 is None or (type(key1) == bytes and len(key1) == 16)
|
|
1231
|
+
assert isinstance(key2, np.datetime64)
|
|
1232
|
+
|
|
1233
|
+
return key1 + dt_to_bytes(key2)
|
|
1234
|
+
|
|
1235
|
+
def _deserialize_key(self, data):
|
|
1236
|
+
assert data is None or (type(data) == bytes and len(data) == 24)
|
|
1237
|
+
|
|
1238
|
+
if data:
|
|
1239
|
+
key1 = data[:16]
|
|
1240
|
+
key2 = bytes_to_dt(data[16:])
|
|
1241
|
+
else:
|
|
1242
|
+
key1 = b"\x00" * 16
|
|
1243
|
+
key2 = np.datetime64(0, "ns")
|
|
1244
|
+
|
|
1245
|
+
return key1, key2
|
|
1246
|
+
|
|
1247
|
+
|
|
1248
|
+
class _Bytes16TimestampUuidKeysMixin(object):
|
|
1249
|
+
@staticmethod
|
|
1250
|
+
def new_key():
|
|
1251
|
+
return os.urandom(20), np.datetime64(time_ns(), "ns"), uuid.uuid4()
|
|
1252
|
+
|
|
1253
|
+
def _serialize_key(self, keys):
|
|
1254
|
+
assert type(keys) == tuple, (
|
|
1255
|
+
'keys in {}._serialize_key must be a tuple, was: "{}"'.format(
|
|
1256
|
+
self.__class__.__name__, keys
|
|
1257
|
+
)
|
|
1258
|
+
)
|
|
1259
|
+
assert len(keys) == 3
|
|
1260
|
+
key1, key2, key3 = keys
|
|
1261
|
+
|
|
1262
|
+
if not key1:
|
|
1263
|
+
key1 = b"\x00" * 16
|
|
1264
|
+
|
|
1265
|
+
assert key1 is None or (type(key1) == bytes and len(key1) == 16)
|
|
1266
|
+
assert isinstance(key2, np.datetime64)
|
|
1267
|
+
assert isinstance(key3, uuid.UUID)
|
|
1268
|
+
|
|
1269
|
+
return key1 + dt_to_bytes(key2) + key3.bytes
|
|
1270
|
+
|
|
1271
|
+
def _deserialize_key(self, data):
|
|
1272
|
+
assert data is None or (type(data) == bytes and len(data) == 40)
|
|
1273
|
+
|
|
1274
|
+
if data:
|
|
1275
|
+
key1 = data[:16]
|
|
1276
|
+
key2 = bytes_to_dt(data[16:24])
|
|
1277
|
+
key3 = uuid.UUID(bytes=data[24:])
|
|
1278
|
+
else:
|
|
1279
|
+
key1 = b"\x00" * 16
|
|
1280
|
+
key2 = np.datetime64(0, "ns")
|
|
1281
|
+
key3 = uuid.UUID(bytes=b"\x00" * 16)
|
|
1282
|
+
|
|
1283
|
+
return key1, key2, key3
|
|
1284
|
+
|
|
1285
|
+
|
|
1286
|
+
#
|
|
1287
|
+
# Value Types
|
|
1288
|
+
#
|
|
1289
|
+
|
|
1290
|
+
|
|
1291
|
+
class _StringValuesMixin(object):
|
|
1292
|
+
def _serialize_value(self, value):
|
|
1293
|
+
assert value is None or type(value) == str
|
|
1294
|
+
|
|
1295
|
+
if value is not None:
|
|
1296
|
+
return value.encode("utf8")
|
|
1297
|
+
else:
|
|
1298
|
+
return b""
|
|
1299
|
+
|
|
1300
|
+
def _deserialize_value(self, data):
|
|
1301
|
+
if data:
|
|
1302
|
+
return data.decode("utf8")
|
|
1303
|
+
else:
|
|
1304
|
+
return None
|
|
1305
|
+
|
|
1306
|
+
|
|
1307
|
+
class _StringSetValuesMixin(object):
|
|
1308
|
+
def _serialize_value(self, value_set):
|
|
1309
|
+
assert type(value_set) == set
|
|
1310
|
+
for v in value_set:
|
|
1311
|
+
assert v is None or type(v) == str
|
|
1312
|
+
|
|
1313
|
+
return b"\0".join(
|
|
1314
|
+
[(value.encode("utf8") if value else b"") for value in value_set]
|
|
1315
|
+
)
|
|
1316
|
+
|
|
1317
|
+
def _deserialize_value(self, data):
|
|
1318
|
+
assert type(data) == bytes
|
|
1319
|
+
return set([(d.decode("utf8") if d else None) for d in data.split("\0")])
|
|
1320
|
+
|
|
1321
|
+
|
|
1322
|
+
class _OidValuesMixin(object):
|
|
1323
|
+
def _serialize_value(self, value):
|
|
1324
|
+
assert type(value) == int
|
|
1325
|
+
assert value >= 0 and value <= _OidKeysMixin.MAX_OID
|
|
1326
|
+
|
|
1327
|
+
return struct.pack(">Q", value)
|
|
1328
|
+
|
|
1329
|
+
def _deserialize_value(self, data):
|
|
1330
|
+
return struct.unpack(">Q", data)[0]
|
|
1331
|
+
|
|
1332
|
+
|
|
1333
|
+
class _OidSetValuesMixin(object):
|
|
1334
|
+
def _serialize_value(self, value_set):
|
|
1335
|
+
assert type(value_set) == set
|
|
1336
|
+
for value in value_set:
|
|
1337
|
+
assert value >= 0 and value <= _OidKeysMixin.MAX_OID
|
|
1338
|
+
return b"".join([struct.pack(">Q", value) for value in value_set])
|
|
1339
|
+
|
|
1340
|
+
def _deserialize_value(self, data):
|
|
1341
|
+
VLEN = 8
|
|
1342
|
+
assert len(data) % VLEN == 0
|
|
1343
|
+
cnt = len(data) // VLEN
|
|
1344
|
+
return set(
|
|
1345
|
+
[struct.unpack(">Q", data[i : i + VLEN])[0] for i in range(0, cnt, VLEN)]
|
|
1346
|
+
)
|
|
1347
|
+
|
|
1348
|
+
|
|
1349
|
+
class _UuidValuesMixin(object):
|
|
1350
|
+
def _serialize_value(self, value):
|
|
1351
|
+
assert value is None or isinstance(value, uuid.UUID), (
|
|
1352
|
+
'not a UUID - value "{}"'.format(value)
|
|
1353
|
+
)
|
|
1354
|
+
|
|
1355
|
+
# The UUID as a 16-byte string (containing the six integer fields in big-endian byte order).
|
|
1356
|
+
# https://docs.python.org/3/library/uuid.html#uuid.UUID.bytes
|
|
1357
|
+
if value:
|
|
1358
|
+
return value.bytes
|
|
1359
|
+
else:
|
|
1360
|
+
return b"\x00" * 16
|
|
1361
|
+
|
|
1362
|
+
def _deserialize_value(self, data):
|
|
1363
|
+
assert data is None or type(data) == bytes
|
|
1364
|
+
|
|
1365
|
+
if data:
|
|
1366
|
+
return uuid.UUID(bytes=data)
|
|
1367
|
+
else:
|
|
1368
|
+
return uuid.UUID(bytes=b"\x00" * 16)
|
|
1369
|
+
|
|
1370
|
+
|
|
1371
|
+
class _TimestampValuesMixin(object):
|
|
1372
|
+
def _serialize_value(self, value):
|
|
1373
|
+
assert value is None or isinstance(value, np.datetime64)
|
|
1374
|
+
|
|
1375
|
+
if value:
|
|
1376
|
+
return dt_to_bytes(value)
|
|
1377
|
+
else:
|
|
1378
|
+
return b"\x00" * 8
|
|
1379
|
+
|
|
1380
|
+
def _deserialize_value(self, data):
|
|
1381
|
+
assert data is None or type(data) == bytes and len(data) == 8
|
|
1382
|
+
|
|
1383
|
+
if data:
|
|
1384
|
+
return bytes_to_dt(data)
|
|
1385
|
+
else:
|
|
1386
|
+
return None
|
|
1387
|
+
|
|
1388
|
+
|
|
1389
|
+
class _Bytes32ValuesMixin(object):
|
|
1390
|
+
def _serialize_value(self, value):
|
|
1391
|
+
assert value is None or (type(value) == bytes and len(value) == 32)
|
|
1392
|
+
if value:
|
|
1393
|
+
return value
|
|
1394
|
+
else:
|
|
1395
|
+
return b"\x00" * 32
|
|
1396
|
+
|
|
1397
|
+
def _deserialize_value(self, data):
|
|
1398
|
+
assert data is None or (type(data) == bytes and len(data) == 32)
|
|
1399
|
+
if data:
|
|
1400
|
+
return data
|
|
1401
|
+
else:
|
|
1402
|
+
return None
|
|
1403
|
+
|
|
1404
|
+
|
|
1405
|
+
class _Bytes20ValuesMixin(object):
|
|
1406
|
+
def _serialize_value(self, value):
|
|
1407
|
+
assert value is None or (type(value) == bytes and len(value) == 20)
|
|
1408
|
+
if value:
|
|
1409
|
+
return value
|
|
1410
|
+
else:
|
|
1411
|
+
return b"\x00" * 20
|
|
1412
|
+
|
|
1413
|
+
def _deserialize_value(self, data):
|
|
1414
|
+
assert data is None or (type(data) == bytes and len(data) == 20)
|
|
1415
|
+
if data:
|
|
1416
|
+
return data
|
|
1417
|
+
else:
|
|
1418
|
+
return None
|
|
1419
|
+
|
|
1420
|
+
|
|
1421
|
+
class _Bytes20TimestampValuesMixin(object):
|
|
1422
|
+
def _serialize_value(self, values):
|
|
1423
|
+
assert type(values) == tuple
|
|
1424
|
+
assert len(values) == 2
|
|
1425
|
+
value1, value2 = values
|
|
1426
|
+
|
|
1427
|
+
if not value1:
|
|
1428
|
+
value1 = b"\x00" * 20
|
|
1429
|
+
|
|
1430
|
+
assert value1 is None or (type(value1) == bytes and len(value1) == 20)
|
|
1431
|
+
assert isinstance(value2, np.datetime64)
|
|
1432
|
+
|
|
1433
|
+
return value1 + dt_to_bytes(value2)
|
|
1434
|
+
|
|
1435
|
+
def _deserialize_value(self, data):
|
|
1436
|
+
assert data is None or (type(data) == bytes and len(data) == 28)
|
|
1437
|
+
|
|
1438
|
+
if data:
|
|
1439
|
+
value1 = data[:20]
|
|
1440
|
+
value2 = bytes_to_dt(data[20:])
|
|
1441
|
+
else:
|
|
1442
|
+
value1 = b"\x00" * 20
|
|
1443
|
+
value2 = np.datetime64(0, "ns")
|
|
1444
|
+
|
|
1445
|
+
return value1, value2
|
|
1446
|
+
|
|
1447
|
+
|
|
1448
|
+
class _Bytes16ValuesMixin(object):
|
|
1449
|
+
def _serialize_value(self, value):
|
|
1450
|
+
assert value is None or (type(value) == bytes and len(value) == 16)
|
|
1451
|
+
if value:
|
|
1452
|
+
return value
|
|
1453
|
+
else:
|
|
1454
|
+
return b"\x00" * 16
|
|
1455
|
+
|
|
1456
|
+
def _deserialize_value(self, data):
|
|
1457
|
+
assert data is None or (type(data) == bytes and len(data) == 16)
|
|
1458
|
+
if data:
|
|
1459
|
+
return data
|
|
1460
|
+
else:
|
|
1461
|
+
return None
|
|
1462
|
+
|
|
1463
|
+
|
|
1464
|
+
class _UuidSetValuesMixin(object):
|
|
1465
|
+
def _serialize_value(self, value_set):
|
|
1466
|
+
assert type(value_set) == set
|
|
1467
|
+
return b"".join([value.bytes for value in value_set])
|
|
1468
|
+
|
|
1469
|
+
def _deserialize_value(self, data):
|
|
1470
|
+
VLEN = 16
|
|
1471
|
+
assert len(data) % VLEN == 0
|
|
1472
|
+
cnt = len(data) // VLEN
|
|
1473
|
+
return set([uuid.UUID(bytes=data[i : i + VLEN]) for i in range(0, cnt, VLEN)])
|
|
1474
|
+
|
|
1475
|
+
|
|
1476
|
+
class _JsonValuesMixin(object):
|
|
1477
|
+
def __init__(self, marshal=None, unmarshal=None):
|
|
1478
|
+
self._marshal = None
|
|
1479
|
+
if marshal:
|
|
1480
|
+
self._marshal = marshal
|
|
1481
|
+
else:
|
|
1482
|
+
if hasattr(self, "_zlmdb_marshal"):
|
|
1483
|
+
self._marshal = self._zlmdb_marshal
|
|
1484
|
+
assert self._marshal
|
|
1485
|
+
|
|
1486
|
+
self._unmarshal = None
|
|
1487
|
+
if unmarshal:
|
|
1488
|
+
self._unmarshal = unmarshal
|
|
1489
|
+
else:
|
|
1490
|
+
if hasattr(self, "_zlmdb_unmarshal"):
|
|
1491
|
+
self._unmarshal = self._zlmdb_unmarshal
|
|
1492
|
+
assert self._unmarshal
|
|
1493
|
+
|
|
1494
|
+
def _serialize_value(self, value):
|
|
1495
|
+
return json.dumps(
|
|
1496
|
+
self._marshal(value),
|
|
1497
|
+
separators=(",", ":"),
|
|
1498
|
+
ensure_ascii=False,
|
|
1499
|
+
sort_keys=False,
|
|
1500
|
+
).encode("utf8")
|
|
1501
|
+
|
|
1502
|
+
def _deserialize_value(self, data):
|
|
1503
|
+
return self._unmarshal(json.loads(data.decode("utf8")))
|
|
1504
|
+
|
|
1505
|
+
|
|
1506
|
+
class _CborValuesMixin(object):
|
|
1507
|
+
def __init__(self, marshal=None, unmarshal=None):
|
|
1508
|
+
self._marshal = None
|
|
1509
|
+
if marshal:
|
|
1510
|
+
self._marshal = marshal
|
|
1511
|
+
else:
|
|
1512
|
+
if hasattr(self, "_zlmdb_marshal"):
|
|
1513
|
+
self._marshal = self._zlmdb_marshal
|
|
1514
|
+
assert self._marshal
|
|
1515
|
+
|
|
1516
|
+
self._unmarshal = None
|
|
1517
|
+
if unmarshal:
|
|
1518
|
+
self._unmarshal = unmarshal
|
|
1519
|
+
else:
|
|
1520
|
+
if hasattr(self, "_zlmdb_unmarshal"):
|
|
1521
|
+
self._unmarshal = self._zlmdb_unmarshal
|
|
1522
|
+
assert self._unmarshal
|
|
1523
|
+
|
|
1524
|
+
def _serialize_value(self, value):
|
|
1525
|
+
return cbor2.dumps(self._marshal(value))
|
|
1526
|
+
|
|
1527
|
+
def _deserialize_value(self, data):
|
|
1528
|
+
return self._unmarshal(cbor2.loads(data))
|
|
1529
|
+
|
|
1530
|
+
|
|
1531
|
+
class _PickleValuesMixin(object):
|
|
1532
|
+
# PROTOCOL = _NATIVE_PICKLE_PROTOCOL
|
|
1533
|
+
PROTOCOL = 2
|
|
1534
|
+
|
|
1535
|
+
def _serialize_value(self, value):
|
|
1536
|
+
return pickle.dumps(value, protocol=self.PROTOCOL)
|
|
1537
|
+
|
|
1538
|
+
def _deserialize_value(self, data):
|
|
1539
|
+
return pickle.loads(data)
|
|
1540
|
+
|
|
1541
|
+
|
|
1542
|
+
class _FlatBuffersValuesMixin(object):
|
|
1543
|
+
def __init__(self, build, cast):
|
|
1544
|
+
self._build = build or self._zlmdb_build
|
|
1545
|
+
self._cast = cast or self._zlmdb_cast
|
|
1546
|
+
|
|
1547
|
+
def _serialize_value(self, value):
|
|
1548
|
+
builder = flatbuffers.Builder(0)
|
|
1549
|
+
obj = self._build(value, builder)
|
|
1550
|
+
builder.Finish(obj)
|
|
1551
|
+
buf = builder.Output()
|
|
1552
|
+
return bytes(buf)
|
|
1553
|
+
|
|
1554
|
+
def _deserialize_value(self, data):
|
|
1555
|
+
return self._cast(data)
|
|
1556
|
+
|
|
1557
|
+
|
|
1558
|
+
class _Pickle5ValuesMixin(object):
|
|
1559
|
+
"""
|
|
1560
|
+
Arbitrary Python object values, serialized using Pickle protocol version 5.
|
|
1561
|
+
Protocol version 5 was added in Python 3.8. It adds support for out-of-band
|
|
1562
|
+
data and speedup for in-band data.
|
|
1563
|
+
|
|
1564
|
+
.. seealso::
|
|
1565
|
+
|
|
1566
|
+
* https://docs.python.org/3/library/pickle.html#data-stream-format
|
|
1567
|
+
* https://www.python.org/dev/peps/pep-0574/
|
|
1568
|
+
"""
|
|
1569
|
+
|
|
1570
|
+
PROTOCOL = 5
|
|
1571
|
+
|
|
1572
|
+
def _serialize_value(self, value):
|
|
1573
|
+
obj_buffers = []
|
|
1574
|
+
obj_data = pickle.dumps(
|
|
1575
|
+
value, protocol=self.PROTOCOL, buffer_callback=obj_buffers.append
|
|
1576
|
+
)
|
|
1577
|
+
data = []
|
|
1578
|
+
data.append(struct.pack(">I", len(obj_data)))
|
|
1579
|
+
data.append(obj_data)
|
|
1580
|
+
for d in obj_buffers:
|
|
1581
|
+
data.append(struct.pack(">I", len(d.raw())))
|
|
1582
|
+
data.append(d)
|
|
1583
|
+
return b"".join(data)
|
|
1584
|
+
|
|
1585
|
+
def _deserialize_value(self, data):
|
|
1586
|
+
data = memoryview(data)
|
|
1587
|
+
obj_buffers = []
|
|
1588
|
+
obj_len = struct.unpack(">I", data[0:4])[0]
|
|
1589
|
+
obj_data = data[4 : obj_len + 4]
|
|
1590
|
+
i = obj_len + 4
|
|
1591
|
+
while i < len(data):
|
|
1592
|
+
buffer_len = struct.unpack(">I", data[i : i + 4])[0]
|
|
1593
|
+
buffer_data = data[i + 4 : i + 4 + buffer_len]
|
|
1594
|
+
obj_buffers.append(buffer_data)
|
|
1595
|
+
i += 4 + buffer_len
|
|
1596
|
+
return pickle.loads(obj_data, buffers=obj_buffers)
|