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}