use crate::space::*;
use crate::*;
use urid::*;
pub struct Tuple;
unsafe impl UriBound for Tuple {
const URI: &'static [u8] = sys::LV2_ATOM__Tuple;
}
impl<'a, 'b> Atom<'a, 'b> for Tuple
where
'a: 'b,
{
type ReadParameter = ();
type ReadHandle = TupleIterator<'a>;
type WriteParameter = ();
type WriteHandle = TupleWriter<'a, 'b>;
fn read(body: Space<'a>, _: ()) -> Option<TupleIterator<'a>> {
Some(TupleIterator { space: body })
}
fn init(frame: FramedMutSpace<'a, 'b>, _: ()) -> Option<TupleWriter<'a, 'b>> {
Some(TupleWriter { frame })
}
}
pub struct TupleIterator<'a> {
space: Space<'a>,
}
impl<'a> Iterator for TupleIterator<'a> {
type Item = UnidentifiedAtom<'a>;
fn next(&mut self) -> Option<UnidentifiedAtom<'a>> {
let (atom, space) = self.space.split_atom()?;
self.space = space;
Some(UnidentifiedAtom::new(atom))
}
}
pub struct TupleWriter<'a, 'b> {
frame: FramedMutSpace<'a, 'b>,
}
impl<'a, 'b> TupleWriter<'a, 'b> {
pub fn init<'c, A: Atom<'a, 'c>>(
&'c mut self,
child_urid: URID<A>,
child_parameter: A::WriteParameter,
) -> Option<A::WriteHandle> {
(&mut self.frame as &mut dyn MutSpace).init(child_urid, child_parameter)
}
}
#[cfg(test)]
mod tests {
use crate::prelude::*;
use crate::space::*;
use std::mem::size_of;
use urid::*;
#[test]
fn test_tuple() {
let map = HashURIDMapper::new();
let urids = crate::AtomURIDCollection::from_map(&map).unwrap();
let mut raw_space: Box<[u8]> = Box::new([0; 256]);
{
let mut space = RootMutSpace::new(raw_space.as_mut());
let mut writer = (&mut space as &mut dyn MutSpace)
.init(urids.tuple, ())
.unwrap();
{
let mut vector_writer =
writer.init::<Vector<Int>>(urids.vector, urids.int).unwrap();
vector_writer.append(&[17; 9]).unwrap();
}
writer.init::<Int>(urids.int, 42).unwrap();
}
{
let (atom, space) = raw_space.split_at(size_of::<sys::LV2_Atom>());
let atom = unsafe { &*(atom.as_ptr() as *const sys::LV2_Atom) };
assert_eq!(atom.type_, urids.tuple);
assert_eq!(
atom.size as usize,
size_of::<sys::LV2_Atom_Vector>()
+ size_of::<i32>() * 9
+ 4
+ size_of::<sys::LV2_Atom_Int>()
);
let (vector, space) = space.split_at(size_of::<sys::LV2_Atom_Vector>());
let vector = unsafe { &*(vector.as_ptr() as *const sys::LV2_Atom_Vector) };
assert_eq!(vector.atom.type_, urids.vector);
assert_eq!(
vector.atom.size as usize,
size_of::<sys::LV2_Atom_Vector_Body>() + size_of::<i32>() * 9
);
assert_eq!(vector.body.child_size as usize, size_of::<i32>());
assert_eq!(vector.body.child_type, urids.int);
let (vector_items, space) = space.split_at(size_of::<i32>() * 9);
let vector_items =
unsafe { std::slice::from_raw_parts(vector_items.as_ptr() as *const i32, 9) };
assert_eq!(vector_items, &[17; 9]);
let (_, space) = space.split_at(4);
let (int, _) = space.split_at(size_of::<sys::LV2_Atom_Int>());
let int = unsafe { &*(int.as_ptr() as *const sys::LV2_Atom_Int) };
assert_eq!(int.atom.type_, urids.int);
assert_eq!(int.atom.size as usize, size_of::<i32>());
assert_eq!(int.body, 42);
}
{
let space = Space::from_slice(raw_space.as_ref());
let (body, _) = space.split_atom_body(urids.tuple).unwrap();
let items: Vec<UnidentifiedAtom> = Tuple::read(body, ()).unwrap().collect();
assert_eq!(items[0].read(urids.vector, urids.int).unwrap(), [17; 9]);
assert_eq!(items[1].read(urids.int, ()).unwrap(), 42);
}
}
}