zvariant/type/
libstd.rs

1use crate::{impl_type_with_repr, Signature, Type};
2use std::{
3    cell::{Cell, RefCell},
4    cmp::Reverse,
5    marker::PhantomData,
6    num::{Saturating, Wrapping},
7    ops::{Range, RangeFrom, RangeInclusive, RangeTo},
8    rc::{Rc, Weak as RcWeak},
9    sync::{
10        atomic::{
11            AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32,
12            AtomicU8, AtomicUsize,
13        },
14        Arc, Mutex, RwLock, Weak as ArcWeak,
15    },
16    time::Duration,
17};
18
19#[cfg(target_has_atomic = "64")]
20use std::sync::atomic::{AtomicI64, AtomicU64};
21
22impl<T> Type for PhantomData<T>
23where
24    T: Type + ?Sized,
25{
26    const SIGNATURE: &'static Signature = T::SIGNATURE;
27}
28
29macro_rules! array_type {
30    ($arr:ty) => {
31        impl<T> Type for $arr
32        where
33            T: Type,
34        {
35            const SIGNATURE: &'static Signature = &Signature::static_array(T::SIGNATURE);
36        }
37    };
38}
39
40array_type!([T]);
41array_type!(Vec<T>);
42array_type!(std::collections::VecDeque<T>);
43array_type!(std::collections::LinkedList<T>);
44
45impl<T, S> Type for std::collections::HashSet<T, S>
46where
47    T: Type + Eq + Hash,
48    S: BuildHasher,
49{
50    const SIGNATURE: &'static Signature = <[T]>::SIGNATURE;
51}
52
53impl<T> Type for std::collections::BTreeSet<T>
54where
55    T: Type + Ord,
56{
57    const SIGNATURE: &'static Signature = <[T]>::SIGNATURE;
58}
59
60impl<T> Type for std::collections::BinaryHeap<T>
61where
62    T: Type + Ord,
63{
64    const SIGNATURE: &'static Signature = <[T]>::SIGNATURE;
65}
66
67#[cfg(feature = "arrayvec")]
68impl<T, const CAP: usize> Type for arrayvec::ArrayVec<T, CAP>
69where
70    T: Type,
71{
72    const SIGNATURE: &'static Signature = <[T]>::SIGNATURE;
73}
74
75#[cfg(feature = "arrayvec")]
76impl<const CAP: usize> Type for arrayvec::ArrayString<CAP> {
77    const SIGNATURE: &'static Signature = &Signature::Str;
78}
79
80#[cfg(feature = "heapless")]
81impl<T, const CAP: usize> Type for heapless::Vec<T, CAP>
82where
83    T: Type,
84{
85    const SIGNATURE: &'static Signature = <[T]>::SIGNATURE;
86}
87
88#[cfg(feature = "heapless")]
89impl<const CAP: usize> Type for heapless::String<CAP> {
90    const SIGNATURE: &'static Signature = &Signature::Str;
91}
92
93// Empty type deserves empty signature
94impl Type for () {
95    const SIGNATURE: &'static Signature = &Signature::Unit;
96}
97
98macro_rules! deref_impl {
99    (
100        $type:ty,
101        <$($desc:tt)+
102    ) => {
103        impl <$($desc)+ {
104            const SIGNATURE: &'static Signature = <$type>::SIGNATURE;
105        }
106    };
107}
108
109deref_impl!(T, <T: ?Sized + Type> Type for &T);
110deref_impl!(T, <T: ?Sized + Type> Type for &mut T);
111deref_impl!(T, <T: ?Sized + Type + ToOwned> Type for Cow<'_, T>);
112deref_impl!(T, <T: ?Sized + Type> Type for Arc<T>);
113deref_impl!(T, <T: ?Sized + Type> Type for ArcWeak<T>);
114deref_impl!(T, <T: ?Sized + Type> Type for Mutex<T>);
115deref_impl!(T, <T: ?Sized + Type> Type for RwLock<T>);
116deref_impl!(T, <T: ?Sized + Type> Type for Box<T>);
117deref_impl!(T, <T: ?Sized + Type> Type for Rc<T>);
118deref_impl!(T, <T: ?Sized + Type> Type for RcWeak<T>);
119deref_impl!(T, <T: ?Sized + Type> Type for Cell<T>);
120deref_impl!(T, <T: ?Sized + Type> Type for RefCell<T>);
121
122#[cfg(all(feature = "gvariant", not(feature = "option-as-array")))]
123impl<T> Type for Option<T>
124where
125    T: Type,
126{
127    const SIGNATURE: &'static Signature = &Signature::static_maybe(T::SIGNATURE);
128}
129
130#[cfg(feature = "option-as-array")]
131impl<T> Type for Option<T>
132where
133    T: Type,
134{
135    const SIGNATURE: &'static Signature = &Signature::static_array(T::SIGNATURE);
136}
137
138////////////////////////////////////////////////////////////////////////////////
139
140macro_rules! tuple_impls {
141    ($($len:expr => ($($n:tt $name:ident)+))+) => {
142        $(
143            impl<$($name),+> Type for ($($name,)+)
144            where
145                $($name: Type,)+
146            {
147                const SIGNATURE: &'static Signature =
148                    &Signature::static_structure(&[
149                        $(
150                            $name::SIGNATURE,
151                        )+
152                    ]);
153            }
154        )+
155    }
156}
157
158tuple_impls! {
159    1 => (0 T0)
160    2 => (0 T0 1 T1)
161    3 => (0 T0 1 T1 2 T2)
162    4 => (0 T0 1 T1 2 T2 3 T3)
163    5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
164    6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
165    7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
166    8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
167    9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
168    10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
169    11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
170    12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11)
171    13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12)
172    14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13)
173    15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14)
174    16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15)
175}
176
177////////////////////////////////////////////////////////////////////////////////
178
179// Arrays are serialized as tuples/structs by Serde so we treat them as such too even though
180// it's very strange. Slices and arrayvec::ArrayVec can be used anyway so I guess it's no big
181// deal.
182impl<T, const N: usize> Type for [T; N]
183where
184    T: Type,
185{
186    const SIGNATURE: &'static Signature = &{
187        if N == 0 {
188            Signature::U8
189        } else {
190            Signature::static_structure(&[T::SIGNATURE; N])
191        }
192    };
193}
194
195////////////////////////////////////////////////////////////////////////////////
196
197use std::{
198    borrow::Cow,
199    collections::{BTreeMap, HashMap},
200    hash::{BuildHasher, Hash},
201};
202
203macro_rules! map_impl {
204    ($ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)* >) => {
205        impl<K, V $(, $typaram)*> Type for $ty<K, V $(, $typaram)*>
206        where
207            K: Type $(+ $kbound1 $(+ $kbound2)*)*,
208            V: Type,
209            $($typaram: $bound,)*
210        {
211            const SIGNATURE: &'static Signature =
212                &Signature::static_dict(K::SIGNATURE, V::SIGNATURE);
213        }
214    }
215}
216
217map_impl!(BTreeMap<K: Ord, V>);
218map_impl!(HashMap<K: Eq + Hash, V, H: BuildHasher>);
219
220////////////////////////////////////////////////////////////////////////////////
221
222impl_type_with_repr! {
223    // usize is serialized as u64:
224    // https://github.com/serde-rs/serde/blob/9b868ef831c95f50dd4bde51a7eb52e3b9ee265a/serde/src/ser/impls.rs#L28
225    usize => u64 {
226        usize {
227            samples = [usize::MAX, usize::MIN],
228            repr(n) = n as u64,
229        }
230    }
231}
232
233impl_type_with_repr! {
234    // isize is serialized as i64:
235    // https://github.com/serde-rs/serde/blob/9b868ef831c95f50dd4bde51a7eb52e3b9ee265a/serde/src/ser/impls.rs#L22
236    isize => i64 {
237        isize {
238            samples = [isize::MAX, isize::MIN],
239            repr(n) = n as i64,
240        }
241    }
242}
243
244////////////////////////////////////////////////////////////////////////////////
245
246impl_type_with_repr! {
247    Duration => (u64, u32) {
248        duration {
249            samples = [Duration::ZERO, Duration::MAX],
250            repr(d) = (d.as_secs(), d.subsec_nanos()),
251        }
252    }
253}
254
255////////////////////////////////////////////////////////////////////////////////
256
257macro_rules! impl_type_for_wrapper {
258    ($($wrapper:ident<$T:ident>),+) => {
259        $(
260            impl<$T: Type> Type for $wrapper<$T> {
261                const SIGNATURE: &'static Signature = <$T>::SIGNATURE;
262            }
263        )+
264    };
265}
266
267impl_type_for_wrapper!(Wrapping<T>, Saturating<T>, Reverse<T>);
268
269////////////////////////////////////////////////////////////////////////////////
270
271macro_rules! atomic_impl {
272    ($($ty:ident $size:expr => $primitive:ident)*) => {
273        $(
274            #[cfg(target_has_atomic = $size)]
275            impl Type for $ty {
276                const SIGNATURE: &'static Signature = <$primitive as Type>::SIGNATURE;
277            }
278        )*
279    }
280}
281
282atomic_impl! {
283    AtomicBool "8" => bool
284    AtomicI8 "8" => i8
285    AtomicI16 "16" => i16
286    AtomicI32 "32" => i32
287    AtomicIsize "ptr" => isize
288    AtomicU8 "8" => u8
289    AtomicU16 "16" => u16
290    AtomicU32 "32" => u32
291    AtomicUsize "ptr" => usize
292}
293
294#[cfg(target_has_atomic = "64")]
295atomic_impl! {
296    AtomicI64 "64" => i64
297    AtomicU64 "64" => u64
298}
299
300////////////////////////////////////////////////////////////////////////////////
301
302impl_type_with_repr! {
303    Range<Idx: Type> => (Idx, Idx) {
304        range <Idx = u32> {
305            samples = [0..42, 17..100],
306            repr(range) = (range.start, range.end),
307        }
308    }
309}
310
311impl_type_with_repr! {
312    RangeFrom<Idx: Type> => (Idx,) {
313        range_from <Idx = u32> {
314            samples = [0.., 17..],
315            repr(range) = (range.start,),
316        }
317    }
318}
319
320impl_type_with_repr! {
321    RangeInclusive<Idx: Type> => (Idx, Idx) {
322        range_inclusive <Idx = u32> {
323            samples = [0..=42, 17..=100],
324            repr(range) = (*range.start(), *range.end()),
325        }
326    }
327}
328
329impl_type_with_repr! {
330    RangeTo<Idx: Type> => (Idx,) {
331        range_to <Idx = u32> {
332            samples = [..42, ..100],
333            repr(range) = (range.end,),
334        }
335    }
336}
337
338// serde::Serialize is not implemented for `RangeToInclusive` and `RangeFull`:
339// https://github.com/serde-rs/serde/issues/2685
340
341// TODO: Blanket implementation for more types: https://github.com/serde-rs/serde/blob/master/serde/src/ser/impls.rs