From 1c84ca59eab1c97f359f7c96380c4959e020bb64 Mon Sep 17 00:00:00 2001 From: Aljoscha Meyer Date: Fri, 8 Nov 2024 23:42:44 +0100 Subject: [PATCH] Test Consumer and BulkConsumer default methods --- fuzz/Cargo.toml | 167 +++++------------- .../local_nb/bulk_pipe_into_slice.rs | 41 ----- .../local_nb/bulk_pipe_into_slice_uninit.rs | 44 ----- fuzz/fuzz_targets/local_nb/into_vec.rs | 35 ---- .../local_nb/into_vec_fallible.rs | 35 ---- fuzz/fuzz_targets/local_nb/pipe_into_slice.rs | 41 ----- .../local_nb/pipe_into_slice_uninit.rs | 43 ----- .../local_nb/scramble_consumer.rs | 73 -------- .../local_nb/scramble_producer.rs | 73 -------- fuzz/fuzz_targets/local_nb/slices.rs | 98 ---------- .../fuzz_targets/sync/bulk_pipe_into_slice.rs | 39 ---- .../sync/bulk_pipe_into_slice_uninit.rs | 41 ----- fuzz/fuzz_targets/sync/into_vec.rs | 31 ---- fuzz/fuzz_targets/sync/into_vec_fallible.rs | 31 ---- fuzz/fuzz_targets/sync/pipe_from_slice.rs | 35 ---- fuzz/fuzz_targets/sync/pipe_into_slice.rs | 39 ---- .../sync/pipe_into_slice_uninit.rs | 41 ----- fuzz/fuzz_targets/sync/scramble_consumer.rs | 71 -------- fuzz/fuzz_targets/sync/scramble_producer.rs | 71 -------- fuzz/fuzz_targets/sync/slices.rs | 94 ---------- ufotofu/src/common/consumer/into_vec.rs | 2 +- .../src/common/consumer/into_vec_fallible.rs | 3 +- ufotofu/src/common/consumer/test_consumer.rs | 87 +++++---- 23 files changed, 94 insertions(+), 1141 deletions(-) delete mode 100644 fuzz/fuzz_targets/local_nb/bulk_pipe_into_slice.rs delete mode 100644 fuzz/fuzz_targets/local_nb/bulk_pipe_into_slice_uninit.rs delete mode 100644 fuzz/fuzz_targets/local_nb/into_vec.rs delete mode 100644 fuzz/fuzz_targets/local_nb/into_vec_fallible.rs delete mode 100644 fuzz/fuzz_targets/local_nb/pipe_into_slice.rs delete mode 100644 fuzz/fuzz_targets/local_nb/pipe_into_slice_uninit.rs delete mode 100644 fuzz/fuzz_targets/local_nb/scramble_consumer.rs delete mode 100644 fuzz/fuzz_targets/local_nb/scramble_producer.rs delete mode 100644 fuzz/fuzz_targets/local_nb/slices.rs delete mode 100644 fuzz/fuzz_targets/sync/bulk_pipe_into_slice.rs delete mode 100644 fuzz/fuzz_targets/sync/bulk_pipe_into_slice_uninit.rs delete mode 100644 fuzz/fuzz_targets/sync/into_vec.rs delete mode 100644 fuzz/fuzz_targets/sync/into_vec_fallible.rs delete mode 100644 fuzz/fuzz_targets/sync/pipe_from_slice.rs delete mode 100644 fuzz/fuzz_targets/sync/pipe_into_slice.rs delete mode 100644 fuzz/fuzz_targets/sync/pipe_into_slice_uninit.rs delete mode 100644 fuzz/fuzz_targets/sync/scramble_consumer.rs delete mode 100644 fuzz/fuzz_targets/sync/scramble_producer.rs delete mode 100644 fuzz/fuzz_targets/sync/slices.rs diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 64fa93d..96dcd9e 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -15,138 +15,55 @@ ufotofu_queues = { path = "../ufotofu_queues", features = ["std"] } wrapper = "0.1.1" either = "1.10.0" -# [[bin]] -# name = "slices" -# path = "fuzz_targets/sync/slices.rs" -# test = false -# doc = false -# bench = false +########### +# ufotofu # +########### -# [[bin]] -# name = "into_vec" -# path = "fuzz_targets/sync/into_vec.rs" -# test = false -# doc = false -# bench = false - -# [[bin]] -# name = "into_vec_fallible" -# path = "fuzz_targets/sync/into_vec_fallible.rs" -# test = false -# doc = false -# bench = false - -# [[bin]] -# name = "scramble_consumer" -# path = "fuzz_targets/sync/scramble_consumer.rs" -# test = false -# doc = false -# bench = false - -# [[bin]] -# name = "scramble_producer" -# path = "fuzz_targets/sync/scramble_producer.rs" -# test = false -# doc = false -# bench = false - -# [[bin]] -# name = "local_nb_slices" -# path = "fuzz_targets/local_nb/slices.rs" -# test = false -# doc = false -# bench = false - -# [[bin]] -# name = "local_nb_into_vec" -# path = "fuzz_targets/local_nb/into_vec.rs" -# test = false -# doc = false -# bench = false - -# [[bin]] -# name = "local_nb_into_vec_fallible" -# path = "fuzz_targets/local_nb/into_vec_fallible.rs" -# test = false -# doc = false -# bench = false - -# [[bin]] -# name = "local_nb_scramble_consumer" -# path = "fuzz_targets/local_nb/scramble_consumer.rs" -# test = false -# doc = false -# bench = false - -# [[bin]] -# name = "local_nb_scramble_producer" -# path = "fuzz_targets/local_nb/scramble_producer.rs" -# test = false -# doc = false -# bench = false - -# [[bin]] -# name = "sync_pipe_into_slice" -# path = "fuzz_targets/sync/pipe_into_slice.rs" -# test = false -# doc = false -# bench = false - -# [[bin]] -# name = "sync_bulk_pipe_into_slice" -# path = "fuzz_targets/sync/bulk_pipe_into_slice.rs" -# test = false -# doc = false -# bench = false - -# [[bin]] -# name = "sync_pipe_into_slice_uninit" -# path = "fuzz_targets/sync/pipe_into_slice_uninit.rs" -# test = false -# doc = false -# bench = false +[[bin]] +name = "sync_consume_full_slice" +path = "fuzz_targets/sync/consume_full_slice.rs" +test = false +doc = false +bench = false -# [[bin]] -# name = "sync_bulk_pipe_into_slice_uninit" -# path = "fuzz_targets/sync/bulk_pipe_into_slice_uninit.rs" -# test = false -# doc = false -# bench = false +[[bin]] +name = "local_nb_consume_full_slice" +path = "fuzz_targets/local_nb/consume_full_slice.rs" +test = false +doc = false +bench = false -# [[bin]] -# name = "sync_pipe_from_slice" -# path = "fuzz_targets/sync/pipe_from_slice.rs" -# test = false -# doc = false -# bench = false +[[bin]] +name = "sync_bulk_consume" +path = "fuzz_targets/sync/bulk_consume.rs" +test = false +doc = false +bench = false -# [[bin]] -# name = "local_nb_pipe_into_slice" -# path = "fuzz_targets/local_nb/pipe_into_slice.rs" -# test = false -# doc = false -# bench = false +[[bin]] +name = "local_nb_bulk_consume" +path = "fuzz_targets/local_nb/bulk_consume.rs" +test = false +doc = false +bench = false -# [[bin]] -# name = "local_nb_bulk_pipe_into_slice" -# path = "fuzz_targets/local_nb/bulk_pipe_into_slice.rs" -# test = false -# doc = false -# bench = false +[[bin]] +name = "sync_bulk_consume_full_slice" +path = "fuzz_targets/sync/bulk_consume_full_slice.rs" +test = false +doc = false +bench = false -# [[bin]] -# name = "local_nb_pipe_into_slice_uninit" -# path = "fuzz_targets/local_nb/pipe_into_slice_uninit.rs" -# test = false -# doc = false -# bench = false +[[bin]] +name = "local_nb_bulk_consume_full_slice" +path = "fuzz_targets/local_nb/bulk_consume_full_slice.rs" +test = false +doc = false +bench = false -# [[bin]] -# name = "local_nb_bulk_pipe_into_slice_uninit" -# path = "fuzz_targets/local_nb/bulk_pipe_into_slice_uninit.rs" -# test = false -# doc = false -# bench = false +#################### +## ufotofu_queues ## +#################### [[bin]] name = "queues_fixed_bulk" diff --git a/fuzz/fuzz_targets/local_nb/bulk_pipe_into_slice.rs b/fuzz/fuzz_targets/local_nb/bulk_pipe_into_slice.rs deleted file mode 100644 index 2ceb5ec..0000000 --- a/fuzz/fuzz_targets/local_nb/bulk_pipe_into_slice.rs +++ /dev/null @@ -1,41 +0,0 @@ -#![no_main] - -use either::{Left, Right}; -use libfuzzer_sys::fuzz_target; -use ufotofu::local_nb::producer::{bulk_pipe_into_slice, TestProducer}; - -fuzz_target!(|data: (TestProducer, usize)| { - let (mut producer, length) = data; - - let clamped_length = length.clamp(0, 512); - - let mut v: Vec = vec![0; clamped_length]; - - let producer_data = producer.peek_slice().to_vec(); - - // peek termination here. - - async { - match bulk_pipe_into_slice(&mut v[0..clamped_length], &mut producer).await { - Ok(_) => { - // Were the bytes successfully piped? - - // refactor as assert_eq - if producer_data[0..clamped_length] != v[0..clamped_length] { - panic!("Bytes piped into slice did not match!") - } - } - Err(err) => { - // let producer_data = producer.peek_slice(); - - // If the filled property is not equal to the inner slice, panic. - // assertion macro - if err.filled != producer_data { - panic!("Filled was not the same as the producer slice.") - } - - // Do we need to check if the error produced was the right kind? e.g. by inspecting the producer's termination field? - } - } - }; -}); diff --git a/fuzz/fuzz_targets/local_nb/bulk_pipe_into_slice_uninit.rs b/fuzz/fuzz_targets/local_nb/bulk_pipe_into_slice_uninit.rs deleted file mode 100644 index e715b2a..0000000 --- a/fuzz/fuzz_targets/local_nb/bulk_pipe_into_slice_uninit.rs +++ /dev/null @@ -1,44 +0,0 @@ -#![no_main] - -// use core::mem::MaybeUninit; -// use either::{Left, Right}; -use libfuzzer_sys::fuzz_target; -// use ufotofu::local_nb::producer::{bulk_pipe_into_slice_uninit, TestProducer}; - -fuzz_target!(|data: u64| { -// fuzz_target!(|data: (TestProducer, usize)| { - // let (mut producer, length) = data; - - // let clamped_length = length.clamp(0, 512); - - // let mut v: Vec = vec![0; clamped_length]; - - // let producer_data = producer.peek_slice().to_vec(); - - // let producer_data_maybe_uninit = - // unsafe { &mut *(&mut v[0..clamped_length] as *mut [u16] as *mut [MaybeUninit]) }; - - // async { - // match bulk_pipe_into_slice_uninit(producer_data_maybe_uninit, &mut producer).await { - // Ok(_) => { - // // Were the bytes successfully piped? - - // // refactor as assert_eq - // if producer_data[0..clamped_length] != v[0..clamped_length] { - // panic!("Bytes piped into slice did not match!") - // } - // } - // Err(err) => { - // // let producer_data = producer.peek_slice(); - - // // If the filled property is not equal to the inner slice, panic. - // // assertion macro - // if err.filled != producer_data { - // panic!("Filled was not the same as the producer slice.") - // } - - // // Do we need to check if the error produced was the right kind? e.g. by inspecting the producer's termination field? - // } - // } - // }; -}); diff --git a/fuzz/fuzz_targets/local_nb/into_vec.rs b/fuzz/fuzz_targets/local_nb/into_vec.rs deleted file mode 100644 index 6c9a20f..0000000 --- a/fuzz/fuzz_targets/local_nb/into_vec.rs +++ /dev/null @@ -1,35 +0,0 @@ -#![no_main] -#![feature(never_type)] - -use libfuzzer_sys::fuzz_target; - -use ufotofu::local_nb; -use ufotofu::local_nb::consumer::IntoVec; -use ufotofu::local_nb::producer::SliceProducer; - -fn fuzz_pipe(data: &[u8]) { - smol::block_on(async { - let mut o = SliceProducer::new(&data[..]); - let mut i = IntoVec::new(); - - let _ = local_nb::pipe(&mut o, &mut i).await; - - assert_eq!(&i.into_vec(), &data[..]); - }) -} - -fn fuzz_bulk_pipe(data: &[u8]) { - smol::block_on(async { - let mut o = SliceProducer::new(&data[..]); - let mut i = IntoVec::new(); - - let _ = local_nb::bulk_pipe(&mut o, &mut i).await; - - assert_eq!(&i.into_vec(), &data[..]); - }) -} - -fuzz_target!(|data: &[u8]| { - fuzz_pipe(data); - fuzz_bulk_pipe(data); -}); diff --git a/fuzz/fuzz_targets/local_nb/into_vec_fallible.rs b/fuzz/fuzz_targets/local_nb/into_vec_fallible.rs deleted file mode 100644 index dfce6b1..0000000 --- a/fuzz/fuzz_targets/local_nb/into_vec_fallible.rs +++ /dev/null @@ -1,35 +0,0 @@ -#![no_main] -#![feature(never_type)] - -use libfuzzer_sys::fuzz_target; - -use ufotofu::local_nb; -use ufotofu::local_nb::consumer::IntoVecFallible; -use ufotofu::local_nb::producer::SliceProducer; - -fn fuzz_pipe(data: &[u8]) { - smol::block_on(async { - let mut o = SliceProducer::new(&data[..]); - let mut i = IntoVecFallible::new(); - - let _ = local_nb::pipe(&mut o, &mut i).await; - - assert_eq!(&i.into_vec(), &data[..]); - }) -} - -fn fuzz_bulk_pipe(data: &[u8]) { - smol::block_on(async { - let mut o = SliceProducer::new(&data[..]); - let mut i = IntoVecFallible::new(); - - let _ = local_nb::bulk_pipe(&mut o, &mut i).await; - - assert_eq!(&i.into_vec(), &data[..]); - }) -} - -fuzz_target!(|data: &[u8]| { - fuzz_pipe(data); - fuzz_bulk_pipe(data); -}); diff --git a/fuzz/fuzz_targets/local_nb/pipe_into_slice.rs b/fuzz/fuzz_targets/local_nb/pipe_into_slice.rs deleted file mode 100644 index 028fc73..0000000 --- a/fuzz/fuzz_targets/local_nb/pipe_into_slice.rs +++ /dev/null @@ -1,41 +0,0 @@ -#![no_main] - -use either::{Left, Right}; -use libfuzzer_sys::fuzz_target; -use ufotofu::local_nb::producer::{pipe_into_slice, TestProducer}; - -fuzz_target!(|data: (TestProducer, usize)| { - let (mut producer, length) = data; - - let clamped_length = length.clamp(0, 512); - - let mut v: Vec = vec![0; clamped_length]; - - let producer_data = producer.peek_slice().to_vec(); - - // peek termination here. - - async { - match pipe_into_slice(&mut v[0..clamped_length], &mut producer).await { - Ok(_) => { - // Were the bytes successfully piped? - - // refactor as assert_eq - if producer_data[0..clamped_length] != v[0..clamped_length] { - panic!("Bytes piped into slice did not match!") - } - } - Err(err) => { - // let producer_data = producer.peek_slice(); - - // If the filled property is not equal to the inner slice, panic. - // assertion macro - if err.filled != producer_data { - panic!("Filled was not the same as the producer slice.") - } - - // Do we need to check if the error produced was the right kind? e.g. by inspecting the producer's termination field? - } - } - }; -}); diff --git a/fuzz/fuzz_targets/local_nb/pipe_into_slice_uninit.rs b/fuzz/fuzz_targets/local_nb/pipe_into_slice_uninit.rs deleted file mode 100644 index cfeab1b..0000000 --- a/fuzz/fuzz_targets/local_nb/pipe_into_slice_uninit.rs +++ /dev/null @@ -1,43 +0,0 @@ -#![no_main] - -use core::mem::MaybeUninit; -use either::{Left, Right}; -use libfuzzer_sys::fuzz_target; -use ufotofu::local_nb::producer::{pipe_into_slice_uninit, TestProducer}; - -fuzz_target!(|data: (TestProducer, usize)| { - let (mut producer, length) = data; - - let clamped_length = length.clamp(0, 512); - - let mut v: Vec = vec![0; clamped_length]; - - let producer_data = producer.peek_slice().to_vec(); - - let producer_data_maybe_uninit = - unsafe { &mut *(&mut v[0..clamped_length] as *mut [u16] as *mut [MaybeUninit]) }; - - async { - match pipe_into_slice_uninit(producer_data_maybe_uninit, &mut producer).await { - Ok(_) => { - // Were the bytes successfully piped? - - // refactor as assert_eq - if producer_data[0..clamped_length] != v[0..clamped_length] { - panic!("Bytes piped into slice did not match!") - } - } - Err(err) => { - // let producer_data = producer.peek_slice(); - - // If the filled property is not equal to the inner slice, panic. - // assertion macro - if err.filled != producer_data { - panic!("Filled was not the same as the producer slice.") - } - - // Do we need to check if the error produced was the right kind? e.g. by inspecting the producer's termination field? - } - } - }; -}); diff --git a/fuzz/fuzz_targets/local_nb/scramble_consumer.rs b/fuzz/fuzz_targets/local_nb/scramble_consumer.rs deleted file mode 100644 index de62745..0000000 --- a/fuzz/fuzz_targets/local_nb/scramble_consumer.rs +++ /dev/null @@ -1,73 +0,0 @@ -#![no_main] -#![feature(never_type)] - -use libfuzzer_sys::fuzz_target; -use libfuzzer_sys::{arbitrary, arbitrary::Arbitrary}; - -use core::cmp::min; - -use wrapper::Wrapper; - -use ufotofu::local_nb::consumer::{ConsumeOperations, IntoVec, Scramble}; -use ufotofu::local_nb::producer::SliceProducer; -use ufotofu::local_nb::{self, LocalBufferedConsumer}; - -fn data_is_invalid(data: &TestData) -> bool { - if data.outer_capacity < 1 || data.outer_capacity > 2048 { - return true; - } - - if data.inner_capacity < 1 || data.inner_capacity > 2048 { - return true; - } - - false -} - -#[derive(Debug, Clone, Arbitrary)] -struct TestData { - producer_buffer: Box<[u8]>, - outer_operations: ConsumeOperations, - inner_operations: ConsumeOperations, - outer_capacity: usize, - inner_capacity: usize, -} - -fuzz_target!(|data: TestData| { - smol::block_on(async { - if data_is_invalid(&data) { - return; - } - - let TestData { - producer_buffer, - outer_operations, - inner_operations, - outer_capacity, - inner_capacity, - } = data; - - // Consumer. - let into_vec = IntoVec::new(); - - // Producer. - let mut o = SliceProducer::new(&producer_buffer[..]); - - // Scrambler wrapping a scrambler with an inner `into_vec` consumer. - let mut i = Scramble::new( - Scramble::new(into_vec, inner_operations, inner_capacity), - outer_operations, - outer_capacity, - ); - - let _ = local_nb::bulk_pipe(&mut o, &mut i).await; - let _ = i.flush().await; - - // Access the inner consumer (`into_vec`). - let i = i.into_inner().into_inner(); - - // Compare the contents of the consumer and producer. - let m = min(o.as_ref().len(), i.as_ref().len()); - assert_eq!(&i.as_ref()[..m], &o.as_ref()[..m]); - }) -}); diff --git a/fuzz/fuzz_targets/local_nb/scramble_producer.rs b/fuzz/fuzz_targets/local_nb/scramble_producer.rs deleted file mode 100644 index 1092993..0000000 --- a/fuzz/fuzz_targets/local_nb/scramble_producer.rs +++ /dev/null @@ -1,73 +0,0 @@ -#![no_main] -#![feature(never_type)] - -use libfuzzer_sys::fuzz_target; -use libfuzzer_sys::{arbitrary, arbitrary::Arbitrary}; - -use core::cmp::min; - -use wrapper::Wrapper; - -use ufotofu::local_nb::consumer::IntoVec; -use ufotofu::local_nb::producer::{ProduceOperations, Scramble, SliceProducer}; -use ufotofu::local_nb::{self, LocalBufferedConsumer}; - -fn data_is_invalid(data: &TestData) -> bool { - if data.outer_capacity < 1 || data.outer_capacity > 2048 { - return true; - } - - if data.inner_capacity < 1 || data.inner_capacity > 2048 { - return true; - } - - false -} - -#[derive(Debug, Clone, Arbitrary)] -struct TestData { - producer_buffer: Box<[u8]>, - outer_operations: ProduceOperations, - inner_operations: ProduceOperations, - outer_capacity: usize, - inner_capacity: usize, -} - -fuzz_target!(|data: TestData| { - smol::block_on(async { - if data_is_invalid(&data) { - return; - } - - let TestData { - mut producer_buffer, - outer_operations, - inner_operations, - outer_capacity, - inner_capacity, - } = data; - - // Producer. - let slice_producer = SliceProducer::new(&mut producer_buffer[..]); - - // Consumer. - let mut i = IntoVec::new(); - - // Scrambler wrapping a scrambler with an inner `slice_producer`. - let mut o = Scramble::new( - Scramble::new(slice_producer, inner_operations, inner_capacity), - outer_operations, - outer_capacity, - ); - - let _ = local_nb::bulk_pipe(&mut o, &mut i).await; - let _ = i.flush().await; - - // Access the inner producer (`slice_producer`). - let o = o.into_inner().into_inner(); - - // Compare the contents of the producer and consumer. - let m = min(o.as_ref().len(), i.as_ref().len()); - assert_eq!(&i.as_ref()[..m], &o.as_ref()[..m]); - }) -}); diff --git a/fuzz/fuzz_targets/local_nb/slices.rs b/fuzz/fuzz_targets/local_nb/slices.rs deleted file mode 100644 index 4610ab1..0000000 --- a/fuzz/fuzz_targets/local_nb/slices.rs +++ /dev/null @@ -1,98 +0,0 @@ -#![no_main] - -use core::cmp::min; - -use libfuzzer_sys::fuzz_target; -use libfuzzer_sys::{arbitrary, arbitrary::Arbitrary}; - -use ufotofu::local_nb; -use ufotofu::local_nb::consumer::SliceConsumer; -use ufotofu::local_nb::producer::SliceProducer; - -#[derive(Debug, Clone, Arbitrary)] -struct TestData { - input_buf: Box<[u8]>, - output_buf: Box<[u8]>, - input_start: usize, - input_end: usize, - output_start: usize, - output_end: usize, -} - -// Filter out any data conditions which would violate invariants that must be -// upheld when calling our functions. -fn data_is_invalid(data: TestData) -> bool { - if data.input_start > data.input_end { - return true; - } else if data.input_end > data.input_buf.len() { - return true; - } else if data.output_start > data.output_end { - return true; - } else if data.output_end > data.output_buf.len() { - return true; - } else { - false - } -} - -fn fuzz_pipe(mut data: TestData) { - smol::block_on(async { - if data_is_invalid(data.clone()) { - return; - } - - let mut o = SliceProducer::new(&data.input_buf[data.input_start..data.input_end]); - let mut i = SliceConsumer::new(&mut data.output_buf[data.output_start..data.output_end]); - - match local_nb::pipe(&mut o, &mut i).await { - Ok(_) => { - if &o.as_ref().len() > &i.as_ref().len() { - panic!() - } - } - Err(_) => { - if &o.as_ref().len() <= &i.as_ref().len() { - panic!() - } - } - } - - let m = min(o.as_ref().len(), i.as_ref().len()); - assert_eq!(&i.as_ref()[..m], &o.as_ref()[..m]); - }) -} - -fn fuzz_bulk_pipe(mut data: TestData) { - smol::block_on(async { - if data_is_invalid(data.clone()) { - return; - } - - let mut o = SliceProducer::new(&data.input_buf[data.input_start..data.input_end]); - let mut i = SliceConsumer::new(&mut data.output_buf[data.output_start..data.output_end]); - - match local_nb::bulk_pipe(&mut o, &mut i).await { - Ok(_) => { - if &o.as_ref().len() > &i.as_ref().len() { - panic!() - } - } - Err(_) => { - if &o.as_ref().len() <= &i.as_ref().len() { - panic!() - } - } - } - - let m = min(o.as_ref().len(), i.as_ref().len()); - assert_eq!(&i.as_ref()[..m], &o.as_ref()[..m]); - }) -} - -fuzz_target!(|data_origin: (TestData, TestData)| { - let data = data_origin.0.clone(); - fuzz_pipe(data); - - let data = data_origin.1.clone(); - fuzz_bulk_pipe(data); -}); diff --git a/fuzz/fuzz_targets/sync/bulk_pipe_into_slice.rs b/fuzz/fuzz_targets/sync/bulk_pipe_into_slice.rs deleted file mode 100644 index 7d1569b..0000000 --- a/fuzz/fuzz_targets/sync/bulk_pipe_into_slice.rs +++ /dev/null @@ -1,39 +0,0 @@ -#![no_main] - -use either::{Left, Right}; -use libfuzzer_sys::fuzz_target; -use ufotofu::sync::producer::{bulk_pipe_into_slice, TestProducer}; - -fuzz_target!(|data: (TestProducer, usize)| { - let (mut producer, length) = data; - - let clamped_length = length.clamp(0, 512); - - let mut v: Vec = vec![0; clamped_length]; - - let producer_data = producer.peek_slice().to_vec(); - - // peek termination here. - - match bulk_pipe_into_slice(&mut v[0..clamped_length], &mut producer) { - Ok(_) => { - // Were the bytes successfully piped? - - // refactor as assert_eq - if producer_data[0..clamped_length] != v[0..clamped_length] { - panic!("Bytes piped into slice did not match!") - } - } - Err(err) => { - // let producer_data = producer.peek_slice(); - - // If the filled property is not equal to the inner slice, panic. - // assertion macro - if err.filled != producer_data { - panic!("Filled was not the same as the producer slice.") - } - - // Do we need to check if the error produced was the right kind? e.g. by inspecting the producer's termination field? - } - } -}); diff --git a/fuzz/fuzz_targets/sync/bulk_pipe_into_slice_uninit.rs b/fuzz/fuzz_targets/sync/bulk_pipe_into_slice_uninit.rs deleted file mode 100644 index 3eb9348..0000000 --- a/fuzz/fuzz_targets/sync/bulk_pipe_into_slice_uninit.rs +++ /dev/null @@ -1,41 +0,0 @@ -#![no_main] - -use core::mem::MaybeUninit; -use either::{Left, Right}; -use libfuzzer_sys::fuzz_target; -use ufotofu::sync::producer::{bulk_pipe_into_slice_uninit, TestProducer}; - -fuzz_target!(|data: (TestProducer, usize)| { - let (mut producer, length) = data; - - let clamped_length = length.clamp(0, 512); - - let mut v: Vec = vec![0; clamped_length]; - - let producer_data = producer.peek_slice().to_vec(); - - let producer_data_maybe_uninit = - unsafe { &mut *(&mut v[0..clamped_length] as *mut [u16] as *mut [MaybeUninit]) }; - - match bulk_pipe_into_slice_uninit(producer_data_maybe_uninit, &mut producer) { - Ok(_) => { - // Were the bytes successfully piped? - - // refactor as assert_eq - if producer_data[0..clamped_length] != v[0..clamped_length] { - panic!("Bytes piped into slice did not match!") - } - } - Err(err) => { - // let producer_data = producer.peek_slice(); - - // If the filled property is not equal to the inner slice, panic. - // assertion macro - if err.filled != producer_data { - panic!("Filled was not the same as the producer slice.") - } - - // Do we need to check if the error produced was the right kind? e.g. by inspecting the producer's termination field? - } - } -}); diff --git a/fuzz/fuzz_targets/sync/into_vec.rs b/fuzz/fuzz_targets/sync/into_vec.rs deleted file mode 100644 index 8c32d54..0000000 --- a/fuzz/fuzz_targets/sync/into_vec.rs +++ /dev/null @@ -1,31 +0,0 @@ -#![no_main] -#![feature(never_type)] - -use libfuzzer_sys::fuzz_target; - -use ufotofu::sync; -use ufotofu::sync::consumer::IntoVec; -use ufotofu::sync::producer::SliceProducer; - -fn fuzz_pipe(data: &[u8]) { - let mut o = SliceProducer::new(&data[..]); - let mut i = IntoVec::new(); - - let _ = sync::pipe(&mut o, &mut i); - - assert_eq!(&i.into_vec(), &data[..]); -} - -fn fuzz_bulk_pipe(data: &[u8]) { - let mut o = SliceProducer::new(&data[..]); - let mut i = IntoVec::new(); - - let _ = sync::bulk_pipe(&mut o, &mut i); - - assert_eq!(&i.into_vec(), &data[..]); -} - -fuzz_target!(|data: &[u8]| { - fuzz_pipe(data); - fuzz_bulk_pipe(data); -}); diff --git a/fuzz/fuzz_targets/sync/into_vec_fallible.rs b/fuzz/fuzz_targets/sync/into_vec_fallible.rs deleted file mode 100644 index 18ea553..0000000 --- a/fuzz/fuzz_targets/sync/into_vec_fallible.rs +++ /dev/null @@ -1,31 +0,0 @@ -#![no_main] -#![feature(never_type)] - -use libfuzzer_sys::fuzz_target; - -use ufotofu::sync; -use ufotofu::sync::consumer::IntoVecFallible; -use ufotofu::sync::producer::SliceProducer; - -fn fuzz_pipe(data: &[u8]) { - let mut o = SliceProducer::new(&data[..]); - let mut i = IntoVecFallible::new(); - - let _ = sync::pipe(&mut o, &mut i); - - assert_eq!(&i.into_vec(), &data[..]); -} - -fn fuzz_bulk_pipe(data: &[u8]) { - let mut o = SliceProducer::new(&data[..]); - let mut i = IntoVecFallible::new(); - - let _ = sync::bulk_pipe(&mut o, &mut i); - - assert_eq!(&i.into_vec(), &data[..]); -} - -fuzz_target!(|data: &[u8]| { - fuzz_pipe(data); - fuzz_bulk_pipe(data); -}); diff --git a/fuzz/fuzz_targets/sync/pipe_from_slice.rs b/fuzz/fuzz_targets/sync/pipe_from_slice.rs deleted file mode 100644 index 8325e3d..0000000 --- a/fuzz/fuzz_targets/sync/pipe_from_slice.rs +++ /dev/null @@ -1,35 +0,0 @@ -#![no_main] - -use either::{Left, Right}; -use libfuzzer_sys::fuzz_target; -use ufotofu::sync::consumer::{pipe_from_slice, TestConsumer}; -use ufotofu::sync::BufferedConsumer; - -fuzz_target!(|data: (TestConsumer, Vec)| { - let (mut consumer, mut items) = data; - - match pipe_from_slice(&mut items, &mut consumer) { - Ok(_) => { - // Were the bytes successfully piped? - consumer.flush(); - - assert_eq!( - consumer.as_ref(), - items.as_slice(), - "Bytes piped into slice did not match!" - ); - } - Err(err) => { - // let consumer_data = consumer.peek_slice(); - consumer.flush(); - - // If the filled property is not equal to the inner slice, panic. - // assertion macro - if *consumer.as_ref() == items[0..err.consumed] { - panic!("Consumed was not the same as the consumer slice.") - } - - // Do we need to check if the error produced was the right kind? e.g. by inspecting the consumer's termination field? - } - } -}); diff --git a/fuzz/fuzz_targets/sync/pipe_into_slice.rs b/fuzz/fuzz_targets/sync/pipe_into_slice.rs deleted file mode 100644 index 771fad4..0000000 --- a/fuzz/fuzz_targets/sync/pipe_into_slice.rs +++ /dev/null @@ -1,39 +0,0 @@ -#![no_main] - -use either::{Left, Right}; -use libfuzzer_sys::fuzz_target; -use ufotofu::sync::producer::{pipe_into_slice, TestProducer}; - -fuzz_target!(|data: (TestProducer, usize)| { - let (mut producer, length) = data; - - let clamped_length = length.clamp(0, 512); - - let mut v: Vec = vec![0; clamped_length]; - - let producer_data = producer.peek_slice().to_vec(); - - // peek termination here. - - match pipe_into_slice(&mut v[0..clamped_length], &mut producer) { - Ok(_) => { - // Were the bytes successfully piped? - - // refactor as assert_eq - if producer_data[0..clamped_length] != v[0..clamped_length] { - panic!("Bytes piped into slice did not match!") - } - } - Err(err) => { - // let producer_data = producer.peek_slice(); - - // If the filled property is not equal to the inner slice, panic. - // assertion macro - if err.filled != producer_data { - panic!("Filled was not the same as the producer slice.") - } - - // Do we need to check if the error produced was the right kind? e.g. by inspecting the producer's termination field? - } - } -}); diff --git a/fuzz/fuzz_targets/sync/pipe_into_slice_uninit.rs b/fuzz/fuzz_targets/sync/pipe_into_slice_uninit.rs deleted file mode 100644 index a783a4d..0000000 --- a/fuzz/fuzz_targets/sync/pipe_into_slice_uninit.rs +++ /dev/null @@ -1,41 +0,0 @@ -#![no_main] - -use core::mem::MaybeUninit; -use either::{Left, Right}; -use libfuzzer_sys::fuzz_target; -use ufotofu::sync::producer::{pipe_into_slice_uninit, TestProducer}; - -fuzz_target!(|data: (TestProducer, usize)| { - let (mut producer, length) = data; - - let clamped_length = length.clamp(0, 512); - - let mut v: Vec = vec![0; clamped_length]; - - let producer_data = producer.peek_slice().to_vec(); - - let producer_data_maybe_uninit = - unsafe { &mut *(&mut v[0..clamped_length] as *mut [u16] as *mut [MaybeUninit]) }; - - match pipe_into_slice_uninit(producer_data_maybe_uninit, &mut producer) { - Ok(_) => { - // Were the bytes successfully piped? - - // refactor as assert_eq - if producer_data[0..clamped_length] != v[0..clamped_length] { - panic!("Bytes piped into slice did not match!") - } - } - Err(err) => { - // let producer_data = producer.peek_slice(); - - // If the filled property is not equal to the inner slice, panic. - // assertion macro - if err.filled != producer_data { - panic!("Filled was not the same as the producer slice.") - } - - // Do we need to check if the error produced was the right kind? e.g. by inspecting the producer's termination field? - } - } -}); diff --git a/fuzz/fuzz_targets/sync/scramble_consumer.rs b/fuzz/fuzz_targets/sync/scramble_consumer.rs deleted file mode 100644 index eb6b9bd..0000000 --- a/fuzz/fuzz_targets/sync/scramble_consumer.rs +++ /dev/null @@ -1,71 +0,0 @@ -#![no_main] -#![feature(never_type)] - -use libfuzzer_sys::fuzz_target; -use libfuzzer_sys::{arbitrary, arbitrary::Arbitrary}; - -use core::cmp::min; - -use wrapper::Wrapper; - -use ufotofu::sync::consumer::{ConsumeOperations, IntoVec, Scramble}; -use ufotofu::sync::producer::SliceProducer; -use ufotofu::sync::{self, BufferedConsumer}; - -fn data_is_invalid(data: &TestData) -> bool { - if data.outer_capacity < 1 || data.outer_capacity > 2048 { - return true; - } - - if data.inner_capacity < 1 || data.inner_capacity > 2048 { - return true; - } - - false -} - -#[derive(Debug, Clone, Arbitrary)] -struct TestData { - producer_buffer: Box<[u8]>, - outer_operations: ConsumeOperations, - inner_operations: ConsumeOperations, - outer_capacity: usize, - inner_capacity: usize, -} - -fuzz_target!(|data: TestData| { - if data_is_invalid(&data) { - return; - } - - let TestData { - producer_buffer, - outer_operations, - inner_operations, - outer_capacity, - inner_capacity, - } = data; - - // Consumer. - let into_vec = IntoVec::new(); - - // Producer. - let mut o = SliceProducer::new(&producer_buffer[..]); - - // Scrambler wrapping a scrambler with an inner `into_vec` consumer. - let mut i = Scramble::new( - Scramble::new(into_vec, inner_operations, inner_capacity), - outer_operations, - outer_capacity, - ); - - let _ = sync::bulk_pipe(&mut o, &mut i); - let _ = i.flush(); - - // Access the inner consumer (`into_vec`). - let i = i.into_inner().into_inner(); - - // Compare the contents of the consumer and producer. - let m = min(o.as_ref().len(), i.as_ref().len()); - assert_eq!(&i.as_ref()[..m], &o.as_ref()[..m]); -}); diff --git a/fuzz/fuzz_targets/sync/scramble_producer.rs b/fuzz/fuzz_targets/sync/scramble_producer.rs deleted file mode 100644 index a6949dc..0000000 --- a/fuzz/fuzz_targets/sync/scramble_producer.rs +++ /dev/null @@ -1,71 +0,0 @@ -#![no_main] -#![feature(never_type)] - -use libfuzzer_sys::fuzz_target; -use libfuzzer_sys::{arbitrary, arbitrary::Arbitrary}; - -use core::cmp::min; - -use wrapper::Wrapper; - -use ufotofu::sync::consumer::IntoVec; -use ufotofu::sync::producer::{ProduceOperations, Scramble, SliceProducer}; -use ufotofu::sync::{self, BufferedConsumer}; - -fn data_is_invalid(data: &TestData) -> bool { - if data.outer_capacity < 1 || data.outer_capacity > 2048 { - return true; - } - - if data.inner_capacity < 1 || data.inner_capacity > 2048 { - return true; - } - - false -} - -#[derive(Debug, Clone, Arbitrary)] -struct TestData { - producer_buffer: Box<[u8]>, - outer_operations: ProduceOperations, - inner_operations: ProduceOperations, - outer_capacity: usize, - inner_capacity: usize, -} - -fuzz_target!(|data: TestData| { - if data_is_invalid(&data) { - return; - } - - let TestData { - mut producer_buffer, - outer_operations, - inner_operations, - outer_capacity, - inner_capacity, - } = data; - - // Producer. - let slice_producer = SliceProducer::new(&mut producer_buffer[..]); - - // Consumer. - let mut i = IntoVec::new(); - - // Scrambler wrapping a scrambler with an inner `slice_producer`. - let mut o = Scramble::new( - Scramble::new(slice_producer, inner_operations, inner_capacity), - outer_operations, - outer_capacity, - ); - - let _ = sync::bulk_pipe(&mut o, &mut i); - let _ = i.flush(); - - // Access the inner producer (`slice_producer`). - let o = o.into_inner().into_inner(); - - // Compare the contents of the producer and consumer. - let m = min(o.as_ref().len(), i.as_ref().len()); - assert_eq!(&i.as_ref()[..m], &o.as_ref()[..m]); -}); diff --git a/fuzz/fuzz_targets/sync/slices.rs b/fuzz/fuzz_targets/sync/slices.rs deleted file mode 100644 index 95de472..0000000 --- a/fuzz/fuzz_targets/sync/slices.rs +++ /dev/null @@ -1,94 +0,0 @@ -#![no_main] - -use core::cmp::min; - -use libfuzzer_sys::fuzz_target; -use libfuzzer_sys::{arbitrary, arbitrary::Arbitrary}; - -use ufotofu::sync; -use ufotofu::sync::consumer::SliceConsumer; -use ufotofu::sync::producer::SliceProducer; - -#[derive(Debug, Clone, Arbitrary)] -struct TestData { - input_buf: Box<[u8]>, - output_buf: Box<[u8]>, - input_start: usize, - input_end: usize, - output_start: usize, - output_end: usize, -} - -// Filter out any data conditions which would violate invariants that must be -// upheld when calling our functions. -fn data_is_invalid(data: TestData) -> bool { - if data.input_start > data.input_end { - return true; - } else if data.input_end > data.input_buf.len() { - return true; - } else if data.output_start > data.output_end { - return true; - } else if data.output_end > data.output_buf.len() { - return true; - } else { - false - } -} - -fn fuzz_pipe(mut data: TestData) { - if data_is_invalid(data.clone()) { - return; - } - - let mut o = SliceProducer::new(&data.input_buf[data.input_start..data.input_end]); - let mut i = SliceConsumer::new(&mut data.output_buf[data.output_start..data.output_end]); - - match sync::pipe(&mut o, &mut i) { - Ok(_) => { - if &o.as_ref().len() > &i.as_ref().len() { - panic!() - } - } - Err(_) => { - if &o.as_ref().len() <= &i.as_ref().len() { - panic!() - } - } - } - - let m = min(o.as_ref().len(), i.as_ref().len()); - assert_eq!(&i.as_ref()[..m], &o.as_ref()[..m]); -} - -fn fuzz_bulk_pipe(mut data: TestData) { - if data_is_invalid(data.clone()) { - return; - } - - let mut o = SliceProducer::new(&data.input_buf[data.input_start..data.input_end]); - let mut i = SliceConsumer::new(&mut data.output_buf[data.output_start..data.output_end]); - - match sync::bulk_pipe(&mut o, &mut i) { - Ok(_) => { - if &o.as_ref().len() > &i.as_ref().len() { - panic!() - } - } - Err(_) => { - if &o.as_ref().len() <= &i.as_ref().len() { - panic!() - } - } - } - - let m = min(o.as_ref().len(), i.as_ref().len()); - assert_eq!(&i.as_ref()[..m], &o.as_ref()[..m]); -} - -fuzz_target!(|data_origin: (TestData, TestData)| { - let data = data_origin.0.clone(); - fuzz_pipe(data); - - let data = data_origin.1.clone(); - fuzz_bulk_pipe(data); -}); diff --git a/ufotofu/src/common/consumer/into_vec.rs b/ufotofu/src/common/consumer/into_vec.rs index 1dbba88..0cf47fb 100644 --- a/ufotofu/src/common/consumer/into_vec.rs +++ b/ufotofu/src/common/consumer/into_vec.rs @@ -19,7 +19,7 @@ use crate::local_nb::{ }; use crate::sync::{BufferedConsumer, BulkConsumer, Consumer}; -#[derive(Debug)] +#[derive(Debug, Clone)] /// Collects data and can at any point be converted into a `Vec`. pub struct IntoVec(IntoVecFallible); diff --git a/ufotofu/src/common/consumer/into_vec_fallible.rs b/ufotofu/src/common/consumer/into_vec_fallible.rs index f0a297a..e1c10fc 100644 --- a/ufotofu/src/common/consumer/into_vec_fallible.rs +++ b/ufotofu/src/common/consumer/into_vec_fallible.rs @@ -14,6 +14,7 @@ use wrapper::Wrapper; use crate::common::consumer::Invariant; use crate::sync::{BufferedConsumer, BulkConsumer, Consumer}; +#[derive(Clone)] /// Collects data and can at any point be converted into a `Vec`. Unlike [`IntoVec`](crate::sync::consumer::IntoVec), reports an error instead of panicking when an internal memory allocation fails. pub struct IntoVecFallible_(Invariant>); @@ -58,7 +59,7 @@ invarianted_impl_consumer_sync_and_local_nb!(IntoVecFallible_ Item T invarianted_impl_buffered_consumer_sync_and_local_nb!(IntoVecFallible_); invarianted_impl_bulk_consumer_sync_and_local_nb!(IntoVecFallible_); -#[derive(Debug)] +#[derive(Debug, Clone)] struct IntoVecFallible { v: Vec, consumed: usize, diff --git a/ufotofu/src/common/consumer/test_consumer.rs b/ufotofu/src/common/consumer/test_consumer.rs index 5d8dfab..653f046 100644 --- a/ufotofu/src/common/consumer/test_consumer.rs +++ b/ufotofu/src/common/consumer/test_consumer.rs @@ -19,6 +19,7 @@ use crate::local_nb::{ }; use crate::sync::{BufferedConsumer, BulkConsumer, Consumer}; +#[derive(Clone)] /// If you need to test code that works with arbitrary consumers, use this one. You can choose which error it should emit, when it emits its error, the size of the slices it presents with `expose_slots`, and when to its async functions should yield instead of returning immediately. Beyond manual control, the [`Arbitrary`] implementation lets you test against various consumer behaviours automatically. /// /// Create new [`TestConsumer`](crate::common::consumer::TestConsumer)s either via a [`TestConsumerBuilder`] or via the implementation of [`Arbitrary`]. @@ -148,6 +149,19 @@ impl<'a, Item: Arbitrary<'a>, Final: Arbitrary<'a>, Error: Arbitrary<'a>> Arbitr } } +/// This implementation considers only the consumed items, the consumed final value, and the stored error value. +impl PartialEq + for TestConsumer_ +{ + fn eq(&self, other: &Self) -> bool { + return self.0.as_ref().inner.as_ref() == other.0.as_ref().inner.as_ref() + && self.0.as_ref().fin == other.0.as_ref().fin + && self.0.as_ref().error == other.0.as_ref().error; + } +} + +impl Eq for TestConsumer_ {} + /// A [builder](https://rust-unofficial.github.io/patterns/patterns/creational/builder.html) for [`TestConsumer`](crate::common::consumer::TestConsumer). /// /// ``` @@ -162,7 +176,7 @@ impl<'a, Item: Arbitrary<'a>, Final: Arbitrary<'a>, Error: Arbitrary<'a>> Arbitr /// ``` pub struct TestConsumerBuilder { error: Error, - operations_until_error: usize, + consumptions_until_error: usize, exposed_slot_sizes: Option>, yield_pattern: Option>, } @@ -170,7 +184,7 @@ pub struct TestConsumerBuilder { impl TestConsumerBuilder { /// Create a new [`TestConsumerBuilder`]. /// - /// The resulting consumer will succesfully perform `operations_until_error` many operations (i.e., calls to non-provided consumer trait methods) before emitting the error `error`. + /// The resulting consumer will succesfully receive `consumptions_until_error` many items before emitting the error `error` any further method call. /// /// ``` /// use ufotofu::sync::consumer::*; @@ -179,13 +193,13 @@ impl TestConsumerBuilder { /// let mut con: TestConsumer = TestConsumerBuilder::new(404, 2).build(); /// assert_eq!(Ok(()), con.consume(4)); /// assert_eq!(Ok(()), con.consume(7)); - /// assert_eq!(Err(404), con.consume(99)); // Configured to fail after two operations. + /// assert_eq!(Err(404), con.consume(99)); // Configured to fail after two consumptions. /// assert_eq!(&[4, 7], con.consumed()); /// ``` - pub fn new(error: Error, operations_until_error: usize) -> TestConsumerBuilder { + pub fn new(error: Error, consumptions_until_error: usize) -> TestConsumerBuilder { TestConsumerBuilder { error, - operations_until_error, + consumptions_until_error, exposed_slot_sizes: None, yield_pattern: None, } @@ -254,18 +268,19 @@ impl TestConsumerBuilder { inner: IntoVec::new(), fin: None, error: Some(self.error), - operations_until_error: self.operations_until_error, + consumptions_until_error: self.consumptions_until_error, exposed_slot_sizes: self.exposed_slot_sizes.map(|sizes| (sizes, 0)), yielder: self.yield_pattern.map(TestYielder::new), })) } } +#[derive(Clone)] struct TestConsumer { inner: IntoVec, fin: Option, error: Option, // An option so we can `take` the error to emit it. - operations_until_error: usize, + consumptions_until_error: usize, exposed_slot_sizes: Option<(Box<[NonZeroUsize]>, usize /* current index*/)>, yielder: Option, } @@ -292,10 +307,9 @@ impl TestConsumer { } fn check_error(&mut self) -> Result<(), Error> { - if self.operations_until_error == 0 { + if self.consumptions_until_error == 0 { Err(self.error.take().unwrap()) // Can unwrap because the invariant wrapper panics before unwrapping can be reached. } else { - self.operations_until_error -= 1; Ok(()) } } @@ -314,7 +328,7 @@ impl Debug for TestConsumer Consumer for TestConsumer fn consume(&mut self, item: Self::Item) -> Result<(), Self::Error> { self.check_error()?; - { - Consumer::consume(&mut self.inner, item).unwrap(); - Ok(()) - } // may unwrap because Err + Consumer::consume(&mut self.inner, item).unwrap(); // may unwrap because Err + self.consumptions_until_error -= 1; + Ok(()) } fn close(&mut self, fin: Self::Final) -> Result<(), Self::Error> { self.check_error()?; self.fin = Some(fin); - { - Consumer::close(&mut self.inner, ()).unwrap(); - Ok(()) - } // may unwrap because Err + Consumer::close(&mut self.inner, ()).unwrap(); // may unwrap because Err + Ok(()) } } @@ -350,10 +361,8 @@ impl BufferedConsumer for TestConsumer Result<(), Self::Error> { self.check_error()?; - { - BufferedConsumer::flush(&mut self.inner).unwrap(); - Ok(()) - } // may unwrap because Err + BufferedConsumer::flush(&mut self.inner).unwrap(); // may unwrap because Err + Ok(()) } } @@ -364,34 +373,36 @@ where fn expose_slots(&mut self) -> Result<&mut [Self::Item], Self::Error> { self.check_error()?; - match self.exposed_slot_sizes { - None => return Ok(BulkConsumer::expose_slots(&mut self.inner).unwrap()), // may unwrap because Err + let max_len: usize = match self.exposed_slot_sizes { + None => usize::MAX, Some((ref exposed_slot_sizes, ref mut index)) => { let max_len: usize = exposed_slot_sizes[*index].into(); *index = (*index + 1) % exposed_slot_sizes.len(); + max_len + } + }; - let min_len = min(max_len, 2048); + let min_len = min(max_len, 2048); - while self.inner.remaining_slots() < min_len { - self.inner.make_space_even_if_not_needed(); - } + while self.inner.remaining_slots() < min_len { + self.inner.make_space_even_if_not_needed(); + } - let inner_slots = BulkConsumer::expose_slots(&mut self.inner).unwrap(); // may unwrap because Err - let actual_len = min(inner_slots.len(), max_len); + let inner_slots = BulkConsumer::expose_slots(&mut self.inner).unwrap(); // may unwrap because Err + let actual_len = min( + min(inner_slots.len(), max_len), + self.consumptions_until_error, + ); - Ok(&mut inner_slots[..actual_len]) - } - } + Ok(&mut inner_slots[..actual_len]) } fn consume_slots(&mut self, amount: usize) -> Result<(), Self::Error> { self.check_error()?; - { - BulkConsumer::consume_slots(&mut self.inner, amount).unwrap(); - Ok(()) - } - // may unwrap because Err + BulkConsumer::consume_slots(&mut self.inner, amount).unwrap(); // may unwrap because Err + self.consumptions_until_error -= amount; + Ok(()) } }