Skip to content

Commit 482f491

Browse files
khernyoyoshuawuyts
authored andcommitted
Implement bitfield iterator (#68)
* Add one bitfield test from dat/hypercore * Rnd::choose is deprecated * Fix warnings and clippy lints * Implement bitfield iterator * Modify data_iterate mask to better match usage * Cleanup * Rename Bitfield::length() to len() and add is_empty()
1 parent c7c8757 commit 482f491

File tree

9 files changed

+307
-48
lines changed

9 files changed

+307
-48
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ blake2-rfc = "0.2.18"
2121
byteorder = "1.2.6"
2222
ed25519-dalek = "0.8.1"
2323
failure = "0.1.2"
24-
flat-tree = "4.0.1"
24+
flat-tree = "4.1"
2525
lazy_static = "1.1.0"
2626
memory-pager = "0.8.0"
2727
merkle-tree-stream = "0.8.0"

src/bitfield/iterator.rs

Lines changed: 121 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,23 @@ use super::Bitfield;
44

55
/// Iterate over a bitfield.
66
#[derive(Debug)]
7-
pub struct<b>Iterator {
7+
pub struct Iterator<'a> {
88
start: usize,
99
end: usize,
1010
index_end: usize,
11-
pos: usize,
12-
byte: usize,
13-
bitfield: Bitfield,
11+
pos: Option<usize>,
12+
byte: u8,
13+
bitfield: &'a mut Bitfield,
1414
}
1515

16-
impl Iterator {
16+
impl<'a> Iterator<'a> {
1717
/// Create a new instance.
18-
pub fn new(bitfield: &mut Bitfield) -> Self {
18+
pub fn new(bitfield: &'a mut Bitfield) -> Self {
1919
Self {
2020
start: 0,
2121
end: 0,
2222
index_end: 0,
23-
pos: 0,
23+
pos: Some(0),
2424
byte: 0,
2525
bitfield,
2626
}
@@ -30,33 +30,129 @@ impl Iterator {
3030
pub fn range(&mut self, start: usize, end: usize) {
3131
self.start = start;
3232
self.end = end;
33-
self.index_end = 2 * (end as f32 / 32).ceil();
33+
self.index_end = 2 * ((end + 31) / 32);
3434

35-
if self.end > self.bitfield.len() {
35+
if self.end > self.bitfield.length {
3636
self.bitfield.expand(self.end);
3737
}
3838
}
3939

40-
pub fn seek(&mut self, offset: usize) {
41-
offset += self.start;
42-
if offset < self.start {
43-
offset = self.start
40+
/// Seek to `offset`
41+
pub fn seek(&mut self, mut offset: usize) -> &mut Self {
42+
offset += self.start;
43+
// FIXME This is fishy. Offset and start is unsigned, so `offset < self.start` can only
44+
// be true when the previous addition overflows. The overflow would cause a panic, so,
45+
// either the addition should be a wrapping_add, or rather, the original offset should
46+
// be checked to ensure it is less than `self.end - self.start`.
47+
if offset < self.start {
48+
offset = self.start;
4449
}
4550

46-
if offset >= self.end {
47-
self.pos = -1
48-
return;
51+
if offset >= self.end {
52+
self.pos = None;
53+
return self;
54+
}
55+
56+
let o = offset % 8;
57+
58+
let pos = offset / 8;
59+
self.pos = Some(pos);
60+
61+
self.byte =
62+
self.bitfield.data.get_byte(pos) | self.bitfield.masks.data_iterate[o];
63+
64+
self
65+
}
66+
67+
pub fn next(&mut self) -> Option<usize> {
68+
let mut pos = self.pos?;
69+
70+
let mut free = self.bitfield.masks.next_data_0_bit[self.byte as usize];
71+
72+
while free == -1 {
73+
pos += 1;
74+
self.byte = self.bitfield.data.get_byte(pos);
75+
free = self.bitfield.masks.next_data_0_bit[self.byte as usize];
76+
77+
if free == -1 {
78+
pos = self.skip_ahead(pos)?;
79+
80+
self.byte = self.bitfield.data.get_byte(pos);
81+
free = self.bitfield.masks.next_data_0_bit[self.byte as usize];
82+
}
83+
}
84+
self.pos = Some(pos);
85+
86+
self.byte |= self.bitfield.masks.data_iterate[free as usize + 1];
87+
88+
let n = 8 * pos + free as usize;
89+
if n < self.end {
90+
Some(n)
91+
} else {
92+
None
93+
}
4994
}
5095

51-
let o = offset & 7;
96+
pub fn skip_ahead(&mut self, start: usize) -> Option<usize> {
97+
let bitfield_index = &self.bitfield.index;
98+
let tree_end = self.index_end;
99+
let iter = &mut self.bitfield.iterator;
100+
let o = start & 3;
101+
102+
iter.seek(2 * (start / 4));
52103

53-
self.pos = (offset - o) / 8;
54-
let left = self.bitfield.data.get_byte(self.pos);
55-
let right = if o == 0 {
56-
0
57-
} else {
58-
self.bitfield.masks.data_iterate_mask[o - 1]
59-
};
104+
let mut tree_byte = bitfield_index.get_byte(iter.index())
105+
| self.bitfield.masks.index_iterate[o];
106+
107+
while self.bitfield.masks.next_index_0_bit[tree_byte as usize] == -1 {
108+
if iter.is_left() {
109+
iter.next();
110+
} else {
111+
iter.next();
112+
iter.parent();
113+
}
114+
115+
if right_span(iter) >= tree_end {
116+
while right_span(iter) >= tree_end && is_parent(iter) {
117+
iter.left_child();
118+
}
119+
if right_span(iter) >= tree_end {
120+
return None;
121+
}
122+
}
123+
124+
tree_byte = bitfield_index.get_byte(iter.index());
125+
}
126+
127+
while iter.factor() > 2 {
128+
if self.bitfield.masks.next_index_0_bit[tree_byte as usize] < 2 {
129+
iter.left_child();
130+
} else {
131+
iter.right_child();
132+
}
133+
134+
tree_byte = bitfield_index.get_byte(iter.index());
135+
}
136+
137+
let mut free = self.bitfield.masks.next_index_0_bit[tree_byte as usize];
138+
if free == -1 {
139+
free = 4;
140+
}
141+
142+
let next = iter.index() * 2 + free as usize;
143+
144+
if next <= start {
145+
Some(start + 1)
146+
} else {
147+
Some(next)
148+
}
149+
}
150+
}
151+
152+
fn right_span(iter: &flat_tree::Iterator) -> usize {
153+
iter.index() + iter.factor() / 2 - 1
154+
}
60155

61-
self.byte = left | right;
156+
fn is_parent(iter: &flat_tree::Iterator) -> bool {
157+
iter.index() & 1 == 1
62158
}

src/bitfield/masks.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ impl Masks {
3434
];
3535

3636
let data_iterate = vec![
37+
0b00_00_00_00, // 0
3738
0b10_00_00_00, // 128
3839
0b11_00_00_00, // 192
3940
0b11_10_00_00, // 224

src/bitfield/mod.rs

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
//! We need to make sure the performance impact of this stays well within
1818
//! bounds.
1919
20+
mod iterator;
2021
mod masks;
2122

2223
use self::masks::Masks;
@@ -57,6 +58,16 @@ impl Bitfield {
5758
}
5859
}
5960

61+
/// Get the current length
62+
pub fn len(&self) -> usize {
63+
self.length
64+
}
65+
66+
/// Returns `true` if the bitfield is empty
67+
pub fn is_empty(&self) -> bool {
68+
self.length == 0
69+
}
70+
6071
/// Set a value at an index.
6172
pub fn set(&mut self, index: usize, value: bool) -> Change {
6273
let o = mask_8b(index);
@@ -113,17 +124,8 @@ impl Bitfield {
113124
let pos = (start - o) / 8;
114125
let last = (end - e) / 8;
115126

116-
let left_mask = if o == 0 {
117-
255
118-
} else {
119-
255 - self.masks.data_iterate[o - 1]
120-
};
121-
122-
let right_mask = if e == 0 {
123-
0
124-
} else {
125-
self.masks.data_iterate[e - 1]
126-
};
127+
let left_mask = 255 - self.masks.data_iterate[o];
128+
let right_mask = self.masks.data_iterate[e];
127129

128130
let byte = self.data.get_byte(pos);
129131
if pos == last {
@@ -226,6 +228,25 @@ impl Bitfield {
226228
}
227229
}
228230
}
231+
232+
/// Constructs an iterator from start to end
233+
pub fn iterator(&mut self) -> iterator::Iterator<'_> {
234+
let len = self.length;
235+
self.iterator_with_range(0, len)
236+
}
237+
238+
/// Constructs an iterator from `start` to `end`
239+
pub fn iterator_with_range(
240+
&mut self,
241+
start: usize,
242+
end: usize,
243+
) -> iterator::Iterator<'_> {
244+
let mut iter = iterator::Iterator::new(self);
245+
iter.range(start, end);
246+
iter.seek(0);
247+
248+
iter
249+
}
229250
}
230251

231252
// NOTE: can we move this into `sparse_bitfield`?

src/feed.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -535,8 +535,8 @@ where
535535
}
536536
}
537537
Ok(Audit {
538-
valid_blocks: valid_blocks,
539-
invalid_blocks: invalid_blocks,
538+
valid_blocks,
539+
invalid_blocks,
540540
})
541541
}
542542

0 commit comments

Comments
 (0)