pyfusefilter 1.3.1__cp313-cp313-win_amd64.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.
@@ -0,0 +1,4 @@
1
+ from pyfusefilter.pyfusefilter import Xor8, Xor16, Fuse8, Fuse16
2
+
3
+ VERSION = "1.2.1"
4
+ __all__ = ["Xor8", "Xor16", "Fuse8", "Fuse16"]
Binary file
@@ -0,0 +1,175 @@
1
+ from cffi import FFI
2
+ import os
3
+ from sys import exit, platform
4
+
5
+
6
+ ffi = FFI()
7
+ cdef_from_file = None
8
+
9
+ all_src = ""
10
+ with open("lib/xor_singleheader/include/xorfilter.h", "r", encoding='utf-8') as src:
11
+ all_src += src.read()
12
+
13
+ with open("lib/xor_singleheader/include/binaryfusefilter.h", "r", encoding='utf-8') as src:
14
+ all_src += src.read()
15
+
16
+
17
+ ffi.set_source(
18
+ "_xorfilter", all_src,
19
+ )
20
+
21
+ ffi.cdef(
22
+ """
23
+ static inline uint64_t xor_murmur64(uint64_t h) ;
24
+
25
+ static inline uint64_t xor_mix_split(uint64_t key, uint64_t seed) ;
26
+
27
+ static inline uint64_t xor_rotl64(uint64_t n, unsigned int c) ;
28
+
29
+ static inline uint32_t xor_reduce(uint32_t hash, uint32_t n) ;
30
+
31
+ static inline uint64_t xor_fingerprint(uint64_t hash) ;
32
+
33
+ static inline uint64_t xor_rng_splitmix64(uint64_t *seed) ;
34
+
35
+
36
+ typedef struct xor8_s {
37
+ uint64_t seed;
38
+ uint64_t blockLength;
39
+ uint8_t
40
+ *fingerprints; // after xor8_allocate, will point to 3*blockLength values
41
+ } xor8_t;
42
+
43
+ struct xor_xorset_s {
44
+ uint64_t xormask;
45
+ uint32_t count;
46
+ };
47
+
48
+ typedef struct xor16_s {
49
+ uint64_t seed;
50
+ uint64_t blockLength;
51
+ uint16_t
52
+ *fingerprints; // after xor16_allocate, will point to 3*blockLength values
53
+ } xor16_t;
54
+
55
+ typedef struct binary_fuse8_s {
56
+ uint64_t Seed;
57
+ uint32_t Size;
58
+ uint32_t SegmentLength;
59
+ uint32_t SegmentLengthMask;
60
+ uint32_t SegmentCount;
61
+ uint32_t SegmentCountLength;
62
+ uint32_t ArrayLength;
63
+ uint8_t *Fingerprints;
64
+ } binary_fuse8_t;
65
+
66
+ typedef struct binary_fuse16_s {
67
+ uint64_t Seed;
68
+ uint32_t Size;
69
+ uint32_t SegmentLength;
70
+ uint32_t SegmentLengthMask;
71
+ uint32_t SegmentCount;
72
+ uint32_t SegmentCountLength;
73
+ uint32_t ArrayLength;
74
+ uint16_t *Fingerprints;
75
+ } binary_fuse16_t;
76
+
77
+ typedef struct xor_xorset_s xor_xorset_t;
78
+
79
+ struct xor_hashes_s {
80
+ uint64_t h;
81
+ uint32_t h0;
82
+ uint32_t h1;
83
+ uint32_t h2;
84
+ };
85
+ typedef struct xor_hashes_s xor_hashes_t;
86
+
87
+ struct xor_h0h1h2_s {
88
+ uint32_t h0;
89
+ uint32_t h1;
90
+ uint32_t h2;
91
+ };
92
+ typedef struct xor_h0h1h2_s xor_h0h1h2_t;
93
+
94
+ struct xor_keyindex_s {
95
+ uint64_t hash;
96
+ uint32_t index;
97
+ };
98
+
99
+ typedef struct xor_keyindex_s xor_keyindex_t;
100
+
101
+ struct xor_setbuffer_s {
102
+ xor_keyindex_t *buffer;
103
+ uint32_t *counts;
104
+ int insignificantbits;
105
+ uint32_t slotsize; // should be 1<< insignificantbits
106
+ uint32_t slotcount;
107
+ size_t originalsize;
108
+ };
109
+ typedef struct xor_setbuffer_s xor_setbuffer_t;
110
+
111
+ static inline bool xor8_contain(uint64_t key, const xor8_t *filter);
112
+ static inline bool xor16_contain(uint64_t key, const xor16_t *filter);
113
+ static inline bool binary_fuse8_contain(uint64_t key, const binary_fuse8_t *filter);
114
+ static inline bool binary_fuse16_contain(uint64_t key, const binary_fuse16_t *filter);
115
+
116
+ static inline bool xor8_allocate(uint32_t size, xor8_t *filter);
117
+ static inline bool xor16_allocate(uint32_t size, xor16_t *filter);
118
+ static inline bool binary_fuse8_allocate(uint32_t size, binary_fuse8_t *filter);
119
+ static inline bool binary_fuse16_allocate(uint32_t size, binary_fuse16_t *filter);
120
+
121
+ static inline size_t xor8_size_in_bytes(const xor8_t *filter);
122
+ static inline size_t xor16_size_in_bytes(const xor16_t *filter);
123
+ static inline size_t binary_fuse8_size_in_bytes(const binary_fuse8_t *filter);
124
+ static inline size_t binary_fuse16_size_in_bytes(const binary_fuse16_t *filter);
125
+
126
+ static inline void xor8_free(xor8_t *filter);
127
+ static inline void xor16_free(xor16_t *filter);
128
+ static inline void binary_fuse8_free(binary_fuse8_t *filter);
129
+ static inline void binary_fuse16_free(binary_fuse16_t *filter);
130
+
131
+ static inline xor_hashes_t xor8_get_h0_h1_h2(uint64_t k, const xor8_t *filter) ;
132
+ static inline uint32_t xor8_get_h0(uint64_t hash, const xor8_t *filter) ;
133
+ static inline uint32_t xor8_get_h1(uint64_t hash, const xor8_t *filter) ;
134
+ static inline uint32_t xor8_get_h2(uint64_t hash, const xor8_t *filter) ;
135
+ static inline uint32_t xor16_get_h0(uint64_t hash, const xor16_t *filter) ;
136
+ static inline uint32_t xor16_get_h1(uint64_t hash, const xor16_t *filter) ;
137
+ static inline uint32_t xor16_get_h2(uint64_t hash, const xor16_t *filter) ;
138
+ static inline xor_hashes_t xor16_get_h0_h1_h2(uint64_t k, const xor16_t *filter) ;
139
+
140
+ static inline bool xor_init_buffer(xor_setbuffer_t *buffer, size_t size) ;
141
+ static inline void xor_free_buffer(xor_setbuffer_t *buffer) ;
142
+ static inline void xor_buffered_increment_counter(uint32_t index, uint64_t hash, xor_setbuffer_t *buffer, xor_xorset_t *sets) ;
143
+ static inline void xor_make_buffer_current(xor_setbuffer_t *buffer, xor_xorset_t *sets, uint32_t index, xor_keyindex_t *Q, size_t *Qsize) ;
144
+ static inline void xor_buffered_decrement_counter(uint32_t index, uint64_t hash, xor_setbuffer_t *buffer, xor_xorset_t *sets, xor_keyindex_t *Q, size_t *Qsize) ;
145
+ static inline void xor_flush_increment_buffer(xor_setbuffer_t *buffer, xor_xorset_t *sets) ;
146
+ static inline void xor_flush_decrement_buffer(xor_setbuffer_t *buffer, xor_xorset_t *sets, xor_keyindex_t *Q, size_t *Qsize) ;
147
+ static inline uint32_t xor_flushone_decrement_buffer(xor_setbuffer_t *buffer, xor_xorset_t *sets, xor_keyindex_t *Q, size_t *Qsize) ;
148
+
149
+ bool xor8_buffered_populate(const uint64_t *keys, uint32_t size, xor8_t *filter) ;
150
+ bool xor8_populate(const uint64_t *keys, uint32_t size, xor8_t *filter) ;
151
+ bool binary_fuse8_populate(const uint64_t *keys, uint32_t size, binary_fuse8_t *filter) ;
152
+ bool xor16_buffered_populate(const uint64_t *keys, uint32_t size, xor16_t *filter) ;
153
+ bool xor16_populate(const uint64_t *keys, uint32_t size, xor16_t *filter) ;
154
+ bool binary_fuse16_populate(const uint64_t *keys, uint32_t size, binary_fuse16_t *filter) ;
155
+
156
+
157
+ size_t xor16_serialization_bytes(xor16_t *filter);
158
+ size_t xor8_serialization_bytes(const xor8_t *filter);
159
+ void xor16_serialize(const xor16_t *filter, char *buffer);
160
+ void xor8_serialize(const xor8_t *filter, char *buffer);
161
+ bool xor16_deserialize(xor16_t * filter, const char *buffer);
162
+ bool xor8_deserialize(xor8_t * filter, const char *buffer);
163
+
164
+ size_t binary_fuse16_serialization_bytes(binary_fuse16_t *filter);
165
+ size_t binary_fuse8_serialization_bytes(const binary_fuse8_t *filter);
166
+ void binary_fuse16_serialize(const binary_fuse16_t *filter, char *buffer);
167
+ void binary_fuse8_serialize(const binary_fuse8_t *filter, char *buffer);
168
+ bool binary_fuse16_deserialize(binary_fuse16_t * filter, const char *buffer);
169
+ bool binary_fuse8_deserialize(binary_fuse8_t * filter, const char *buffer);
170
+
171
+ """
172
+ )
173
+
174
+ if __name__ == "__main__":
175
+ ffi.compile(verbose=True)
@@ -0,0 +1,412 @@
1
+ from ._xorfilter import lib, ffi
2
+ from ctypes import c_ulonglong
3
+ import xxhash
4
+ import struct
5
+
6
+ def hash(item):
7
+ # xxhash 4 no longer accepts str; encoding as UTF-8 gives exactly the
8
+ # same hash values that earlier xxhash versions computed for str input.
9
+ return xxhash.xxh64_intdigest(str(item).encode("utf-8"))
10
+
11
+ class Xor8:
12
+ """
13
+ Xor8 is a probabilistic data structure that allows for fast set membership queries.
14
+ It may return false positives but never false negatives. It uses slightly more than
15
+ a byte of memory per key. Its false positive rate is roughly 0.39%.
16
+ For large sets, a Fuse8 filter is more efficient than a Xor8 filter.
17
+ """
18
+ def __init__(self, size_or_data):
19
+ """
20
+ Initialize the Xor8 filter.
21
+ If an integer is provided, allocate a filter of that size. You must then use 'populate' to add data.
22
+ If an iterable is provided, populate the filter with the data.
23
+ """
24
+ self.__filter = ffi.new("xor8_t *")
25
+ if isinstance(size_or_data, int):
26
+ status = lib.xor8_allocate(size_or_data, self.__filter)
27
+ if not status:
28
+ raise MemoryError("Unable to allocate memory for filter")
29
+ else:
30
+ data = list(size_or_data)
31
+ status = lib.xor8_allocate(len(data), self.__filter)
32
+ if not status:
33
+ raise MemoryError("Unable to allocate memory for filter")
34
+ else:
35
+ data = list(map(lambda x: c_ulonglong((hash(x))).value, data))
36
+ if not lib.xor8_buffered_populate(data, len(data), self.__filter):
37
+ raise ValueError("Unable to populate the filter")
38
+
39
+ def __repr__(self):
40
+ return "Xor8 object with size(in bytes):{}".format(self.size_in_bytes())
41
+
42
+ def __getitem__(self, item):
43
+ """
44
+ Check if the item is in the filter. With a small probability, the filter
45
+ may return true for an item not in the set (false positive). There is
46
+ no false negative: if the filter returns false, the item is definitely not in the set.
47
+ """
48
+ return self.contains(item)
49
+
50
+ def __contains__(self, item):
51
+ """
52
+ Check if the item is in the filter. With a small probability, the filter
53
+ may return true for an item not in the set (false positive). There is
54
+ no false negative: if the filter returns false, the item is definitely not in the set.
55
+ """
56
+ return self.contains(item)
57
+
58
+ def __del__(self):
59
+ lib.xor8_free(self.__filter)
60
+
61
+ def populate(self, data: list):
62
+ """
63
+ Set the data of the filter. You may use this method to add data after
64
+ allocating the filter with an integer size. The sizes should match.
65
+ You can reuse a filter with new data (i.e., call populate several times)
66
+ as long as the size remains a constant.
67
+ """
68
+ data = list(map(lambda x: c_ulonglong((hash(x))).value, data))
69
+ return lib.xor8_buffered_populate(data, len(data), self.__filter)
70
+
71
+ def contains(self, item):
72
+ """
73
+ Check if the item is in the filter. With a small probability, the filter
74
+ may return true for an item not in the set (false positive). There is
75
+ no false negative: if the filter returns false, the item is definitely not in the set.
76
+ """
77
+ item = c_ulonglong((hash(item))).value
78
+ return lib.xor8_contain(item, self.__filter)
79
+
80
+ def size_in_bytes(self):
81
+ """
82
+ Return the size of the filter in bytes, not counting Python overhead.
83
+ This value might be slightly larger than the serialized size.
84
+ """
85
+ return lib.xor8_size_in_bytes(self.__filter)
86
+
87
+ def serialize(self):
88
+ """
89
+ Serialize the filter to a bytes object.
90
+ """
91
+ buffer = ffi.new("char[]", lib.xor8_serialization_bytes(self.__filter))
92
+ lib.xor8_serialize(self.__filter, buffer)
93
+ return ffi.buffer(buffer)
94
+
95
+ @staticmethod
96
+ def deserialize(buffer):
97
+ """
98
+ Deserialize a bytes object to a Xor8 filter.
99
+ """
100
+ self = object.__new__(Xor8)
101
+ self.__filter = ffi.new("xor8_t *")
102
+ lib.xor8_deserialize(self.__filter, ffi.from_buffer(buffer))
103
+ return self
104
+
105
+
106
+ class Xor16:
107
+ """
108
+ Xor16 is a probabilistic data structure that allows for fast set membership queries.
109
+ It may return false positives but never false negatives. It uses about two bytes of memory per key.
110
+ Its false positive rate is roughly 0.0015%.
111
+ For large sets, a Fuse16 filter is more efficient than a Xor16 filter.
112
+ """
113
+ def __init__(self, size_or_data):
114
+ """
115
+ Initialize the Xor16 filter.
116
+ If an integer is provided, allocate a filter of that size. You must then use 'populate' to add data.
117
+ If an iterable is provided, populate the filter with the data.
118
+ """
119
+ self.__filter = ffi.new("xor16_t *")
120
+ if isinstance(size_or_data, int):
121
+ status = lib.xor16_allocate(size_or_data, self.__filter)
122
+ if not status:
123
+ raise MemoryError("Unable to allocate memory for filter")
124
+ else:
125
+ data = list(size_or_data)
126
+ status = lib.xor16_allocate(len(data), self.__filter)
127
+ if not status:
128
+ raise MemoryError("Unable to allocate memory for filter")
129
+ else:
130
+ data = list(map(lambda x: c_ulonglong((hash(x))).value, data))
131
+ if not lib.xor16_buffered_populate(data, len(data), self.__filter):
132
+ raise ValueError("Unable to populate the filter")
133
+
134
+ def __repr__(self):
135
+ """
136
+ Return a string representation of the Xor16 filter, including its size in bytes.
137
+ """
138
+ return "Xor16 object with size(in bytes):{}".format(self.size_in_bytes())
139
+
140
+ def __getitem__(self, item):
141
+ """
142
+ Check if the item is in the filter. With a small probability, the filter
143
+ may return true for an item not in the set (false positive). There is
144
+ no false negative: if the filter returns false, the item is definitely not in the set.
145
+ """
146
+ return self.contains(item)
147
+
148
+ def __contains__(self, item):
149
+ """
150
+ Check if the item is in the filter. With a small probability, the filter
151
+ may return true for an item not in the set (false positive). There is
152
+ no false negative: if the filter returns false, the item is definitely not in the set.
153
+ """
154
+ return self.contains(item)
155
+
156
+ def __del__(self):
157
+ """
158
+ Free the memory allocated for the Xor16 filter.
159
+ """
160
+ lib.xor16_free(self.__filter)
161
+
162
+ def populate(self, data):
163
+ """
164
+ Set the data of the filter. You may use this method to add data after
165
+ allocating the filter with an integer size. The sizes should match.
166
+ You can reuse a filter with new data (i.e., call populate several times)
167
+ as long as the size remains a constant.
168
+ """
169
+ data = list(map(lambda x: c_ulonglong((hash(x))).value, data))
170
+ return lib.xor16_buffered_populate(data, len(data), self.__filter)
171
+
172
+ def contains(self, item):
173
+ """
174
+ Check if the item is in the filter. With a small probability, the filter
175
+ may return true for an item not in the set (false positive). There is
176
+ no false negative: if the filter returns false, the item is definitely not in the set.
177
+ """
178
+ item = c_ulonglong((hash(item))).value
179
+ return lib.xor16_contain(item, self.__filter)
180
+
181
+ def size_in_bytes(self):
182
+ """
183
+ Return the size of the filter in bytes, not counting Python overhead.
184
+ This value might be slightly larger than the serialized size.
185
+ """
186
+ return lib.xor16_size_in_bytes(self.__filter)
187
+
188
+ def serialize(self):
189
+ """
190
+ Serialize the filter to a bytes object.
191
+ """
192
+ buffer = ffi.new("char[]", lib.xor16_serialization_bytes(self.__filter))
193
+ lib.xor16_serialize(self.__filter, buffer)
194
+ return ffi.buffer(buffer)
195
+
196
+ @staticmethod
197
+ def deserialize(buffer):
198
+ """
199
+ Deserialize a bytes object to a Xor16 filter.
200
+ """
201
+ self = object.__new__(Xor16)
202
+ self.__filter = ffi.new("xor16_t *")
203
+ lib.xor16_deserialize(self.__filter, ffi.from_buffer(buffer))
204
+ return self
205
+
206
+ class Fuse8:
207
+ """
208
+ Fuse8 is a probabilistic data structure for fast set membership queries.
209
+ It offers a balance between speed and memory usage, with a false positive rate of about 0.39%.
210
+ It uses about one byte of memory per key.
211
+ For large sets, a Fuse8 filter is more efficient than a Xor8 filter.
212
+ """
213
+ def __init__(self, size_or_data):
214
+ """
215
+ Initialize the Fuse8 filter.
216
+ If an integer is provided, allocate a filter of that size. You must then use 'populate' to add data.
217
+ If an iterable is provided, populate the filter with the data.
218
+ """
219
+ self.__filter = ffi.new("binary_fuse8_t *")
220
+ if isinstance(size_or_data, int):
221
+ status = lib.binary_fuse8_allocate(size_or_data, self.__filter)
222
+ if not status:
223
+ raise MemoryError("Unable to allocate memory for filter")
224
+ else:
225
+ data = list(size_or_data)
226
+ status = lib.binary_fuse8_allocate(len(data), self.__filter)
227
+ if not status:
228
+ raise MemoryError("Unable to allocate memory for filter")
229
+ else:
230
+ data = list(map(lambda x: c_ulonglong((hash(x))).value, data))
231
+ if not lib.binary_fuse8_populate(data, len(data), self.__filter):
232
+ raise ValueError("Unable to populate the filter")
233
+
234
+ def __repr__(self):
235
+ """
236
+ Return a string representation of the Fuse8 filter, including its size in bytes.
237
+ """
238
+ return "Fuse8 object with size(in bytes):{}".format(self.size_in_bytes())
239
+
240
+ def __getitem__(self, item):
241
+ """
242
+ Check if the item is in the filter. With a small probability, the filter
243
+ may return true for an item not in the set (false positive). There is
244
+ no false negative: if the filter returns false, the item is definitely not in the set.
245
+ """
246
+ return self.contains(item)
247
+
248
+ def __contains__(self, item):
249
+ """
250
+ Check if the item is in the filter. With a small probability, the filter
251
+ may return true for an item not in the set (false positive). There is
252
+ no false negative: if the filter returns false, the item is definitely not in the set.
253
+ """
254
+ return self.contains(item)
255
+
256
+ def __del__(self):
257
+ """
258
+ Free the memory allocated for the Fuse8 filter.
259
+ """
260
+ lib.binary_fuse8_free(self.__filter)
261
+
262
+ def populate(self, data: list):
263
+ """
264
+ Set the data of the filter. You may use this method to add data after
265
+ allocating the filter with an integer size. If the number of items
266
+ differs from the allocated size, the filter is reallocated.
267
+ You can reuse a filter with new data (i.e., call populate several times).
268
+ """
269
+ data = list(map(lambda x: c_ulonglong((hash(x))).value, data))
270
+ if len(data) != self.__filter.Size:
271
+ lib.binary_fuse8_free(self.__filter)
272
+ if not lib.binary_fuse8_allocate(len(data), self.__filter):
273
+ raise MemoryError("Unable to allocate memory for filter")
274
+ return lib.binary_fuse8_populate(data, len(data), self.__filter)
275
+
276
+ def contains(self, item):
277
+ """
278
+ Check if the item is in the filter. With a small probability, the filter
279
+ may return true for an item not in the set (false positive). There is
280
+ no false negative: if the filter returns false, the item is definitely not in the set.
281
+ """
282
+ item = c_ulonglong((hash(item))).value
283
+ return lib.binary_fuse8_contain(item, self.__filter)
284
+
285
+ def size_in_bytes(self):
286
+ """
287
+ Return the size of the filter in bytes, not counting Python overhead.
288
+ This value might be slightly larger than the serialized size.
289
+ """
290
+ return lib.binary_fuse8_size_in_bytes(self.__filter)
291
+
292
+ def serialize(self):
293
+ """
294
+ Serialize the filter to a bytes object.
295
+ """
296
+ buffer = ffi.new("char[]", lib.binary_fuse8_serialization_bytes(self.__filter))
297
+ lib.binary_fuse8_serialize(self.__filter, buffer)
298
+ return ffi.buffer(buffer)
299
+
300
+ @staticmethod
301
+ def deserialize(buffer):
302
+ """
303
+ Deserialize a bytes object to a Fuse8 filter.
304
+ """
305
+ self = object.__new__(Fuse8)
306
+ self.__filter = ffi.new("binary_fuse8_t *")
307
+ lib.binary_fuse8_deserialize(self.__filter, ffi.from_buffer(buffer))
308
+ return self
309
+
310
+ class Fuse16:
311
+ """
312
+ Fuse16 is a probabilistic data structure that allows for fast set membership queries.
313
+ It may return false positives but never false negatives. It uses about two bytes of memory per key.
314
+ Its false positive rate is roughly 0.0015%.
315
+ For large sets, a Fuse16 filter is more efficient than a Xor16 filter.
316
+ """
317
+ def __init__(self, size_or_data):
318
+ """
319
+ Initialize the Fuse16 filter.
320
+ If an integer is provided, allocate a filter of that size. You must then use 'populate' to add data.
321
+ If an iterable is provided, populate the filter with the data.
322
+ """
323
+ self.__filter = ffi.new("binary_fuse16_t *")
324
+ if isinstance(size_or_data, int):
325
+ status = lib.binary_fuse16_allocate(size_or_data, self.__filter)
326
+ if not status:
327
+ raise MemoryError("Unable to allocate memory for filter")
328
+ else:
329
+ data = list(size_or_data)
330
+ status = lib.binary_fuse16_allocate(len(data), self.__filter)
331
+ if not status:
332
+ raise MemoryError("Unable to allocate memory for filter")
333
+ else:
334
+ data = list(map(lambda x: c_ulonglong((hash(x))).value, data))
335
+ if not lib.binary_fuse16_populate(data, len(data), self.__filter):
336
+ raise ValueError("Unable to populate the filter")
337
+
338
+ def __repr__(self):
339
+ """
340
+ Return a string representation of the Fuse16 filter, including its size in bytes.
341
+ """
342
+ return "Fuse16 object with size(in bytes):{}".format(self.size_in_bytes())
343
+
344
+ def __getitem__(self, item):
345
+ """
346
+ Check if the item is in the filter. With a small probability, the filter
347
+ may return true for an item not in the set (false positive). There is
348
+ no false negative: if the filter returns false, the item is definitely not in the set.
349
+ """
350
+ return self.contains(item)
351
+
352
+ def __contains__(self, item):
353
+ """
354
+ Check if the item is in the filter. With a small probability, the filter
355
+ may return true for an item not in the set (false positive). There is
356
+ no false negative: if the filter returns false, the item is definitely not in the set.
357
+ """
358
+ return self.contains(item)
359
+
360
+ def __del__(self):
361
+ """
362
+ Free the memory allocated for the Fuse16 filter.
363
+ """
364
+ lib.binary_fuse16_free(self.__filter)
365
+
366
+ def populate(self, data: list):
367
+ """
368
+ Set the data of the filter. You may use this method to add data after
369
+ allocating the filter with an integer size. If the number of items
370
+ differs from the allocated size, the filter is reallocated.
371
+ You can reuse a filter with new data (i.e., call populate several times).
372
+ """
373
+ data = list(map(lambda x: c_ulonglong((hash(x))).value, data))
374
+ if len(data) != self.__filter.Size:
375
+ lib.binary_fuse16_free(self.__filter)
376
+ if not lib.binary_fuse16_allocate(len(data), self.__filter):
377
+ raise MemoryError("Unable to allocate memory for filter")
378
+ return lib.binary_fuse16_populate(data, len(data), self.__filter)
379
+
380
+ def contains(self, item):
381
+ """
382
+ Check if the item is in the filter. With a small probability, the filter
383
+ may return true for an item not in the set (false positive). There is
384
+ no false negative: if the filter returns false, the item is definitely not in the set.
385
+ """
386
+ item = c_ulonglong((hash(item))).value
387
+ return lib.binary_fuse16_contain(item, self.__filter)
388
+
389
+ def size_in_bytes(self):
390
+ """
391
+ Return the size of the filter in bytes, not counting Python overhead.
392
+ This value might be slightly larger than the serialized size.
393
+ """
394
+ return lib.binary_fuse16_size_in_bytes(self.__filter)
395
+
396
+ def serialize(self):
397
+ """
398
+ Serialize the filter to a bytes object.
399
+ """
400
+ buffer = ffi.new("char[]", lib.binary_fuse16_serialization_bytes(self.__filter))
401
+ lib.binary_fuse16_serialize(self.__filter, buffer)
402
+ return ffi.buffer(buffer)
403
+
404
+ @staticmethod
405
+ def deserialize(buffer):
406
+ """
407
+ Deserialize a bytes object to a Fuse16 filter.
408
+ """
409
+ self = object.__new__(Fuse16)
410
+ self.__filter = ffi.new("binary_fuse16_t *")
411
+ lib.binary_fuse16_deserialize(self.__filter, ffi.from_buffer(buffer))
412
+ return self