zvariant/type/
libstd.rs

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