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
93impl 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
138macro_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
177impl<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
195use 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
220impl_type_with_repr! {
223 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 => i64 {
237 isize {
238 samples = [isize::MAX, isize::MIN],
239 repr(n) = n as i64,
240 }
241 }
242}
243
244impl_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
255macro_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
269macro_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
300impl_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