Skip to content

Commit

Permalink
Merge pull request #43 from tweedegolf/combine-pop-and-peek
Browse files Browse the repository at this point in the history
Adapted queue iterator to return structs
  • Loading branch information
diondokter authored Apr 9, 2024
2 parents cd27d8d + 61e23a5 commit 3906f90
Show file tree
Hide file tree
Showing 5 changed files with 229 additions and 270 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- *Breaking:* The error type is no longer generic over the Item error. That error variant has been renamed `MapValueError`
and carries a predefined error subtype.
- Added `erase_all` function as a helper to erase the flash in a region.
- *Breaking:* Changed the way that queue iteration works. Now there's an `iter` function instead of two separate `peek_many` and `pop_many` functions. The new iter returns an entry from which you can get the data that was just peeked. If you want to pop it, then call the pop function on the entry.

## 1.0.0 01-03-24

Expand Down
2 changes: 1 addition & 1 deletion example/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@ fn main() {
println!("cargo:rustc-link-arg-bins=--nmagic");
println!("cargo:rustc-link-arg-bins=-Tlink.x");
println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
}
}
137 changes: 61 additions & 76 deletions fuzz/fuzz_targets/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ struct Input {
#[derive(Arbitrary, Debug, Clone)]
enum Op {
Push(PushOp),
PopMany(u8),
PeekMany(u8),
Iterate(Vec<bool>),
Peek,
Pop,
}
Expand Down Expand Up @@ -190,66 +189,6 @@ fn fuzz(ops: Input, mut cache: impl CacheImpl + Debug) {
Err(e) => panic!("Error popping (single) from queue: {e:?}"),
}
}
Op::PopMany(n) => {
let mut popper = match block_on(sequential_storage::queue::pop_many(
&mut flash,
FLASH_RANGE,
&mut cache,
)) {
Ok(val) => val,
Err(Error::Corrupted {
backtrace: _backtrace,
}) => {
#[cfg(fuzzing_repro)]
eprintln!(
"Corrupted when creating popper! Originated from:\n{_backtrace:#}"
);
panic!("Corrupted!");
}
Err(e) => panic!("Error while creating popper: {e:?}"),
};

for i in 0..*n {
match block_on(popper.next(&mut buf.0)) {
Ok(value) => {
assert_eq!(
value,
order
.pop_front()
.as_mut()
.map(|target| target.as_mut_slice())
);
}
Err(Error::Storage {
value: MockFlashError::EarlyShutoff(address),
backtrace: _backtrace,
}) => {
#[cfg(fuzzing_repro)]
eprintln!(
"Early shutoff when popping (many)! Originated from:\n{_backtrace:#}"
);

if !matches!(flash.get_item_presence(address), Some(true)) {
// The item is no longer readable here
order.pop_front();
}

*n -= i;
break;
}
Err(Error::Corrupted {
backtrace: _backtrace,
}) => {
#[cfg(fuzzing_repro)]
eprintln!(
"Corrupted when popping many! Originated from:\n{_backtrace:#}"
);
panic!("Corrupted!");
}
Err(e) => panic!("Error popping (many) from queue: {e:?}"),
}
}
}
Op::Peek => {
match block_on(sequential_storage::queue::peek(
&mut flash,
Expand All @@ -275,8 +214,8 @@ fn fuzz(ops: Input, mut cache: impl CacheImpl + Debug) {
Err(e) => panic!("Error popping (single) from queue: {e:?}"),
}
}
Op::PeekMany(n) => {
let mut peeker = match block_on(sequential_storage::queue::peek_many(
Op::Iterate(pop_sequence) => {
let mut iterator = match block_on(sequential_storage::queue::iter(
&mut flash,
FLASH_RANGE,
&mut cache,
Expand All @@ -287,34 +226,80 @@ fn fuzz(ops: Input, mut cache: impl CacheImpl + Debug) {
}) => {
#[cfg(fuzzing_repro)]
eprintln!(
"Corrupted when creating peeker! Originated from:\n{_backtrace:#}"
"Corrupted when creating iterator! Originated from:\n{_backtrace:#}"
);
panic!("Corrupted!");
}
Err(e) => panic!("Error while creating peeker: {e:?}"),
Err(e) => panic!("Error while creating iterator: {e:?}"),
};

for i in 0..*n {
match block_on(peeker.next(&mut buf.0)) {
Ok(value) => {
let mut popped_items = 0;
for (i, do_pop) in pop_sequence.iter().enumerate() {
match block_on(iterator.next(&mut buf.0)) {
Ok(Some(value)) => {
assert_eq!(
value.map(|b| &b[..]),
order
.get(i as usize)
.as_ref()
.map(|target| target.as_slice())
&*value,
order.get(i as usize - popped_items).unwrap().as_slice()
);

if *do_pop {
let popped = block_on(value.pop());

match popped {
Ok(value) => {
assert_eq!(
value,
order
.get(i as usize - popped_items)
.unwrap()
.as_slice()
);

order.remove(i - popped_items).unwrap();
popped_items += 1;
}
Err(Error::Corrupted {
backtrace: _backtrace,
}) => {
#[cfg(fuzzing_repro)]
eprintln!(
"Corrupted when popping interator entry! Originated from:\n{_backtrace:#}"
);
panic!("Corrupted!");
}
Err(Error::Storage {
value: MockFlashError::EarlyShutoff(address),
backtrace: _backtrace,
}) => {
#[cfg(fuzzing_repro)]
eprintln!(
"Early shutoff when popping iterator entry! Originated from:\n{_backtrace:#}"
);

if !matches!(flash.get_item_presence(address), Some(true)) {
// The item is no longer readable here
order.remove(i - popped_items).unwrap();
}

break;
}
Err(e) => panic!("Error popping iterator entry: {e:?}"),
}
}
}
Ok(None) => {
assert_eq!(None, order.get(i as usize - popped_items));
}
Err(Error::Corrupted {
backtrace: _backtrace,
}) => {
#[cfg(fuzzing_repro)]
eprintln!(
"Corrupted when peeking many! Originated from:\n{_backtrace:#}"
"Corrupted when interating! Originated from:\n{_backtrace:#}"
);
panic!("Corrupted!");
}
Err(e) => panic!("Error peeking (many) from queue: {e:?}"),
Err(e) => panic!("Error iterating queue: {e:?}"),
}
}
}
Expand Down
8 changes: 6 additions & 2 deletions src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use crate::{
MAX_WORD_SIZE,
};

#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct ItemHeader {
/// Length of the item payload (so not including the header and not including word alignment)
pub length: u16,
Expand Down Expand Up @@ -204,10 +204,14 @@ pub struct Item<'d> {
}

impl<'d> Item<'d> {
pub fn data(&'d self) -> &'d [u8] {
pub fn data(&self) -> &[u8] {
&self.data_buffer[..self.header.length as usize]
}

pub fn data_mut(&mut self) -> &mut [u8] {
&mut self.data_buffer[..self.header.length as usize]
}

/// Destruct the item to get back the full data buffer
pub fn destruct(self) -> (ItemHeader, &'d mut [u8]) {
(self.header, self.data_buffer)
Expand Down
Loading

0 comments on commit 3906f90

Please sign in to comment.