bitcoinleveldb_table/block.rs
1/*!
2 | Decodes the blocks generated by
3 | block_builder.cc.
4 |
5 */
6
7crate::ix!();
8
9//-------------------------------------------[.cpp/bitcoin/src/leveldb/table/block.h]
10
11pub struct Block {
12
13 data: *const u8,
14 size: usize,
15
16 /**
17 | Offset in data_ of restart array
18 |
19 */
20 restart_offset: u32,
21
22 /**
23 | Block owns data_[]
24 |
25 */
26 owned: bool,
27}
28
29unsafe impl Send for Block {}
30unsafe impl Sync for Block {}
31
32//-------------------------------------------[.cpp/bitcoin/src/leveldb/table/block.cc]
33impl Drop for Block {
34 fn drop(&mut self) {
35 todo!();
36 /*
37 if (owned_) {
38 delete[] data_;
39 }
40 */
41 }
42}
43
44impl Block {
45
46 pub fn size(&self) -> usize {
47
48 todo!();
49 /*
50 return size_;
51 */
52 }
53
54 #[inline] pub fn num_restarts(&self) -> u32 {
55
56 todo!();
57 /*
58 assert(size_ >= sizeof(uint32_t));
59 return DecodeFixed32(data_ + size_ - sizeof(uint32_t));
60 */
61 }
62
63 /**
64 | Initialize the block with the specified
65 | contents.
66 |
67 */
68 pub fn new(contents: &BlockContents) -> Self {
69
70 todo!();
71 /*
72 : data(contents.data.data()),
73 : size(contents.data.size()),
74 : owned(contents.heap_allocated),
75
76 if (size_ < sizeof(uint32_t)) {
77 size_ = 0; // Error marker
78 } else {
79 size_t max_restarts_allowed = (size_ - sizeof(uint32_t)) / sizeof(uint32_t);
80 if (NumRestarts() > max_restarts_allowed) {
81 // The size is too small for NumRestarts()
82 size_ = 0;
83 } else {
84 restart_offset_ = size_ - (1 + NumRestarts()) * sizeof(uint32_t);
85 }
86 }
87 */
88 }
89
90 pub fn new_iterator(&mut self, comparator: Box<dyn SliceComparator>) -> *mut LevelDBIterator {
91
92 todo!();
93 /*
94 if (size_ < sizeof(uint32_t)) {
95 return NewErrorIterator(Status::Corruption("bad block contents"));
96 }
97 const uint32_t num_restarts = NumRestarts();
98 if (num_restarts == 0) {
99 return NewEmptyIterator();
100 } else {
101 return new Iter(comparator, data_, restart_offset_, num_restarts);
102 }
103 */
104 }
105}
106
107/**
108 | Helper routine: decode the next block entry
109 | starting at "p", storing the number of shared
110 | key bytes, non_shared key bytes, and the length
111 | of the value in "*shared", "*non_shared", and
112 | "*value_length", respectively. Will not
113 | dereference past "limit".
114 |
115 | If any errors are detected, returns nullptr.
116 | Otherwise, returns a pointer to the key delta
117 | (just past the three decoded values).
118 */
119#[inline] pub fn decode_entry(
120 p: *const u8,
121 limit: *const u8,
122 shared: *mut u32,
123 non_shared: *mut u32,
124 value_length: *mut u32) -> *const u8 {
125
126 todo!();
127 /*
128 if (limit - p < 3) return nullptr;
129 *shared = reinterpret_cast<const uint8_t*>(p)[0];
130 *non_shared = reinterpret_cast<const uint8_t*>(p)[1];
131 *value_length = reinterpret_cast<const uint8_t*>(p)[2];
132 if ((*shared | *non_shared | *value_length) < 128) {
133 // Fast path: all three values are encoded in one byte each
134 p += 3;
135 } else {
136 if ((p = GetVarint32Ptr(p, limit, shared)) == nullptr) return nullptr;
137 if ((p = GetVarint32Ptr(p, limit, non_shared)) == nullptr) return nullptr;
138 if ((p = GetVarint32Ptr(p, limit, value_length)) == nullptr) return nullptr;
139 }
140
141 if (static_cast<uint32_t>(limit - p) < (*non_shared + *value_length)) {
142 return nullptr;
143 }
144 return p;
145 */
146}
147
148///--------------------
149pub struct BlockIter {
150
151 base: LevelDBIterator,
152
153 comparator: Box<dyn SliceComparator>,
154
155 /**
156 | underlying block contents
157 |
158 */
159 data: *const u8,
160
161 /**
162 | Offset of restart array (list of fixed32)
163 |
164 */
165 restarts: u32,
166
167 /**
168 | Number of uint32_t entries in restart
169 | array
170 |
171 */
172 num_restarts: u32,
173
174 /**
175 | current_ is offset in data_ of current
176 | entry. >= restarts_ if !Valid
177 |
178 */
179 current: u32,
180
181 /**
182 | Index of restart block in which current_
183 | falls
184 |
185 */
186 restart_index: u32,
187
188 key_: String,
189 value: Slice,
190 status: Status,
191}
192
193impl BlockIter {
194
195 #[inline] pub fn compare(&self,
196 a: &Slice,
197 b: &Slice) -> i32 {
198
199 todo!();
200 /*
201 return comparator_->Compare(a, b);
202 */
203 }
204
205 /**
206 | Return the offset in data_ just past
207 | the end of the current entry.
208 |
209 */
210 #[inline] pub fn next_entry_offset(&self) -> u32 {
211
212 todo!();
213 /*
214 return (value_.data() + value_.size()) - data_;
215 */
216 }
217
218 pub fn get_restart_point(&mut self, index: u32) -> u32 {
219
220 todo!();
221 /*
222 assert(index < num_restarts_);
223 return DecodeFixed32(data_ + restarts_ + index * sizeof(uint32_t));
224 */
225 }
226
227 pub fn seek_to_restart_point(&mut self, index: u32) {
228
229 todo!();
230 /*
231 key_.clear();
232 restart_index_ = index;
233 // current_ will be fixed by ParseNextKey();
234
235 // ParseNextKey() starts at the end of value_, so set value_ accordingly
236 uint32_t offset = GetRestartPoint(index);
237 value_ = Slice(data_ + offset, 0);
238 */
239 }
240
241 pub fn new(
242 comparator: Box<dyn SliceComparator>,
243 data: *const u8,
244 restarts: u32,
245 num_restarts: u32) -> Self {
246
247 todo!();
248 /*
249 : comparator(comparator),
250 : data(data),
251 : restarts(restarts),
252 : num_restarts(num_restarts),
253 : current(restarts_),
254 : restart_index(num_restarts_),
255
256 assert(num_restarts_ > 0);
257 */
258 }
259
260 pub fn valid(&self) -> bool {
261
262 todo!();
263 /*
264 return current_ < restarts_;
265 */
266 }
267
268 pub fn status(&self) -> crate::Status {
269
270 todo!();
271 /*
272 return status_;
273 */
274 }
275
276 pub fn key(&self) -> Slice {
277
278 todo!();
279 /*
280 assert(Valid());
281 return key_;
282 */
283 }
284
285 pub fn value(&self) -> Slice {
286
287 todo!();
288 /*
289 assert(Valid());
290 return value_;
291 */
292 }
293
294 pub fn next(&mut self) {
295
296 todo!();
297 /*
298 assert(Valid());
299 ParseNextKey();
300 */
301 }
302
303 pub fn prev(&mut self) {
304
305 todo!();
306 /*
307 assert(Valid());
308
309 // Scan backwards to a restart point before current_
310 const uint32_t original = current_;
311 while (GetRestartPoint(restart_index_) >= original) {
312 if (restart_index_ == 0) {
313 // No more entries
314 current_ = restarts_;
315 restart_index_ = num_restarts_;
316 return;
317 }
318 restart_index_--;
319 }
320
321 SeekToRestartPoint(restart_index_);
322 do {
323 // Loop until end of current entry hits the start of original entry
324 } while (ParseNextKey() && NextEntryOffset() < original);
325 */
326 }
327
328 pub fn seek(&mut self, target: &Slice) {
329
330 todo!();
331 /*
332 // Binary search in restart array to find the last restart point
333 // with a key < target
334 uint32_t left = 0;
335 uint32_t right = num_restarts_ - 1;
336 while (left < right) {
337 uint32_t mid = (left + right + 1) / 2;
338 uint32_t region_offset = GetRestartPoint(mid);
339 uint32_t shared, non_shared, value_length;
340 const char* key_ptr =
341 DecodeEntry(data_ + region_offset, data_ + restarts_, &shared,
342 &non_shared, &value_length);
343 if (key_ptr == nullptr || (shared != 0)) {
344 CorruptionError();
345 return;
346 }
347 Slice mid_key(key_ptr, non_shared);
348 if (Compare(mid_key, target) < 0) {
349 // Key at "mid" is smaller than "target". Therefore all
350 // blocks before "mid" are uninteresting.
351 left = mid;
352 } else {
353 // Key at "mid" is >= "target". Therefore all blocks at or
354 // after "mid" are uninteresting.
355 right = mid - 1;
356 }
357 }
358
359 // Linear search (within restart block) for first key >= target
360 SeekToRestartPoint(left);
361 while (true) {
362 if (!ParseNextKey()) {
363 return;
364 }
365 if (Compare(key_, target) >= 0) {
366 return;
367 }
368 }
369 */
370 }
371
372 pub fn seek_to_first(&mut self) {
373
374 todo!();
375 /*
376 SeekToRestartPoint(0);
377 ParseNextKey();
378 */
379 }
380
381 pub fn seek_to_last(&mut self) {
382
383 todo!();
384 /*
385 SeekToRestartPoint(num_restarts_ - 1);
386 while (ParseNextKey() && NextEntryOffset() < restarts_) {
387 // Keep skipping
388 }
389 */
390 }
391
392 pub fn corruption_error(&mut self) {
393
394 todo!();
395 /*
396 current_ = restarts_;
397 restart_index_ = num_restarts_;
398 status_ = Status::Corruption("bad entry in block");
399 key_.clear();
400 value_.clear();
401 */
402 }
403
404 pub fn parse_next_key(&mut self) -> bool {
405
406 todo!();
407 /*
408 current_ = NextEntryOffset();
409 const char* p = data_ + current_;
410 const char* limit = data_ + restarts_; // Restarts come right after data
411 if (p >= limit) {
412 // No more entries to return. Mark as invalid.
413 current_ = restarts_;
414 restart_index_ = num_restarts_;
415 return false;
416 }
417
418 // Decode next entry
419 uint32_t shared, non_shared, value_length;
420 p = DecodeEntry(p, limit, &shared, &non_shared, &value_length);
421 if (p == nullptr || key_.size() < shared) {
422 CorruptionError();
423 return false;
424 } else {
425 key_.resize(shared);
426 key_.append(p, non_shared);
427 value_ = Slice(p + non_shared, value_length);
428 while (restart_index_ + 1 < num_restarts_ &&
429 GetRestartPoint(restart_index_ + 1) < current_) {
430 ++restart_index_;
431 }
432 return true;
433 }
434 */
435 }
436}