zvariant/
basic.rs

1use crate::{Signature, Type, impl_type_with_repr, serialized::Format};
2
3/// Trait for basic types.
4///
5/// All basic types are also [`Type`] implementers.
6///
7/// [`Type`]: trait.Type.html
8/// [`Value`]: enum.Value.html
9pub trait Basic: Type {
10    /// The type signature, as a character.
11    const SIGNATURE_CHAR: char;
12    /// The type signature, as a string.
13    const SIGNATURE_STR: &'static str;
14
15    /// The required padding alignment for the given format.
16    ///
17    /// The default implementation covers all possible cases so you should never need to override
18    /// it.
19    fn alignment(format: Format) -> usize {
20        Self::SIGNATURE.alignment(format)
21    }
22}
23
24macro_rules! impl_type {
25    ($for:ty) => {
26        impl Type for $for {
27            const SIGNATURE: &'static Signature = {
28                match Self::SIGNATURE_CHAR {
29                    'y' => &Signature::U8,
30                    'b' => &Signature::Bool,
31                    'n' => &Signature::I16,
32                    'q' => &Signature::U16,
33                    'i' => &Signature::I32,
34                    'u' => &Signature::U32,
35                    'x' => &Signature::I64,
36                    't' => &Signature::U64,
37                    'd' => &Signature::F64,
38                    's' => &Signature::Str,
39                    'g' => &Signature::Signature,
40                    'o' => &Signature::ObjectPath,
41                    'v' => &Signature::Variant,
42                    #[cfg(unix)]
43                    'h' => &Signature::Fd,
44                    _ => unreachable!(),
45                }
46            };
47        }
48    };
49}
50
51impl Basic for u8 {
52    const SIGNATURE_CHAR: char = 'y';
53    const SIGNATURE_STR: &'static str = "y";
54}
55impl_type!(u8);
56
57impl Basic for std::num::NonZeroU8 {
58    const SIGNATURE_CHAR: char = u8::SIGNATURE_CHAR;
59    const SIGNATURE_STR: &'static str = u8::SIGNATURE_STR;
60}
61impl_type!(std::num::NonZeroU8);
62
63// No i8 type in D-Bus/GVariant, let's pretend it's i16
64impl Basic for i8 {
65    const SIGNATURE_CHAR: char = i16::SIGNATURE_CHAR;
66    const SIGNATURE_STR: &'static str = i16::SIGNATURE_STR;
67}
68impl_type!(i8);
69
70impl Basic for std::num::NonZeroI8 {
71    const SIGNATURE_CHAR: char = i8::SIGNATURE_CHAR;
72    const SIGNATURE_STR: &'static str = i8::SIGNATURE_STR;
73}
74impl_type!(std::num::NonZeroI8);
75
76impl Basic for bool {
77    const SIGNATURE_CHAR: char = 'b';
78    const SIGNATURE_STR: &'static str = "b";
79}
80impl_type!(bool);
81
82impl Basic for i16 {
83    const SIGNATURE_CHAR: char = 'n';
84    const SIGNATURE_STR: &'static str = "n";
85}
86impl_type!(i16);
87
88impl Basic for std::num::NonZeroI16 {
89    const SIGNATURE_CHAR: char = i16::SIGNATURE_CHAR;
90    const SIGNATURE_STR: &'static str = i16::SIGNATURE_STR;
91}
92impl_type!(std::num::NonZeroI16);
93
94impl Basic for u16 {
95    const SIGNATURE_CHAR: char = 'q';
96    const SIGNATURE_STR: &'static str = "q";
97}
98impl_type!(u16);
99
100impl Basic for std::num::NonZeroU16 {
101    const SIGNATURE_CHAR: char = u16::SIGNATURE_CHAR;
102    const SIGNATURE_STR: &'static str = u16::SIGNATURE_STR;
103}
104impl_type!(std::num::NonZeroU16);
105
106impl Basic for i32 {
107    const SIGNATURE_CHAR: char = 'i';
108    const SIGNATURE_STR: &'static str = "i";
109}
110impl_type!(i32);
111
112impl Basic for std::num::NonZeroI32 {
113    const SIGNATURE_CHAR: char = i32::SIGNATURE_CHAR;
114    const SIGNATURE_STR: &'static str = i32::SIGNATURE_STR;
115}
116impl_type!(std::num::NonZeroI32);
117
118impl Basic for u32 {
119    const SIGNATURE_CHAR: char = 'u';
120    const SIGNATURE_STR: &'static str = "u";
121}
122impl_type!(u32);
123
124impl Basic for std::num::NonZeroU32 {
125    const SIGNATURE_CHAR: char = u32::SIGNATURE_CHAR;
126    const SIGNATURE_STR: &'static str = u32::SIGNATURE_STR;
127}
128impl_type!(std::num::NonZeroU32);
129
130impl Basic for i64 {
131    const SIGNATURE_CHAR: char = 'x';
132    const SIGNATURE_STR: &'static str = "x";
133}
134impl_type!(i64);
135
136impl Basic for std::num::NonZeroI64 {
137    const SIGNATURE_CHAR: char = i64::SIGNATURE_CHAR;
138    const SIGNATURE_STR: &'static str = i64::SIGNATURE_STR;
139}
140impl_type!(std::num::NonZeroI64);
141
142impl Basic for u64 {
143    const SIGNATURE_CHAR: char = 't';
144    const SIGNATURE_STR: &'static str = "t";
145}
146impl_type!(u64);
147
148impl Basic for std::num::NonZeroU64 {
149    const SIGNATURE_CHAR: char = u64::SIGNATURE_CHAR;
150    const SIGNATURE_STR: &'static str = u64::SIGNATURE_STR;
151}
152impl_type!(std::num::NonZeroU64);
153
154// No f32 type in D-Bus/GVariant, let's pretend it's f64
155impl Basic for f32 {
156    const SIGNATURE_CHAR: char = f64::SIGNATURE_CHAR;
157    const SIGNATURE_STR: &'static str = f64::SIGNATURE_STR;
158}
159impl_type!(f32);
160
161impl Basic for f64 {
162    const SIGNATURE_CHAR: char = 'd';
163    const SIGNATURE_STR: &'static str = "d";
164}
165impl_type!(f64);
166
167impl Basic for str {
168    const SIGNATURE_CHAR: char = 's';
169    const SIGNATURE_STR: &'static str = "s";
170}
171impl_type!(str);
172
173impl Basic for String {
174    const SIGNATURE_CHAR: char = 's';
175    const SIGNATURE_STR: &'static str = "s";
176}
177impl_type!(String);
178
179impl Basic for char {
180    const SIGNATURE_CHAR: char = <&str>::SIGNATURE_CHAR;
181    const SIGNATURE_STR: &'static str = <&str>::SIGNATURE_STR;
182}
183impl_type!(char);
184
185////////////////////////////////////////////////////////////////////////////////
186
187impl Basic for usize {
188    const SIGNATURE_CHAR: char = <u64 as Basic>::SIGNATURE_CHAR;
189    const SIGNATURE_STR: &'static str = <u64 as Basic>::SIGNATURE_STR;
190}
191
192impl_type_with_repr! {
193    // usize is serialized as u64:
194    // https://github.com/serde-rs/serde/blob/9b868ef831c95f50dd4bde51a7eb52e3b9ee265a/serde/src/ser/impls.rs#L28
195    usize => u64 {
196        usize {
197            samples = [usize::MAX, usize::MIN],
198            repr(n) = n as u64,
199        }
200    }
201}
202
203impl_type_with_repr! {
204    // isize is serialized as i64:
205    // https://github.com/serde-rs/serde/blob/9b868ef831c95f50dd4bde51a7eb52e3b9ee265a/serde/src/ser/impls.rs#L22
206    isize => i64 {
207        isize {
208            samples = [isize::MAX, isize::MIN],
209            repr(n) = n as i64,
210        }
211    }
212}
213
214impl Basic for isize {
215    const SIGNATURE_CHAR: char = <i64 as Basic>::SIGNATURE_CHAR;
216    const SIGNATURE_STR: &'static str = <i64 as Basic>::SIGNATURE_STR;
217}
218
219////////////////////////////////////////////////////////////////////////////////
220
221macro_rules! impl_basic_for_deref {
222    (
223        $type:ty,
224        <$($desc:tt)+
225    ) => {
226        impl <$($desc)+ {
227            const SIGNATURE_CHAR: char = <$type>::SIGNATURE_CHAR;
228            const SIGNATURE_STR: &'static str = <$type>::SIGNATURE_STR;
229        }
230    };
231}
232
233impl_basic_for_deref!(T, <T: ?Sized + Basic> Basic for &T);
234impl_basic_for_deref!(T, <T: ?Sized + Basic> Basic for &mut T);
235impl_basic_for_deref!(T, <T: ?Sized + Basic + ToOwned> Basic for std::borrow::Cow<'_,T>);
236impl_basic_for_deref!(T, <T: ?Sized + Basic> Basic for std::sync::Arc<T>);
237impl_basic_for_deref!(T, <T: ?Sized + Basic> Basic for std::sync::Weak<T>);
238impl_basic_for_deref!(T, <T: ?Sized + Basic> Basic for std::sync::Mutex<T>);
239impl_basic_for_deref!(T, <T: ?Sized + Basic> Basic for std::sync::RwLock<T>);
240impl_basic_for_deref!(T, <T: ?Sized + Basic> Basic for std::boxed::Box<T>);
241impl_basic_for_deref!(T, <T: ?Sized + Basic> Basic for std::rc::Rc<T>);
242impl_basic_for_deref!(T, <T: ?Sized + Basic> Basic for std::rc::Weak<T>);
243impl_basic_for_deref!(T, <T: ?Sized + Basic> Basic for std::cell::Cell<T>);
244impl_basic_for_deref!(T, <T: ?Sized + Basic> Basic for std::cell::RefCell<T>);
245
246////////////////////////////////////////////////////////////////////////////////
247
248use std::{
249    cmp::Reverse,
250    num::{Saturating, Wrapping},
251};
252
253macro_rules! impl_basic_for_wrapper {
254    ($($wrapper:ident<$T:ident>),+) => {
255        $(
256            impl<$T: Basic> Basic for $wrapper<$T> {
257                const SIGNATURE_CHAR: char = <$T>::SIGNATURE_CHAR;
258                const SIGNATURE_STR: &'static str = <$T>::SIGNATURE_STR;
259            }
260        )+
261    };
262}
263
264impl_basic_for_wrapper!(Wrapping<T>, Saturating<T>, Reverse<T>);
265
266////////////////////////////////////////////////////////////////////////////////
267
268macro_rules! atomic_impl {
269    ($($ty:ident $size:expr => $primitive:ident)*) => {
270        $(
271            #[cfg(target_has_atomic = $size)]
272            impl Basic for $ty {
273                const SIGNATURE_CHAR: char = <$primitive as Basic>::SIGNATURE_CHAR;
274                const SIGNATURE_STR: &'static str = <$primitive as Basic>::SIGNATURE_STR;
275            }
276            impl_type!($ty);
277        )*
278    }
279}
280
281use std::sync::atomic::{
282    AtomicBool, AtomicI8, AtomicI16, AtomicI32, AtomicIsize, AtomicU8, AtomicU16, AtomicU32,
283    AtomicUsize,
284};
285#[cfg(target_has_atomic = "64")]
286use std::sync::atomic::{AtomicI64, AtomicU64};
287
288atomic_impl! {
289    AtomicBool "8" => bool
290    AtomicI8 "8" => i8
291    AtomicI16 "16" => i16
292    AtomicI32 "32" => i32
293    AtomicIsize "ptr" => isize
294    AtomicU8 "8" => u8
295    AtomicU16 "16" => u16
296    AtomicU32 "32" => u32
297    AtomicUsize "ptr" => usize
298}
299
300#[cfg(target_has_atomic = "64")]
301atomic_impl! {
302    AtomicI64 "64" => i64
303    AtomicU64 "64" => u64
304}
305
306////////////////////////////////////////////////////////////////////////////////
307
308#[cfg(feature = "heapless")]
309impl<const CAP: usize> Basic for heapless::String<CAP> {
310    const SIGNATURE_CHAR: char = <&str as Basic>::SIGNATURE_CHAR;
311    const SIGNATURE_STR: &'static str = <&str as Basic>::SIGNATURE_STR;
312}