1use crate::space::*;
34use crate::*;
35use urid::*;
36
37pub struct Tuple;
41
42unsafe impl UriBound for Tuple {
43 const URI: &'static [u8] = sys::LV2_ATOM__Tuple;
44}
45
46impl<'a, 'b> Atom<'a, 'b> for Tuple
47where
48 'a: 'b,
49{
50 type ReadParameter = ();
51 type ReadHandle = TupleIterator<'a>;
52 type WriteParameter = ();
53 type WriteHandle = TupleWriter<'a, 'b>;
54
55 fn read(body: Space<'a>, _: ()) -> Option<TupleIterator<'a>> {
56 Some(TupleIterator { space: body })
57 }
58
59 fn init(frame: FramedMutSpace<'a, 'b>, _: ()) -> Option<TupleWriter<'a, 'b>> {
60 Some(TupleWriter { frame })
61 }
62}
63
64pub struct TupleIterator<'a> {
68 space: Space<'a>,
69}
70
71impl<'a> Iterator for TupleIterator<'a> {
72 type Item = UnidentifiedAtom<'a>;
73
74 fn next(&mut self) -> Option<UnidentifiedAtom<'a>> {
75 let (atom, space) = self.space.split_atom()?;
76 self.space = space;
77 Some(UnidentifiedAtom::new(atom))
78 }
79}
80
81pub struct TupleWriter<'a, 'b> {
83 frame: FramedMutSpace<'a, 'b>,
84}
85
86impl<'a, 'b> TupleWriter<'a, 'b> {
87 pub fn init<'c, A: Atom<'a, 'c>>(
89 &'c mut self,
90 child_urid: URID<A>,
91 child_parameter: A::WriteParameter,
92 ) -> Option<A::WriteHandle> {
93 (&mut self.frame as &mut dyn MutSpace).init(child_urid, child_parameter)
94 }
95}
96
97#[cfg(test)]
98mod tests {
99 use crate::prelude::*;
100 use crate::space::*;
101 use std::mem::size_of;
102 use urid::*;
103
104 #[test]
105 fn test_tuple() {
106 let map = HashURIDMapper::new();
107 let urids = crate::AtomURIDCollection::from_map(&map).unwrap();
108
109 let mut raw_space: Box<[u8]> = Box::new([0; 256]);
110
111 {
113 let mut space = RootMutSpace::new(raw_space.as_mut());
114 let mut writer = (&mut space as &mut dyn MutSpace)
115 .init(urids.tuple, ())
116 .unwrap();
117 {
118 let mut vector_writer =
119 writer.init::<Vector<Int>>(urids.vector, urids.int).unwrap();
120 vector_writer.append(&[17; 9]).unwrap();
121 }
122 writer.init::<Int>(urids.int, 42).unwrap();
123 }
124
125 {
127 let (atom, space) = raw_space.split_at(size_of::<sys::LV2_Atom>());
128 let atom = unsafe { &*(atom.as_ptr() as *const sys::LV2_Atom) };
129 assert_eq!(atom.type_, urids.tuple);
130 assert_eq!(
131 atom.size as usize,
132 size_of::<sys::LV2_Atom_Vector>()
133 + size_of::<i32>() * 9
134 + 4
135 + size_of::<sys::LV2_Atom_Int>()
136 );
137
138 let (vector, space) = space.split_at(size_of::<sys::LV2_Atom_Vector>());
139 let vector = unsafe { &*(vector.as_ptr() as *const sys::LV2_Atom_Vector) };
140 assert_eq!(vector.atom.type_, urids.vector);
141 assert_eq!(
142 vector.atom.size as usize,
143 size_of::<sys::LV2_Atom_Vector_Body>() + size_of::<i32>() * 9
144 );
145 assert_eq!(vector.body.child_size as usize, size_of::<i32>());
146 assert_eq!(vector.body.child_type, urids.int);
147
148 let (vector_items, space) = space.split_at(size_of::<i32>() * 9);
149 let vector_items =
150 unsafe { std::slice::from_raw_parts(vector_items.as_ptr() as *const i32, 9) };
151 assert_eq!(vector_items, &[17; 9]);
152 let (_, space) = space.split_at(4);
153
154 let (int, _) = space.split_at(size_of::<sys::LV2_Atom_Int>());
155 let int = unsafe { &*(int.as_ptr() as *const sys::LV2_Atom_Int) };
156 assert_eq!(int.atom.type_, urids.int);
157 assert_eq!(int.atom.size as usize, size_of::<i32>());
158 assert_eq!(int.body, 42);
159 }
160
161 {
163 let space = Space::from_slice(raw_space.as_ref());
164 let (body, _) = space.split_atom_body(urids.tuple).unwrap();
165 let items: Vec<UnidentifiedAtom> = Tuple::read(body, ()).unwrap().collect();
166 assert_eq!(items[0].read(urids.vector, urids.int).unwrap(), [17; 9]);
167 assert_eq!(items[1].read(urids.int, ()).unwrap(), 42);
168 }
169 }
170}