1use crate::space::*;
34use crate::*;
35use std::marker::Unpin;
36use urid::UriBound;
37use urid::URID;
38
39pub trait ScalarAtom: UriBound {
43 type InternalType: Unpin + Copy + Send + Sync + Sized + 'static;
47
48 fn read_scalar(body: Space) -> Option<Self::InternalType> {
52 body.split_type::<Self::InternalType>()
53 .map(|(value, _)| *value)
54 }
55
56 fn write_scalar<'a, 'b>(
60 mut frame: FramedMutSpace<'a, 'b>,
61 value: Self::InternalType,
62 ) -> Option<&'a mut Self::InternalType> {
63 (&mut frame as &mut dyn MutSpace).write(&value, true)
64 }
65}
66
67impl<'a, 'b, A: ScalarAtom> Atom<'a, 'b> for A
68where
69 'a: 'b,
70{
71 type ReadParameter = ();
72 type ReadHandle = A::InternalType;
73 type WriteParameter = A::InternalType;
74 type WriteHandle = &'a mut A::InternalType;
75
76 fn read(body: Space<'a>, _: ()) -> Option<A::InternalType> {
77 <A as ScalarAtom>::read_scalar(body)
78 }
79
80 fn init(
81 frame: FramedMutSpace<'a, 'b>,
82 value: A::InternalType,
83 ) -> Option<&'a mut A::InternalType> {
84 <A as ScalarAtom>::write_scalar(frame, value)
85 }
86}
87
88macro_rules! make_scalar_atom {
90 ($atom:ty, $internal:ty, $uri:expr, $urid:expr) => {
91 unsafe impl UriBound for $atom {
92 const URI: &'static [u8] = $uri;
93 }
94
95 impl ScalarAtom for $atom {
96 type InternalType = $internal;
97 }
98 };
99}
100
101pub struct Double;
103
104make_scalar_atom!(
105 Double,
106 f64,
107 sys::LV2_ATOM__Double,
108 |urids: &AtomURIDCollection| urids.double
109);
110
111pub struct Float;
113
114make_scalar_atom!(
115 Float,
116 f32,
117 sys::LV2_ATOM__Float,
118 |urids: &AtomURIDCollection| { urids.float }
119);
120
121pub struct Long;
123
124make_scalar_atom!(
125 Long,
126 i64,
127 sys::LV2_ATOM__Long,
128 |urids: &AtomURIDCollection| { urids.long }
129);
130
131pub struct Int;
133
134make_scalar_atom!(
135 Int,
136 i32,
137 sys::LV2_ATOM__Int,
138 |urids: &AtomURIDCollection| { urids.int }
139);
140
141pub struct Bool;
145
146make_scalar_atom!(
147 Bool,
148 i32,
149 sys::LV2_ATOM__Bool,
150 |urids: &AtomURIDCollection| { urids.bool }
151);
152
153pub struct AtomURID;
155
156make_scalar_atom!(
157 AtomURID,
158 URID,
159 sys::LV2_ATOM__URID,
160 |urids: &AtomURIDCollection| urids.urid
161);
162
163#[cfg(test)]
164mod tests {
165 use crate::prelude::*;
166 use crate::scalar::ScalarAtom;
167 use crate::space::*;
168 use std::convert::TryFrom;
169 use std::mem::size_of;
170 use urid::*;
171
172 fn test_scalar<A: ScalarAtom>(value: A::InternalType)
173 where
174 A::InternalType: PartialEq<A::InternalType>,
175 A::InternalType: std::fmt::Debug,
176 {
177 let map = HashURIDMapper::new();
178 let urid: URID<A> = map.map_type().unwrap();
179
180 let mut raw_space: Box<[u8]> = Box::new([0; 256]);
181
182 {
184 let mut space = RootMutSpace::new(raw_space.as_mut());
185 (&mut space as &mut dyn MutSpace).init(urid, value).unwrap();
186 }
187
188 {
190 #[repr(C)]
192 struct Scalar<B: Sized> {
193 atom: sys::LV2_Atom,
194 body: B,
195 }
196
197 let (scalar, _) = raw_space.split_at(size_of::<sys::LV2_Atom>());
198
199 let scalar = unsafe { &*(scalar.as_ptr() as *const Scalar<A::InternalType>) };
200 assert_eq!(scalar.atom.type_, urid);
201 assert_eq!(scalar.atom.size as usize, size_of::<A::InternalType>());
202 assert_eq!(scalar.body, value);
203 }
204
205 {
207 let space = Space::from_slice(raw_space.as_ref());
208 let (body, _) = space.split_atom_body(urid).unwrap();
209 assert_eq!(A::read(body, ()).unwrap(), value);
210 }
211 }
212
213 #[test]
214 fn test_scalars() {
215 test_scalar::<Double>(42.0);
216 test_scalar::<Float>(42.0);
217 test_scalar::<Long>(42);
218 test_scalar::<Int>(42);
219 test_scalar::<Bool>(1);
220 test_scalar::<AtomURID>(URID::try_from(1).unwrap());
221 }
222}