lv2_atom/
chunk.rs

1//! An atom containing memory of undefined type.
2//!
3//! This contents of this atom is considered as a simple blob of data. It used, for example, by the host to transmit the size of a writable atom port. Since it is so simple, it does not need a reading or writing parameter.
4//!
5//! # Example
6//! ```
7//! use lv2_core::prelude::*;
8//! use lv2_atom::prelude::*;
9//!
10//! #[derive(PortCollection)]
11//! struct MyPorts {
12//!     input: InputPort<AtomPort>,
13//!     output: OutputPort<AtomPort>,
14//! }
15//!
16//! fn run(ports: &mut MyPorts, urids: &AtomURIDCollection) {
17//!     let in_chunk: &[u8] = ports.input.read(urids.chunk, ()).unwrap();
18//!     let mut out_chunk: FramedMutSpace = ports.output.init(urids.chunk, ()).unwrap();
19//!
20//!     out_chunk.write_raw(in_chunk, false).unwrap();
21//! }
22//! ```
23//!
24//! # Specification
25//!
26//! [http://lv2plug.in/ns/ext/atom/atom.html#Chunk](http://lv2plug.in/ns/ext/atom/atom.html#Chunk)
27use crate::space::*;
28use crate::Atom;
29use urid::UriBound;
30
31/// An atom containing memory of undefined type.
32///
33/// [See also the module documentation.](index.html)
34pub struct Chunk;
35
36unsafe impl UriBound for Chunk {
37    const URI: &'static [u8] = sys::LV2_ATOM__Chunk;
38}
39
40impl<'a, 'b> Atom<'a, 'b> for Chunk
41where
42    'a: 'b,
43{
44    type ReadParameter = ();
45    type ReadHandle = &'a [u8];
46    type WriteParameter = ();
47    type WriteHandle = FramedMutSpace<'a, 'b>;
48
49    fn read(space: Space<'a>, _: ()) -> Option<&'a [u8]> {
50        space.data()
51    }
52
53    fn init(frame: FramedMutSpace<'a, 'b>, _: ()) -> Option<FramedMutSpace<'a, 'b>> {
54        Some(frame)
55    }
56}
57
58#[cfg(test)]
59mod tests {
60    use crate::chunk::*;
61    use crate::*;
62    use std::mem::size_of;
63    use urid::*;
64
65    #[test]
66    fn test_chunk_and_slice_writer() {
67        const SLICE_LENGTH: usize = 42;
68
69        let map = HashURIDMapper::new();
70        let urids = crate::AtomURIDCollection::from_map(&map).unwrap();
71
72        let mut raw_space: Box<[u8]> = Box::new([0; 256]);
73
74        // writing
75        {
76            let mut space = RootMutSpace::new(raw_space.as_mut());
77            let mut writer = (&mut space as &mut dyn MutSpace)
78                .init(urids.chunk, ())
79                .unwrap();
80
81            for (i, value) in writer
82                .allocate(SLICE_LENGTH - 1, false)
83                .map(|(_, data)| data)
84                .unwrap()
85                .into_iter()
86                .enumerate()
87            {
88                *value = i as u8;
89            }
90            (&mut writer as &mut dyn MutSpace)
91                .write(&41u8, false)
92                .unwrap();
93        }
94
95        // verifying
96        {
97            let raw_space = raw_space.as_ref();
98            let (atom, data) = raw_space.split_at(size_of::<sys::LV2_Atom>());
99
100            let atom = unsafe { &*(atom.as_ptr() as *const sys::LV2_Atom) };
101            assert_eq!(atom.size as usize, SLICE_LENGTH);
102            assert_eq!(atom.type_, urids.chunk.get());
103
104            let data = data.split_at(SLICE_LENGTH).0;
105            for i in 0..SLICE_LENGTH {
106                assert_eq!(data[i] as usize, i);
107            }
108        }
109
110        // reading
111        {
112            let space = Space::from_reference(raw_space.as_ref());
113
114            let data = Chunk::read(space.split_atom_body(urids.chunk).unwrap().0, ()).unwrap();
115            assert_eq!(data.len(), SLICE_LENGTH);
116
117            for (i, value) in data.iter().enumerate() {
118                assert_eq!(*value as usize, i);
119            }
120        }
121    }
122}