expanse 0.4.1
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.
- checksums.yaml +7 -0
- data/README.md +59 -0
- data/Rakefile +11 -0
- data/expanse.gemspec +14 -0
- data/lib/expanse.rb +415 -0
- metadata +47 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: ce88f8b1e4b7b624370805e71f07889013ed5fcc48df6a2d77a2866b617aef2a
|
|
4
|
+
data.tar.gz: 9e5315fbaa5ac09418678232ad510cec31b9c99193c83bc2582eef319cdd3ec1
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: fa88cb5a5b3601e2239f8ca6b06d1d43318f4b9204ca9c33f859b4d583925110b96993e88ee1030fe65756010ea100782609abdfa990c74c944dd92f7f90aff0
|
|
7
|
+
data.tar.gz: 670528b144d51a7e254f58a175aa12b943fefd4bf88031e68bf1117d147d811bf780c0b94195392139229c1b85faace7bc35d7952b9a195a8e3b5c285e69b0f8
|
data/README.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Expanse Ruby Bindings (`expanse`)
|
|
2
|
+
|
|
3
|
+
High-performance, pure-Rust Judy arrays and digital trie engine for Ruby via FFI (`Fiddle`).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Add to your `Gemfile`:
|
|
8
|
+
```ruby
|
|
9
|
+
gem "expanse"
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Or install directly:
|
|
13
|
+
```bash
|
|
14
|
+
gem install expanse
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Quickstart
|
|
18
|
+
|
|
19
|
+
```ruby
|
|
20
|
+
require "expanse"
|
|
21
|
+
|
|
22
|
+
# 1. Dynamic sparse 64-bit integer set (Judy1)
|
|
23
|
+
set = Expanse::Set.new
|
|
24
|
+
set.add(42)
|
|
25
|
+
set.add(100_000)
|
|
26
|
+
puts set.include?(42) # true
|
|
27
|
+
puts set.rank(100_000) # O(depth) rank
|
|
28
|
+
puts set.first # 42
|
|
29
|
+
puts set.last # 100000
|
|
30
|
+
|
|
31
|
+
# 2. Ordered 64-bit key-value map (JudyL)
|
|
32
|
+
map = Expanse::Map.new
|
|
33
|
+
map[42] = 1000
|
|
34
|
+
map[100] = 5000
|
|
35
|
+
puts map[42] # 1000
|
|
36
|
+
map.each do |k, v|
|
|
37
|
+
puts "Key #{k} -> #{v}"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# 3. String trie (JudySL)
|
|
41
|
+
strmap = Expanse::StrMap.new
|
|
42
|
+
strmap["/api/v1/users"] = 200
|
|
43
|
+
puts strmap["/api/v1/users"] # 200
|
|
44
|
+
|
|
45
|
+
# 4. Arbitrary binary bytes map (JudyHS)
|
|
46
|
+
bytesmap = Expanse::BytesMap.new
|
|
47
|
+
bytesmap["binary\x00key".b] = 9999
|
|
48
|
+
puts bytesmap["binary\x00key".b] # 9999
|
|
49
|
+
|
|
50
|
+
# 5. Large-value off-heap blob map
|
|
51
|
+
blobmap = Expanse::BlobMap.new
|
|
52
|
+
blobmap.set(100, "hello world", hot_meta: 1234)
|
|
53
|
+
val, meta = blobmap.get(100)
|
|
54
|
+
puts "#{val} (meta: #{meta})"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Documentation
|
|
58
|
+
|
|
59
|
+
For complete API specifications and benchmarks, see [docs/bindings/ruby.md](https://github.com/orieg/expanse/blob/main/docs/bindings/ruby.md).
|
data/Rakefile
ADDED
data/expanse.gemspec
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Gem::Specification.new do |spec|
|
|
2
|
+
spec.name = "expanse"
|
|
3
|
+
spec.version = "0.4.1"
|
|
4
|
+
spec.authors = ["Nicolas Brousse"]
|
|
5
|
+
spec.email = ["nicolas@brousse.info"]
|
|
6
|
+
spec.summary = "Expanse: clean-room, pure-Rust Judy arrays"
|
|
7
|
+
spec.description = "Ruby bindings for the expanse library."
|
|
8
|
+
spec.homepage = "https://github.com/orieg/expanse"
|
|
9
|
+
spec.license = "MIT OR Apache-2.0"
|
|
10
|
+
|
|
11
|
+
spec.files = Dir["lib/**/*.rb", "README.md", "expanse.gemspec", "Rakefile"]
|
|
12
|
+
spec.require_paths = ["lib"]
|
|
13
|
+
spec.required_ruby_version = ">= 3.0.0"
|
|
14
|
+
end
|
data/lib/expanse.rb
ADDED
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fiddle"
|
|
4
|
+
require "fiddle/import"
|
|
5
|
+
|
|
6
|
+
module Expanse
|
|
7
|
+
VERSION = "0.4.1"
|
|
8
|
+
|
|
9
|
+
module Native
|
|
10
|
+
extend Fiddle::Importer
|
|
11
|
+
|
|
12
|
+
lib_paths = [
|
|
13
|
+
File.expand_path("../../../target/release/libexpanse.dylib", __dir__),
|
|
14
|
+
File.expand_path("../../../target/release/libexpanse.so", __dir__),
|
|
15
|
+
File.expand_path("../../../target/release/expanse.dll", __dir__),
|
|
16
|
+
File.expand_path("../../../target/debug/libexpanse.dylib", __dir__),
|
|
17
|
+
File.expand_path("../../../target/debug/libexpanse.so", __dir__),
|
|
18
|
+
"libexpanse.dylib",
|
|
19
|
+
"libexpanse.so",
|
|
20
|
+
"expanse.dll"
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
loaded = false
|
|
24
|
+
lib_paths.each do |path|
|
|
25
|
+
if File.exist?(path) || !path.include?("/")
|
|
26
|
+
begin
|
|
27
|
+
dlload path
|
|
28
|
+
loaded = true
|
|
29
|
+
break
|
|
30
|
+
rescue StandardError
|
|
31
|
+
# continue searching
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
raise "Could not load libexpanse native library" unless loaded
|
|
37
|
+
|
|
38
|
+
# Library metadata
|
|
39
|
+
extern "const char* expanse_version(void)"
|
|
40
|
+
|
|
41
|
+
# Set
|
|
42
|
+
extern "void* expanse_set_new(void)"
|
|
43
|
+
extern "void expanse_set_free(void*)"
|
|
44
|
+
extern "int expanse_set_insert(void*, unsigned long long)"
|
|
45
|
+
extern "int expanse_set_remove(void*, unsigned long long)"
|
|
46
|
+
extern "int expanse_set_contains(void*, unsigned long long)"
|
|
47
|
+
extern "unsigned long long expanse_set_len(void*)"
|
|
48
|
+
extern "size_t expanse_set_mem_used(void*)"
|
|
49
|
+
extern "void expanse_set_clear(void*)"
|
|
50
|
+
extern "int expanse_set_first(void*, void*)"
|
|
51
|
+
extern "int expanse_set_last(void*, void*)"
|
|
52
|
+
extern "int expanse_set_next_after(void*, unsigned long long, void*)"
|
|
53
|
+
extern "int expanse_set_prev_before(void*, unsigned long long, void*)"
|
|
54
|
+
extern "unsigned long long expanse_set_count_below(void*, unsigned long long)"
|
|
55
|
+
extern "unsigned long long expanse_set_count_range(void*, unsigned long long, unsigned long long)"
|
|
56
|
+
extern "int expanse_set_by_count(void*, unsigned long long, void*)"
|
|
57
|
+
|
|
58
|
+
# Map
|
|
59
|
+
extern "void* expanse_map_new(void)"
|
|
60
|
+
extern "void expanse_map_free(void*)"
|
|
61
|
+
extern "int expanse_map_insert(void*, unsigned long long, unsigned long long, void*)"
|
|
62
|
+
extern "int expanse_map_get(void*, unsigned long long, void*)"
|
|
63
|
+
extern "int expanse_map_remove(void*, unsigned long long, void*)"
|
|
64
|
+
extern "unsigned long long expanse_map_len(void*)"
|
|
65
|
+
extern "size_t expanse_map_mem_used(void*)"
|
|
66
|
+
extern "void expanse_map_clear(void*)"
|
|
67
|
+
extern "int expanse_map_first(void*, void*, void*)"
|
|
68
|
+
extern "int expanse_map_last(void*, void*, void*)"
|
|
69
|
+
extern "int expanse_map_next_after(void*, unsigned long long, void*, void*)"
|
|
70
|
+
extern "int expanse_map_prev_before(void*, unsigned long long, void*, void*)"
|
|
71
|
+
|
|
72
|
+
# StrMap
|
|
73
|
+
extern "void* expanse_strmap_new(void)"
|
|
74
|
+
extern "void expanse_strmap_free(void*)"
|
|
75
|
+
extern "int expanse_strmap_insert(void*, const char*, unsigned long long, void*)"
|
|
76
|
+
extern "int expanse_strmap_get(void*, const char*, void*)"
|
|
77
|
+
extern "int expanse_strmap_remove(void*, const char*, void*)"
|
|
78
|
+
extern "unsigned long long expanse_strmap_len(void*)"
|
|
79
|
+
extern "void expanse_strmap_clear(void*)"
|
|
80
|
+
|
|
81
|
+
# BytesMap
|
|
82
|
+
extern "void* expanse_bytesmap_new(void)"
|
|
83
|
+
extern "void expanse_bytesmap_free(void*)"
|
|
84
|
+
extern "int expanse_bytesmap_insert(void*, const void*, size_t, unsigned long long, void*)"
|
|
85
|
+
extern "int expanse_bytesmap_get(void*, const void*, size_t, void*)"
|
|
86
|
+
extern "int expanse_bytesmap_remove(void*, const void*, size_t, void*)"
|
|
87
|
+
extern "unsigned long long expanse_bytesmap_len(void*)"
|
|
88
|
+
extern "void expanse_bytesmap_clear(void*)"
|
|
89
|
+
|
|
90
|
+
# BlobMap
|
|
91
|
+
extern "void* expanse_blob_map_new(size_t)"
|
|
92
|
+
extern "void expanse_blob_map_free(void*)"
|
|
93
|
+
extern "int expanse_blob_map_insert(void*, unsigned long long, const void*, size_t, unsigned int)"
|
|
94
|
+
extern "int expanse_blob_map_get(void*, unsigned long long, void*)"
|
|
95
|
+
extern "int expanse_blob_map_remove(void*, unsigned long long)"
|
|
96
|
+
extern "unsigned long long expanse_blob_map_len(void*)"
|
|
97
|
+
extern "void expanse_blob_map_clear(void*)"
|
|
98
|
+
extern "int expanse_blob_map_contains_key(void*, unsigned long long)"
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def self.version
|
|
102
|
+
Native.expanse_version.to_s
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
class Set
|
|
106
|
+
include Enumerable
|
|
107
|
+
|
|
108
|
+
def initialize
|
|
109
|
+
@ptr = Native.expanse_set_new
|
|
110
|
+
ObjectSpace.define_finalizer(self, self.class.finalize(@ptr))
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def self.finalize(ptr)
|
|
114
|
+
proc { Native.expanse_set_free(ptr) if ptr && !ptr.null? }
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def add(key)
|
|
118
|
+
Native.expanse_set_insert(@ptr, key) != 0
|
|
119
|
+
end
|
|
120
|
+
alias << add
|
|
121
|
+
|
|
122
|
+
def delete(key)
|
|
123
|
+
Native.expanse_set_remove(@ptr, key) != 0
|
|
124
|
+
end
|
|
125
|
+
alias remove delete
|
|
126
|
+
|
|
127
|
+
def include?(key)
|
|
128
|
+
Native.expanse_set_contains(@ptr, key) != 0
|
|
129
|
+
end
|
|
130
|
+
alias key? include?
|
|
131
|
+
alias member? include?
|
|
132
|
+
|
|
133
|
+
def size
|
|
134
|
+
Native.expanse_set_len(@ptr)
|
|
135
|
+
end
|
|
136
|
+
alias length size
|
|
137
|
+
alias count size
|
|
138
|
+
|
|
139
|
+
def empty?
|
|
140
|
+
size.zero?
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def clear
|
|
144
|
+
Native.expanse_set_clear(@ptr)
|
|
145
|
+
self
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def first
|
|
149
|
+
buf = Fiddle::Pointer.malloc(8)
|
|
150
|
+
if Native.expanse_set_first(@ptr, buf) != 0
|
|
151
|
+
buf.to_str(8).unpack1("Q<")
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def last
|
|
156
|
+
buf = Fiddle::Pointer.malloc(8)
|
|
157
|
+
if Native.expanse_set_last(@ptr, buf) != 0
|
|
158
|
+
buf.to_str(8).unpack1("Q<")
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def next(key)
|
|
163
|
+
buf = Fiddle::Pointer.malloc(8)
|
|
164
|
+
if Native.expanse_set_next_after(@ptr, key, buf) != 0
|
|
165
|
+
buf.to_str(8).unpack1("Q<")
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def prev(key)
|
|
170
|
+
buf = Fiddle::Pointer.malloc(8)
|
|
171
|
+
if Native.expanse_set_prev_before(@ptr, key, buf) != 0
|
|
172
|
+
buf.to_str(8).unpack1("Q<")
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def rank(key)
|
|
177
|
+
Native.expanse_set_count_below(@ptr, key)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def select(k)
|
|
181
|
+
buf = Fiddle::Pointer.malloc(8)
|
|
182
|
+
if Native.expanse_set_by_count(@ptr, k, buf) != 0
|
|
183
|
+
buf.to_str(8).unpack1("Q<")
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def count_range(lo, hi)
|
|
188
|
+
Native.expanse_set_count_range(@ptr, lo, hi)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def each
|
|
192
|
+
return enum_for(:each) unless block_given?
|
|
193
|
+
cur = first
|
|
194
|
+
while cur
|
|
195
|
+
yield cur
|
|
196
|
+
cur = self.next(cur)
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
class Map
|
|
202
|
+
include Enumerable
|
|
203
|
+
|
|
204
|
+
def initialize
|
|
205
|
+
@ptr = Native.expanse_map_new
|
|
206
|
+
ObjectSpace.define_finalizer(self, self.class.finalize(@ptr))
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def self.finalize(ptr)
|
|
210
|
+
proc { Native.expanse_map_free(ptr) if ptr && !ptr.null? }
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def []=(key, val)
|
|
214
|
+
Native.expanse_map_insert(@ptr, key, val, nil)
|
|
215
|
+
val
|
|
216
|
+
end
|
|
217
|
+
alias set []=
|
|
218
|
+
|
|
219
|
+
def [](key)
|
|
220
|
+
buf = Fiddle::Pointer.malloc(8)
|
|
221
|
+
if Native.expanse_map_get(@ptr, key, buf) != 0
|
|
222
|
+
buf.to_str(8).unpack1("Q<")
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
alias get []
|
|
226
|
+
|
|
227
|
+
def delete(key)
|
|
228
|
+
buf = Fiddle::Pointer.malloc(8)
|
|
229
|
+
if Native.expanse_map_remove(@ptr, key, buf) != 0
|
|
230
|
+
buf.to_str(8).unpack1("Q<")
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def key?(key)
|
|
235
|
+
!self[key].nil?
|
|
236
|
+
end
|
|
237
|
+
alias include? key?
|
|
238
|
+
|
|
239
|
+
def size
|
|
240
|
+
Native.expanse_map_len(@ptr)
|
|
241
|
+
end
|
|
242
|
+
alias length size
|
|
243
|
+
|
|
244
|
+
def clear
|
|
245
|
+
Native.expanse_map_clear(@ptr)
|
|
246
|
+
self
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def first
|
|
250
|
+
k_buf = Fiddle::Pointer.malloc(8)
|
|
251
|
+
v_buf = Fiddle::Pointer.malloc(8)
|
|
252
|
+
if Native.expanse_map_first(@ptr, k_buf, v_buf) != 0
|
|
253
|
+
[k_buf.to_str(8).unpack1("Q<"), v_buf.to_str(8).unpack1("Q<")]
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def next(key)
|
|
258
|
+
k_buf = Fiddle::Pointer.malloc(8)
|
|
259
|
+
v_buf = Fiddle::Pointer.malloc(8)
|
|
260
|
+
if Native.expanse_map_next_after(@ptr, key, k_buf, v_buf) != 0
|
|
261
|
+
[k_buf.to_str(8).unpack1("Q<"), v_buf.to_str(8).unpack1("Q<")]
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
def each
|
|
266
|
+
return enum_for(:each) unless block_given?
|
|
267
|
+
pair = first
|
|
268
|
+
while pair
|
|
269
|
+
yield pair[0], pair[1]
|
|
270
|
+
pair = self.next(pair[0])
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
class StrMap
|
|
276
|
+
def initialize
|
|
277
|
+
@ptr = Native.expanse_strmap_new
|
|
278
|
+
ObjectSpace.define_finalizer(self, self.class.finalize(@ptr))
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
def self.finalize(ptr)
|
|
282
|
+
proc { Native.expanse_strmap_free(ptr) if ptr && !ptr.null? }
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
def []=(key, val)
|
|
286
|
+
s = key.to_s
|
|
287
|
+
Native.expanse_strmap_insert(@ptr, s, val, nil)
|
|
288
|
+
val
|
|
289
|
+
end
|
|
290
|
+
alias set []=
|
|
291
|
+
|
|
292
|
+
def [](key)
|
|
293
|
+
s = key.to_s
|
|
294
|
+
buf = Fiddle::Pointer.malloc(8)
|
|
295
|
+
if Native.expanse_strmap_get(@ptr, s, buf) != 0
|
|
296
|
+
buf.to_str(8).unpack1("Q<")
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
alias get []
|
|
300
|
+
|
|
301
|
+
def delete(key)
|
|
302
|
+
s = key.to_s
|
|
303
|
+
buf = Fiddle::Pointer.malloc(8)
|
|
304
|
+
if Native.expanse_strmap_remove(@ptr, s, buf) != 0
|
|
305
|
+
buf.to_str(8).unpack1("Q<")
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
def key?(key)
|
|
310
|
+
!self[key].nil?
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
def size
|
|
314
|
+
Native.expanse_strmap_len(@ptr)
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
def clear
|
|
318
|
+
Native.expanse_strmap_clear(@ptr)
|
|
319
|
+
self
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
class BytesMap
|
|
324
|
+
def initialize
|
|
325
|
+
@ptr = Native.expanse_bytesmap_new
|
|
326
|
+
ObjectSpace.define_finalizer(self, self.class.finalize(@ptr))
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
def self.finalize(ptr)
|
|
330
|
+
proc { Native.expanse_bytesmap_free(ptr) if ptr && !ptr.null? }
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
def []=(key, val)
|
|
334
|
+
b = key.b
|
|
335
|
+
Native.expanse_bytesmap_insert(@ptr, b, b.bytesize, val, nil)
|
|
336
|
+
val
|
|
337
|
+
end
|
|
338
|
+
alias set []=
|
|
339
|
+
|
|
340
|
+
def [](key)
|
|
341
|
+
b = key.b
|
|
342
|
+
buf = Fiddle::Pointer.malloc(8)
|
|
343
|
+
if Native.expanse_bytesmap_get(@ptr, b, b.bytesize, buf) != 0
|
|
344
|
+
buf.to_str(8).unpack1("Q<")
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
alias get []
|
|
348
|
+
|
|
349
|
+
def delete(key)
|
|
350
|
+
b = key.b
|
|
351
|
+
buf = Fiddle::Pointer.malloc(8)
|
|
352
|
+
if Native.expanse_bytesmap_remove(@ptr, b, b.bytesize, buf) != 0
|
|
353
|
+
buf.to_str(8).unpack1("Q<")
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
def key?(key)
|
|
358
|
+
!self[key].nil?
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
def size
|
|
362
|
+
Native.expanse_bytesmap_len(@ptr)
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
def clear
|
|
366
|
+
Native.expanse_bytesmap_clear(@ptr)
|
|
367
|
+
self
|
|
368
|
+
end
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
class BlobMap
|
|
372
|
+
def initialize(chunk_size: 0)
|
|
373
|
+
@ptr = Native.expanse_blob_map_new(chunk_size)
|
|
374
|
+
ObjectSpace.define_finalizer(self, self.class.finalize(@ptr))
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
def self.finalize(ptr)
|
|
378
|
+
proc { Native.expanse_blob_map_free(ptr) if ptr && !ptr.null? }
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
def set(key, payload, hot_meta: 0)
|
|
382
|
+
b = payload.b
|
|
383
|
+
Native.expanse_blob_map_insert(@ptr, key, b, b.bytesize, hot_meta) != 0
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
def get(key)
|
|
387
|
+
# ExpanseBlobView: ptr (8B), len (8B), hot_meta (4B), is_inline (1B) + padding (3B) = 24 bytes
|
|
388
|
+
view_buf = Fiddle::Pointer.malloc(24)
|
|
389
|
+
if Native.expanse_blob_map_get(@ptr, key, view_buf) != 0
|
|
390
|
+
raw_ptr = view_buf[0, 8].unpack1("Q<")
|
|
391
|
+
len = view_buf[8, 8].unpack1("Q<")
|
|
392
|
+
meta = view_buf[16, 4].unpack1("L<")
|
|
393
|
+
val = len.zero? ? "" : Fiddle::Pointer.new(raw_ptr).to_str(len)
|
|
394
|
+
[val, meta]
|
|
395
|
+
end
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
def delete(key)
|
|
399
|
+
Native.expanse_blob_map_remove(@ptr, key) != 0
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
def key?(key)
|
|
403
|
+
Native.expanse_blob_map_contains_key(@ptr, key) != 0
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
def size
|
|
407
|
+
Native.expanse_blob_map_len(@ptr)
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
def clear
|
|
411
|
+
Native.expanse_blob_map_clear(@ptr)
|
|
412
|
+
self
|
|
413
|
+
end
|
|
414
|
+
end
|
|
415
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: expanse
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.4.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Nicolas Brousse
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-08-26 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description: Ruby bindings for the expanse library.
|
|
14
|
+
email:
|
|
15
|
+
- nicolas@brousse.info
|
|
16
|
+
executables: []
|
|
17
|
+
extensions: []
|
|
18
|
+
extra_rdoc_files: []
|
|
19
|
+
files:
|
|
20
|
+
- README.md
|
|
21
|
+
- Rakefile
|
|
22
|
+
- expanse.gemspec
|
|
23
|
+
- lib/expanse.rb
|
|
24
|
+
homepage: https://github.com/orieg/expanse
|
|
25
|
+
licenses:
|
|
26
|
+
- MIT OR Apache-2.0
|
|
27
|
+
metadata: {}
|
|
28
|
+
post_install_message:
|
|
29
|
+
rdoc_options: []
|
|
30
|
+
require_paths:
|
|
31
|
+
- lib
|
|
32
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
33
|
+
requirements:
|
|
34
|
+
- - ">="
|
|
35
|
+
- !ruby/object:Gem::Version
|
|
36
|
+
version: 3.0.0
|
|
37
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
38
|
+
requirements:
|
|
39
|
+
- - ">="
|
|
40
|
+
- !ruby/object:Gem::Version
|
|
41
|
+
version: '0'
|
|
42
|
+
requirements: []
|
|
43
|
+
rubygems_version: 3.5.22
|
|
44
|
+
signing_key:
|
|
45
|
+
specification_version: 4
|
|
46
|
+
summary: 'Expanse: clean-room, pure-Rust Judy arrays'
|
|
47
|
+
test_files: []
|