lv2rs_atom/
scalar.rs

1//! Scalar (number-like) atoms
2//!
3//! There are several scalar atoms:
4//! * `i32`
5//! * `i64`
6//! * `f32`
7//! * `f64`
8//! * `bool`
9//! * `URID`
10//!
11//! They all have in common that they are statically sized (which is something special among atoms)
12//! and that they can be written in one piece; Once they are initialized, they are completed and
13//! need no further amendments. Therefore, their behaviour is abstracted to another trait,
14//! [`ScalarAtomBody`](trait.ScalarAtomBody.html), which features a standard implementation of
15//! [`AtomBody`](../atom/trait.AtomBody.html) for every type that implements it. Therefore, writing
16//! and reading scalar atoms is pretty straight foreward:
17//!
18//!     extern crate lv2rs_atom as atom;
19//!     extern crate lv2rs_urid as urid;
20//!
21//!     use atom::prelude::*;
22//!     use atom::ports::*;
23//!     use urid::{CachedMap, debug::DebugMap};
24//!     use std::ffi::CStr;
25//!
26//!     pub struct Plugin {
27//!         in_port: AtomInputPort<f32>,
28//!         out_port: AtomOutputPort<f32>,
29//!         urids: CachedMap,
30//!     }
31//!
32//!     impl Plugin {
33//!         /// Simulated `run` method.
34//!         fn run(&mut self) {
35//!             // Writing.
36//!             unsafe { self.out_port.write_atom_body(&42.0f32, &mut self.urids) }.unwrap();
37//!
38//!             // Reading.
39//!             let float = unsafe { self.in_port.get_atom_body(&mut self.urids) }.unwrap();
40//!             assert_eq!(42.0, *float);
41//!         }
42//!     }
43//!
44//!     // Getting a debug URID map.
45//!     let mut debug_map = DebugMap::new();
46//!     let mut urids = unsafe {debug_map.create_cached_map()};
47//!
48//!     // Creating the plugin.
49//!     let mut plugin = Plugin {
50//!         in_port: AtomInputPort::new(),
51//!         out_port: AtomOutputPort::new(),
52//!         urids: urids,
53//!     };
54//!
55//!     // Creating the atom space.
56//!     let mut atom_space = vec![0u8; 256];
57//!     let atom = unsafe { (atom_space.as_mut_ptr() as *mut Atom).as_mut() }.unwrap();
58//!     *(atom.mut_size()) = 256 - 8;
59//!
60//!     // Connecting the ports.
61//!     plugin.in_port.connect_port(atom as &Atom);
62//!     plugin.out_port.connect_port(atom);
63//!
64//!     // Calling `run`.
65//!     plugin.run();
66use crate::atom::*;
67use crate::frame::{WritingFrame, WritingFrameExt};
68use crate::uris;
69use std::ffi::CStr;
70
71/// Abstraction over scalar (number-like) atoms.
72///
73/// See the [module documentation](index.html) for more information.
74pub trait ScalarAtomBody {
75    fn get_uri() -> &'static CStr;
76}
77
78impl<T> AtomBody for T
79where
80    T: 'static + Sized + ScalarAtomBody,
81{
82    type InitializationParameter = Self;
83
84    fn get_uri() -> &'static CStr {
85        T::get_uri()
86    }
87
88    unsafe fn initialize_body<'a, W>(
89        writer: &mut W,
90        parameter: &Self,
91        _urids: &mut urid::CachedMap,
92    ) -> Result<(), ()>
93    where
94        W: WritingFrame<'a> + WritingFrameExt<'a, Self>,
95    {
96        writer.write_sized(parameter)?;
97        Ok(())
98    }
99
100    fn create_ref<'a>(raw_body: &'a [u8]) -> Result<&'a Self, ()> {
101        if raw_body.len() == std::mem::size_of::<Self>() {
102            let ptr = raw_body.as_ptr() as *const Self;
103            Ok(unsafe { ptr.as_ref() }.unwrap())
104        } else {
105            Err(())
106        }
107    }
108}
109
110impl ScalarAtomBody for i32 {
111    fn get_uri() -> &'static CStr {
112        unsafe { CStr::from_bytes_with_nul_unchecked(uris::INT_TYPE_URI) }
113    }
114}
115
116impl ScalarAtomBody for i64 {
117    fn get_uri() -> &'static CStr {
118        unsafe { CStr::from_bytes_with_nul_unchecked(uris::LONG_TYPE_URI) }
119    }
120}
121
122impl ScalarAtomBody for f32 {
123    fn get_uri() -> &'static CStr {
124        unsafe { CStr::from_bytes_with_nul_unchecked(uris::FLOAT_TYPE_URI) }
125    }
126}
127
128impl ScalarAtomBody for f64 {
129    fn get_uri() -> &'static CStr {
130        unsafe { CStr::from_bytes_with_nul_unchecked(uris::DOUBLE_TYPE_URI) }
131    }
132}
133
134pub use urid::URID;
135
136impl ScalarAtomBody for URID {
137    fn get_uri() -> &'static CStr {
138        unsafe { CStr::from_bytes_with_nul_unchecked(uris::URID_TYPE_URI) }
139    }
140}
141
142impl ScalarAtomBody for bool {
143    fn get_uri() -> &'static CStr {
144        unsafe { CStr::from_bytes_with_nul_unchecked(uris::BOOL_TYPE_URI) }
145    }
146}