1use crate::scalar::ScalarAtom;
34use crate::space::*;
35use crate::*;
36use std::marker::PhantomData;
37use std::mem::size_of;
38use urid::*;
39
40pub struct Vector<C: ScalarAtom> {
44 child: PhantomData<C>,
45}
46
47unsafe impl<C: ScalarAtom> UriBound for Vector<C> {
48 const URI: &'static [u8] = sys::LV2_ATOM__Vector;
49}
50
51impl<'a, 'b, C: ScalarAtom> Atom<'a, 'b> for Vector<C>
52where
53 'a: 'b,
54 C: 'b,
55{
56 type ReadParameter = URID<C>;
57 type ReadHandle = &'a [C::InternalType];
58 type WriteParameter = URID<C>;
59 type WriteHandle = VectorWriter<'a, 'b, C>;
60
61 fn read(body: Space<'a>, child_urid: URID<C>) -> Option<&'a [C::InternalType]> {
62 let (header, body) = body.split_type::<sys::LV2_Atom_Vector_Body>()?;
63
64 if header.child_type != child_urid
65 || header.child_size as usize != size_of::<C::InternalType>()
66 {
67 return None;
68 }
69
70 let data = body.data()?;
71
72 assert_eq!(data.len() % size_of::<C::InternalType>(), 0);
73 let children_count = data.len() / size_of::<C::InternalType>();
74
75 let children = unsafe {
76 std::slice::from_raw_parts(data.as_ptr() as *const C::InternalType, children_count)
77 };
78 Some(children)
79 }
80
81 fn init(
82 mut frame: FramedMutSpace<'a, 'b>,
83 child_urid: URID<C>,
84 ) -> Option<VectorWriter<'a, 'b, C>> {
85 let body = sys::LV2_Atom_Vector_Body {
86 child_type: child_urid.get(),
87 child_size: size_of::<C::InternalType>() as u32,
88 };
89 (&mut frame as &mut dyn MutSpace).write(&body, false)?;
90
91 Some(VectorWriter {
92 frame,
93 type_: PhantomData,
94 })
95 }
96}
97
98pub struct VectorWriter<'a, 'b, A: ScalarAtom> {
102 frame: FramedMutSpace<'a, 'b>,
103 type_: PhantomData<A>,
104}
105
106impl<'a, 'b, A: ScalarAtom> VectorWriter<'a, 'b, A> {
107 pub fn push(&mut self, child: A::InternalType) -> Option<&mut A::InternalType> {
109 (&mut self.frame as &mut dyn MutSpace).write(&child, false)
110 }
111
112 pub fn allocate(&mut self, size: usize) -> Option<&mut [A::InternalType]> {
116 self.frame
117 .allocate(size_of::<A::InternalType>() * size, false)
118 .map(|(_, data)| unsafe {
119 std::slice::from_raw_parts_mut(data.as_mut_ptr() as *mut A::InternalType, size)
120 })
121 }
122
123 pub fn append(&mut self, data: &[A::InternalType]) -> Option<&mut [A::InternalType]> {
125 let raw_data = unsafe {
126 std::slice::from_raw_parts(data.as_ptr() as *const u8, std::mem::size_of_val(data))
127 };
128 self.frame
129 .allocate(raw_data.len(), false)
130 .map(|(_, space)| unsafe {
131 space.copy_from_slice(raw_data);
132 std::slice::from_raw_parts_mut(
133 space.as_mut_ptr() as *mut A::InternalType,
134 data.len(),
135 )
136 })
137 }
138}
139
140#[cfg(test)]
141mod tests {
142 use crate::prelude::*;
143 use crate::space::*;
144 use std::mem::size_of;
145 use urid::*;
146
147 #[test]
148 fn test_vector() {
149 const CHILD_COUNT: usize = 17;
150
151 let map = HashURIDMapper::new();
152 let urids = crate::AtomURIDCollection::from_map(&map).unwrap();
153
154 let mut raw_space: Box<[u8]> = Box::new([0; 256]);
155
156 {
158 let mut space = RootMutSpace::new(raw_space.as_mut());
159 let mut writer = (&mut space as &mut dyn MutSpace)
160 .init(urids.vector(), urids.int)
161 .unwrap();
162 writer.append(&[42; CHILD_COUNT - 1]);
163 writer.push(1);
164 }
165
166 {
168 let (vector, children) = raw_space.split_at(size_of::<sys::LV2_Atom_Vector>());
169
170 let vector = unsafe { &*(vector.as_ptr() as *const sys::LV2_Atom_Vector) };
171 assert_eq!(vector.atom.type_, urids.vector.get());
172 assert_eq!(
173 vector.atom.size as usize,
174 size_of::<sys::LV2_Atom_Vector_Body>() + size_of::<i32>() * CHILD_COUNT
175 );
176 assert_eq!(vector.body.child_size as usize, size_of::<i32>());
177 assert_eq!(vector.body.child_type, urids.int.get());
178
179 let children =
180 unsafe { std::slice::from_raw_parts(children.as_ptr() as *const i32, CHILD_COUNT) };
181 for value in &children[0..children.len() - 1] {
182 assert_eq!(*value, 42);
183 }
184 assert_eq!(children[children.len() - 1], 1);
185 }
186
187 {
189 let space = Space::from_slice(raw_space.as_ref());
190 let (body, _) = space.split_atom_body(urids.vector).unwrap();
191 let children: &[i32] = Vector::<Int>::read(body, urids.int).unwrap();
192
193 assert_eq!(children.len(), CHILD_COUNT);
194 for i in 0..children.len() - 1 {
195 assert_eq!(children[i], 42);
196 }
197 assert_eq!(children[children.len() - 1], 1);
198 }
199 }
200}