lv2rs_atom/
vector.rs

1//! Homogenous array of sized atoms.
2//!
3//! A [vector](type.Vector.html) is the LV2 equivalent of a slice: It has a variable length, but it
4//! does only contain one type of item, which has to be sized.
5//!
6//! When initialized, a vector does not contain any items. These items have to be pushed or appended
7//! to the vector using the [`VectorWritingFrame`](trait.VectorWritingFrame.html) trait. Every
8//! writing frame implements this trait via a blanket implementation and the trait is included in
9//! the crate's prelude. You can, therefore, act as if the extended methods were normal methods of a
10//! writing frame.
11//!
12//! Reading the vector is done using these methods:
13//! * [`child_body_size`](type.Vector.html#method.child_body_size)
14//! * [`child_body_type`](type.Vector.html#method.child_body_type)
15//! * [`as_slice`](type.Vector.html#method.as_slice)
16//!
17//! An example:
18//!
19//!     extern crate lv2rs_atom as atom;
20//!     extern crate lv2rs_urid as urid;
21//!
22//!     use atom::prelude::*;
23//!     use atom::ports::*;
24//!     use urid::{CachedMap, debug::DebugMap};
25//!     use std::ffi::CStr;
26//!
27//!     pub struct Plugin {
28//!         in_port: AtomInputPort<Vector<f32>>,
29//!         out_port: AtomOutputPort<Vector<f32>>,
30//!         urids: CachedMap,
31//!     }
32//!
33//!     impl Plugin {
34//!         /// Simulated `run` method.
35//!         fn run(&mut self) {
36//!             // Writing
37//!             {
38//!                 let mut frame =
39//!                     unsafe { self.out_port.write_atom_body(&(), &mut self.urids) }.unwrap();
40//!                 frame.push(0.0).unwrap();
41//!                 frame.append(&[1.0, 2.0, 3.0, 4.0]).unwrap();
42//!             }
43//!
44//!             // Reading.
45//!             let vector = unsafe { self.in_port.get_atom_body(&mut self.urids) }.unwrap();
46//!             assert_eq!([0.0, 1.0, 2.0, 3.0, 4.0], vector.as_slice());
47//!         }
48//!     }
49//!
50//!     // Getting a debug URID map.
51//!     let mut debug_map = DebugMap::new();
52//!     let mut urids = unsafe {debug_map.create_cached_map()};
53//!
54//!     // Creating the plugin.
55//!     let mut plugin = Plugin {
56//!         in_port: AtomInputPort::new(),
57//!         out_port: AtomOutputPort::new(),
58//!         urids: urids,
59//!     };
60//!
61//!     // Creating the atom space.
62//!     let mut atom_space = vec![0u8; 256];
63//!     let atom = unsafe { (atom_space.as_mut_ptr() as *mut Atom).as_mut() }.unwrap();
64//!     *(atom.mut_size()) = 256 - 8;
65//!
66//!     // Connecting the ports.
67//!     plugin.in_port.connect_port(atom as &Atom);
68//!     plugin.out_port.connect_port(atom);
69//!
70//!     // Calling `run`.
71//!     plugin.run();
72use crate::atom::{array::*, *};
73use crate::frame::{WritingFrame, WritingFrameExt};
74use crate::uris;
75use std::ffi::CStr;
76use std::mem::size_of;
77use std::os::raw::*;
78use urid::URID;
79
80/// The body header of a vector.
81///
82/// It contains the size of the child type (which has to be static) and the child type itself.
83/// This struct is also `repr(C)` and is used to interpret raw atom data.
84#[repr(C)]
85pub struct VectorHeader {
86    pub child_size: c_uint,
87    pub child_type: c_uint,
88}
89
90/// A homogenous array of sized atoms.
91///
92/// See the [module documentation](index.html) for more information.
93pub type Vector<T> = ArrayAtomBody<VectorHeader, T>;
94
95impl ArrayAtomHeader for VectorHeader {
96    type InitializationParameter = URID;
97
98    unsafe fn initialize<'a, W, T>(
99        writer: &mut W,
100        child_type: &URID,
101        _urids: &mut urid::CachedMap,
102    ) -> Result<(), ()>
103    where
104        T: 'static + Sized + Copy,
105        ArrayAtomBody<Self, T>: AtomBody,
106        W: WritingFrame<'a> + WritingFrameExt<'a, ArrayAtomBody<Self, T>>,
107    {
108        let header = VectorHeader {
109            child_size: size_of::<T>() as u32,
110            child_type: *child_type,
111        };
112        writer.write_sized(&header)?;
113        Ok(())
114    }
115}
116
117impl<T> AtomBody for Vector<T>
118where
119    T: 'static + AtomBody + Sized + Copy,
120{
121    type InitializationParameter = ();
122
123    fn get_uri() -> &'static CStr {
124        unsafe { CStr::from_bytes_with_nul_unchecked(uris::VECTOR_TYPE_URI) }
125    }
126
127    unsafe fn initialize_body<'a, W>(
128        writer: &mut W,
129        _: &(),
130        urids: &mut urid::CachedMap,
131    ) -> Result<(), ()>
132    where
133        W: WritingFrame<'a> + WritingFrameExt<'a, Self>,
134    {
135        Self::__initialize_body(writer, &urids.map(T::get_uri()), urids)
136    }
137
138    fn create_ref<'a>(raw_data: &'a [u8]) -> Result<&'a Self, ()> {
139        Self::__create_ref(raw_data)
140    }
141}
142
143impl<T> Vector<T>
144where
145    T: 'static + AtomBody + Sized + Copy,
146{
147    /// Return the size of the child type, according to the vector's body header.
148    pub fn child_body_size(&self) -> usize {
149        self.header.child_size as usize
150    }
151
152    /// Return the type of the child, according to the vector's body header.
153    pub fn child_body_type(&self) -> URID {
154        self.header.child_type
155    }
156
157    /// Return a slice containing all items in the vector.
158    ///
159    /// No allocation is done; This method simply borrows the data of the vector.
160    pub fn as_slice(&self) -> &[T] {
161        &self.data
162    }
163}
164
165/// Extension for [`WritingFrame`](../frame/trait.WritingFrame.html) and
166/// [`WritingFrameExt`](../frame/trait.WritingFrameExt.html) for vectors.
167///
168/// See the [module documentation](index.html) for more information.
169pub trait VectorWritingFrame<'a, T>
170where
171    T: 'static + AtomBody + Sized + Copy,
172    Self: WritingFrame<'a> + WritingFrameExt<'a, Vector<T>>,
173{
174    /// Push a value to the end of the vector.
175    fn push(&mut self, value: T) -> Result<(), ()> {
176        unsafe { Vector::<T>::push(self, value) }
177    }
178
179    /// Append a slice of values to the end of the vector.
180    fn append(&mut self, slice: &[T]) -> Result<(), ()> {
181        unsafe { Vector::<T>::append(self, slice) }
182    }
183}
184
185impl<'a, T, F> VectorWritingFrame<'a, T> for F
186where
187    T: 'static + AtomBody + Sized + Copy,
188    F: WritingFrame<'a> + WritingFrameExt<'a, Vector<T>>,
189{
190}