diff --git a/examples/gain/src/lib.rs b/examples/gain/src/lib.rs index 3f1a49e..4a92466 100644 --- a/examples/gain/src/lib.rs +++ b/examples/gain/src/lib.rs @@ -115,8 +115,8 @@ impl Processor for GainProcessor { fn reset(&mut self) {} fn process(&mut self, buffers: Buffers, events: Events) { - let mut buffer = buffers.collect::().unwrap(); - for (mut buffer, events) in buffer.split_at_events(events) { + let mut buffers: (BufferMut,) = buffers.try_into().unwrap(); + for (mut buffer, events) in buffers.0.split_at_events(events) { for event in events { if let Data::ParamChange { id, value } = event.data { self.params.set_param(id, value); diff --git a/src/buffers.rs b/src/buffers.rs index c1206b5..24f207c 100644 --- a/src/buffers.rs +++ b/src/buffers.rs @@ -1,12 +1,11 @@ use std::marker::PhantomData; use std::ops::{Index, IndexMut, Range}; -use std::{array, slice}; +use std::slice; -pub mod collect; +pub mod convert; pub mod iter; use crate::events::Events; -use collect::FromBuffers; use iter::{BlockIterator, IntoBlocks, IntoSamples}; #[derive(Copy, Clone, Eq, PartialEq)] @@ -108,19 +107,6 @@ impl<'a, 'b> Buffers<'a, 'b> { } } - #[inline] - pub fn collect>(self) -> Option { - let mut iter = self.into_iter(); - - let result = B::from_buffers(&mut iter)?; - - if iter.next().is_none() { - Some(result) - } else { - None - } - } - #[inline] pub fn slice(&mut self, range: Range) -> Option { if range.start > range.end || range.end > self.len { @@ -335,17 +321,6 @@ impl<'a, 'b> Buffer<'a, 'b> { self.ptrs.len() } - #[inline] - pub fn collect(self) -> Option<[&'b [f32]; N]> { - if self.channel_count() != N { - return None; - } - - Some(array::from_fn(|i| unsafe { - slice::from_raw_parts(self.ptrs[i].offset(self.offset), self.len) - })) - } - #[inline] pub fn samples(&self) -> iter::SampleIter<'a, 'b> { self.into_samples() @@ -515,17 +490,6 @@ impl<'a, 'b> BufferMut<'a, 'b> { } } - #[inline] - pub fn collect(self) -> Option<[&'b mut [f32]; N]> { - if self.channel_count() != N { - return None; - } - - Some(array::from_fn(|i| unsafe { - slice::from_raw_parts_mut(self.ptrs[i].offset(self.offset), self.len) - })) - } - #[inline] pub fn samples<'c>(&'c mut self) -> iter::SampleIterMut<'a, 'c> { self.reborrow().into_samples() diff --git a/src/buffers/collect.rs b/src/buffers/collect.rs deleted file mode 100644 index 7a60424..0000000 --- a/src/buffers/collect.rs +++ /dev/null @@ -1,106 +0,0 @@ -use std::array; - -use super::{AnyBuffer, Buffer, BufferMut}; - -pub trait FromBuffers<'a, 'b>: Sized { - fn from_buffers(buffers: &mut I) -> Option - where - I: Iterator>; -} - -impl<'a, 'b> FromBuffers<'a, 'b> for Buffer<'a, 'b> { - #[inline] - fn from_buffers(buffers: &mut I) -> Option - where - I: Iterator>, - { - match buffers.next()? { - AnyBuffer::Const(buffer) => Some(buffer), - _ => None, - } - } -} - -impl<'a, 'b, const N: usize> FromBuffers<'a, 'b> for [&'b [f32]; N] { - #[inline] - fn from_buffers(buffers: &mut I) -> Option - where - I: Iterator>, - { - Buffer::from_buffers(buffers)?.collect() - } -} - -impl<'a, 'b> FromBuffers<'a, 'b> for BufferMut<'a, 'b> { - #[inline] - fn from_buffers(buffers: &mut I) -> Option - where - I: Iterator>, - { - match buffers.next()? { - AnyBuffer::Mut(buffer) => Some(buffer), - _ => None, - } - } -} - -impl<'a, 'b, const N: usize> FromBuffers<'a, 'b> for [&'b mut [f32]; N] { - #[inline] - fn from_buffers(buffers: &mut I) -> Option - where - I: Iterator>, - { - BufferMut::from_buffers(buffers)?.collect() - } -} - -macro_rules! from_buffers { - ($($buffer:ident),*) => { - impl<'a, 'b, $($buffer),*> FromBuffers<'a, 'b> for ($($buffer,)*) - where - $($buffer: FromBuffers<'a, 'b>),* - { - #[inline] - fn from_buffers(buffers: &mut I) -> Option - where - I: Iterator>, - { - Some(( - $( - $buffer::from_buffers(buffers)?, - )* - )) - } - } - } -} - -from_buffers!(B0); -from_buffers!(B0, B1); -from_buffers!(B0, B1, B2); -from_buffers!(B0, B1, B2, B3); -from_buffers!(B0, B1, B2, B3, B4); -from_buffers!(B0, B1, B2, B3, B4, B5); -from_buffers!(B0, B1, B2, B3, B4, B5, B6); -from_buffers!(B0, B1, B2, B3, B4, B5, B6, B7); -from_buffers!(B0, B1, B2, B3, B4, B5, B6, B7, B8); -from_buffers!(B0, B1, B2, B3, B4, B5, B6, B7, B8, B9); - -impl<'a, 'b, const N: usize, B> FromBuffers<'a, 'b> for [B; N] -where - B: FromBuffers<'a, 'b>, -{ - #[inline] - fn from_buffers(buffers: &mut I) -> Option - where - I: Iterator>, - { - let mut results = array::from_fn(|_| None); - - for result in results.iter_mut() { - *result = Some(B::from_buffers(buffers)?); - } - - Some(results.map(|result| result.unwrap())) - } -} diff --git a/src/buffers/convert.rs b/src/buffers/convert.rs new file mode 100644 index 0000000..1dcb59d --- /dev/null +++ b/src/buffers/convert.rs @@ -0,0 +1,110 @@ +use std::error::Error; +use std::{array, fmt, slice}; + +use super::{AnyBuffer, Buffer, BufferMut, Buffers}; + +impl<'a, 'b> TryFrom> for Buffer<'a, 'b> { + type Error = AnyBuffer<'a, 'b>; + + #[inline] + fn try_from(value: AnyBuffer<'a, 'b>) -> Result, Self::Error> { + match value { + AnyBuffer::Const(buffer) => Ok(buffer), + _ => Err(value), + } + } +} + +impl<'a, 'b> TryFrom> for BufferMut<'a, 'b> { + type Error = AnyBuffer<'a, 'b>; + + #[inline] + fn try_from(value: AnyBuffer<'a, 'b>) -> Result, Self::Error> { + match value { + AnyBuffer::Mut(buffer) => Ok(buffer), + _ => Err(value), + } + } +} + +impl<'a, 'b, const N: usize> TryFrom> for [&'b [f32]; N] { + type Error = Buffer<'a, 'b>; + + #[inline] + fn try_from(value: Buffer<'a, 'b>) -> Result<[&'b [f32]; N], Self::Error> { + if value.channel_count() == N { + Ok(array::from_fn(|i| unsafe { + slice::from_raw_parts(value.ptrs[i].offset(value.offset), value.len) + })) + } else { + Err(value) + } + } +} + +impl<'a, 'b, const N: usize> TryFrom> for [&'b mut [f32]; N] { + type Error = BufferMut<'a, 'b>; + + #[inline] + fn try_from(value: BufferMut<'a, 'b>) -> Result<[&'b mut [f32]; N], Self::Error> { + if value.channel_count() == N { + Ok(array::from_fn(|i| unsafe { + slice::from_raw_parts_mut(value.ptrs[i].offset(value.offset), value.len) + })) + } else { + Err(value) + } + } +} + +#[derive(Debug)] +pub struct TryFromBuffersError; + +impl fmt::Display for TryFromBuffersError { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + "buffer layout does not match".fmt(fmt) + } +} + +impl Error for TryFromBuffersError {} + +macro_rules! try_from_buffers { + ($($buffer:ident),*) => { + impl<'a, 'b, $($buffer),*> TryFrom> for ($($buffer,)*) + where + $($buffer: TryFrom>),* + { + type Error = TryFromBuffersError; + + #[inline] + fn try_from(value: Buffers<'a, 'b>) -> Result { + let mut iter = value.into_iter(); + + let result = ( + $({ + let next = iter.next().ok_or(TryFromBuffersError)?; + $buffer::try_from(next).map_err(|_| TryFromBuffersError)? + },)* + ); + + if iter.next().is_none() { + Ok(result) + } else { + Err(TryFromBuffersError) + } + } + } + } +} + +try_from_buffers!(); +try_from_buffers!(B0); +try_from_buffers!(B0, B1); +try_from_buffers!(B0, B1, B2); +try_from_buffers!(B0, B1, B2, B3); +try_from_buffers!(B0, B1, B2, B3, B4); +try_from_buffers!(B0, B1, B2, B3, B4, B5); +try_from_buffers!(B0, B1, B2, B3, B4, B5, B6); +try_from_buffers!(B0, B1, B2, B3, B4, B5, B6, B7); +try_from_buffers!(B0, B1, B2, B3, B4, B5, B6, B7, B8); +try_from_buffers!(B0, B1, B2, B3, B4, B5, B6, B7, B8, B9);