candid/types/
impls.rs

1use super::internal::*;
2use super::{CandidType, Compound, Serializer};
3
4macro_rules! primitive_impl {
5    ($t:ty, $id:tt, $method:ident $($cast:tt)*) => {
6        impl CandidType for $t {
7            fn _ty() -> Type { TypeInner::$id.into() }
8            fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error> where S: Serializer {
9                serializer.$method(*self $($cast)*)
10            }
11        }
12    };
13}
14
15primitive_impl!((), Null, serialize_null);
16primitive_impl!(bool, Bool, serialize_bool);
17
18primitive_impl!(i8, Int8, serialize_int8);
19primitive_impl!(i16, Int16, serialize_int16);
20primitive_impl!(i32, Int32, serialize_int32);
21primitive_impl!(i64, Int64, serialize_int64);
22
23primitive_impl!(u8, Nat8, serialize_nat8);
24primitive_impl!(u16, Nat16, serialize_nat16);
25primitive_impl!(u32, Nat32, serialize_nat32);
26primitive_impl!(u64, Nat64, serialize_nat64);
27
28primitive_impl!(f32, Float32, serialize_float32);
29primitive_impl!(f64, Float64, serialize_float64);
30
31// isize, usize always encode to 64bit to ensure the same behavior
32// on different platforms. This is consistent with serde's convention
33primitive_impl!(isize, Int64, serialize_int64 as i64);
34primitive_impl!(usize, Nat64, serialize_nat64 as u64);
35
36impl CandidType for i128 {
37    fn _ty() -> Type {
38        TypeInner::Int.into()
39    }
40    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
41    where
42        S: Serializer,
43    {
44        serializer.serialize_i128(*self)
45    }
46}
47impl CandidType for u128 {
48    fn _ty() -> Type {
49        TypeInner::Nat.into()
50    }
51    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
52    where
53        S: Serializer,
54    {
55        serializer.serialize_u128(*self)
56    }
57}
58
59impl CandidType for String {
60    fn _ty() -> Type {
61        TypeInner::Text.into()
62    }
63    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
64    where
65        S: Serializer,
66    {
67        serializer.serialize_text(self)
68    }
69}
70impl CandidType for str {
71    fn _ty() -> Type {
72        TypeInner::Text.into()
73    }
74    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
75    where
76        S: Serializer,
77    {
78        serializer.serialize_text(self)
79    }
80}
81
82impl CandidType for std::path::Path {
83    fn _ty() -> Type {
84        TypeInner::Text.into()
85    }
86    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
87    where
88        S: Serializer,
89    {
90        use serde::ser::Error;
91        match self.to_str() {
92            Some(s) => s.idl_serialize(serializer),
93            None => Err(S::Error::custom("path contains invalid UTF-8 characters")),
94        }
95    }
96}
97
98impl CandidType for std::path::PathBuf {
99    fn _ty() -> Type {
100        TypeInner::Text.into()
101    }
102    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
103    where
104        S: Serializer,
105    {
106        self.as_path().idl_serialize(serializer)
107    }
108}
109
110impl<T: Sized> CandidType for Option<T>
111where
112    T: CandidType,
113{
114    fn _ty() -> Type {
115        TypeInner::Opt(T::ty()).into()
116    }
117    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
118    where
119        S: Serializer,
120    {
121        serializer.serialize_option(self.as_ref())
122    }
123}
124
125impl<T> CandidType for [T]
126where
127    T: CandidType,
128{
129    fn _ty() -> Type {
130        TypeInner::Vec(T::ty()).into()
131    }
132    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
133    where
134        S: Serializer,
135    {
136        let mut ser = serializer.serialize_vec(self.len())?;
137        for e in self {
138            Compound::serialize_element(&mut ser, &e)?;
139        }
140        Ok(())
141    }
142}
143#[cfg_attr(docsrs, doc(cfg(feature = "serde_bytes")))]
144#[cfg(feature = "serde_bytes")]
145impl CandidType for serde_bytes::ByteBuf {
146    fn _ty() -> Type {
147        TypeInner::Vec(TypeInner::Nat8.into()).into()
148    }
149    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
150    where
151        S: Serializer,
152    {
153        serializer.serialize_blob(self.as_slice())
154    }
155}
156#[cfg_attr(docsrs, doc(cfg(feature = "serde_bytes")))]
157#[cfg(feature = "serde_bytes")]
158impl CandidType for serde_bytes::Bytes {
159    fn _ty() -> Type {
160        TypeInner::Vec(TypeInner::Nat8.into()).into()
161    }
162    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
163    where
164        S: Serializer,
165    {
166        serializer.serialize_blob(self)
167    }
168}
169#[cfg_attr(docsrs, doc(cfg(feature = "serde_bytes")))]
170#[cfg(feature = "serde_bytes")]
171impl<const N: usize> CandidType for serde_bytes::ByteArray<N> {
172    fn _ty() -> Type {
173        TypeInner::Vec(TypeInner::Nat8.into()).into()
174    }
175    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
176    where
177        S: Serializer,
178    {
179        serializer.serialize_blob(self.as_slice())
180    }
181}
182
183macro_rules! map_impl {
184    ($ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)* >) => {
185        impl<K, V $(, $typaram)*> CandidType for $ty<K, V $(, $typaram)*>
186        where
187            K: CandidType $(+ $kbound1 $(+ $kbound2)*)*,
188            V: CandidType,
189            $($typaram: $bound,)*
190        {
191            fn _ty() -> Type {
192                let tuple = TypeInner::Record(vec![
193                    Field {
194                        id: Label::Id(0).into(),
195                        ty: K::ty(),
196                    },
197                    Field {
198                        id: Label::Id(1).into(),
199                        ty: V::ty(),
200                    },
201                ]).into();
202                TypeInner::Vec(tuple).into()
203            }
204            fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
205            where
206                S: Serializer,
207            {
208                let mut ser = serializer.serialize_vec(self.len())?;
209                for e in self.iter() {
210                    Compound::serialize_element(&mut ser, &e)?;
211                }
212                Ok(())
213            }
214        }
215    }
216}
217macro_rules! seq_impl {
218    ($ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)* $(, $typaram:ident : $bound:ident)* >) => {
219        impl<K $(, $typaram)*> CandidType for $ty<K $(, $typaram)*>
220        where
221            K: CandidType $(+ $kbound1 $(+ $kbound2)*)*,
222            $($typaram: $bound,)*
223        {
224            fn _ty() -> Type {
225                TypeInner::Vec(K::ty()).into()
226            }
227            fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
228            where
229                S: Serializer,
230            {
231                let mut ser = serializer.serialize_vec(self.len())?;
232                for e in self.iter() {
233                    Compound::serialize_element(&mut ser, &e)?;
234                }
235                Ok(())
236            }
237        }
238    }
239}
240use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};
241use std::hash::{BuildHasher, Hash};
242map_impl!(BTreeMap<K: Ord, V>);
243map_impl!(HashMap<K: Eq + Hash, V, H: BuildHasher>);
244
245seq_impl!(Vec<K>);
246seq_impl!(VecDeque<K>);
247seq_impl!(LinkedList<K>);
248seq_impl!(BinaryHeap<K: Ord>);
249seq_impl!(BTreeSet<K: Ord>);
250seq_impl!(HashSet<K: Eq + Hash, H: BuildHasher>);
251
252impl<T: CandidType, const N: usize> CandidType for [T; N] {
253    fn _ty() -> Type {
254        TypeInner::Vec(T::ty()).into()
255    }
256    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
257    where
258        S: Serializer,
259    {
260        let mut ser = serializer.serialize_vec(N)?;
261        for e in self {
262            Compound::serialize_element(&mut ser, &e)?;
263        }
264        Ok(())
265    }
266}
267
268impl<T, E> CandidType for Result<T, E>
269where
270    T: CandidType,
271    E: CandidType,
272{
273    fn _ty() -> Type {
274        TypeInner::Variant(vec![
275            // Make sure the field id is sorted by idl_hash
276            Field {
277                id: Label::Named("Ok".to_owned()).into(),
278                ty: T::ty(),
279            },
280            Field {
281                id: Label::Named("Err".to_owned()).into(),
282                ty: E::ty(),
283            },
284        ])
285        .into()
286    }
287    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
288    where
289        S: Serializer,
290    {
291        match *self {
292            Result::Ok(ref v) => {
293                let mut ser = serializer.serialize_variant(0)?;
294                Compound::serialize_element(&mut ser, v)
295            }
296            Result::Err(ref e) => {
297                let mut ser = serializer.serialize_variant(1)?;
298                Compound::serialize_element(&mut ser, e)
299            }
300        }
301    }
302}
303
304impl<T> CandidType for Box<T>
305where
306    T: ?Sized + CandidType,
307{
308    fn _ty() -> Type {
309        T::ty()
310    }
311    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
312    where
313        S: Serializer,
314    {
315        (**self).idl_serialize(serializer)
316    }
317}
318
319impl<T> CandidType for std::cmp::Reverse<T>
320where
321    T: CandidType,
322{
323    fn _ty() -> Type {
324        T::ty()
325    }
326    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
327    where
328        S: Serializer,
329    {
330        self.0.idl_serialize(serializer)
331    }
332}
333
334impl<T> CandidType for &T
335where
336    T: ?Sized + CandidType,
337{
338    fn id() -> TypeId {
339        TypeId::of::<&T>()
340    } // ignore lifetime
341    fn _ty() -> Type {
342        T::ty()
343    }
344    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
345    where
346        S: Serializer,
347    {
348        (**self).idl_serialize(serializer)
349    }
350}
351impl<T> CandidType for &mut T
352where
353    T: ?Sized + CandidType,
354{
355    fn id() -> TypeId {
356        TypeId::of::<&T>()
357    } // ignore lifetime
358    fn _ty() -> Type {
359        T::ty()
360    }
361    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
362    where
363        S: Serializer,
364    {
365        (**self).idl_serialize(serializer)
366    }
367}
368
369impl<T> CandidType for std::borrow::Cow<'_, T>
370where
371    T: ?Sized + CandidType + ToOwned,
372{
373    fn _ty() -> Type {
374        T::ty()
375    }
376    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
377    where
378        S: Serializer,
379    {
380        (**self).idl_serialize(serializer)
381    }
382}
383
384impl<T> CandidType for std::cell::Cell<T>
385where
386    T: CandidType + Copy,
387{
388    fn _ty() -> Type {
389        T::ty()
390    }
391    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
392    where
393        S: Serializer,
394    {
395        self.get().idl_serialize(serializer)
396    }
397}
398
399impl<T> CandidType for std::cell::RefCell<T>
400where
401    T: CandidType,
402{
403    fn _ty() -> Type {
404        T::ty()
405    }
406    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
407    where
408        S: Serializer,
409    {
410        use serde::ser::Error;
411        match self.try_borrow() {
412            Ok(v) => v.idl_serialize(serializer),
413            Err(_) => Err(S::Error::custom("already mutably borrowed")),
414        }
415    }
416}
417
418impl<T> CandidType for std::rc::Rc<T>
419where
420    T: CandidType,
421{
422    fn _ty() -> Type {
423        T::ty()
424    }
425    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
426    where
427        S: Serializer,
428    {
429        self.as_ref().idl_serialize(serializer)
430    }
431}
432
433impl<T> CandidType for std::sync::Arc<T>
434where
435    T: CandidType,
436{
437    fn _ty() -> Type {
438        T::ty()
439    }
440    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
441    where
442        S: Serializer,
443    {
444        self.as_ref().idl_serialize(serializer)
445    }
446}
447
448impl<T> CandidType for std::marker::PhantomData<T>
449where
450    T: CandidType,
451{
452    fn _ty() -> Type {
453        T::ty()
454    }
455    fn idl_serialize<S>(&self, _: S) -> Result<(), S::Error>
456    where
457        S: Serializer,
458    {
459        use serde::ser::Error;
460        Err(S::Error::custom("`PhantomData` cannot be serialized"))
461    }
462}
463
464macro_rules! tuple_impls {
465    ($($len:expr => ($($n:tt $name:ident)+))+) => {
466        $(
467            impl<$($name),+> CandidType for ($($name,)+)
468            where
469                $($name: CandidType,)+
470            {
471                fn _ty() -> Type {
472                    TypeInner::Record(vec![
473                        $(Field{ id: Label::Id($n).into(), ty: $name::ty() },)+
474                    ]).into()
475                }
476                fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
477                where S: Serializer,
478                {
479                    let mut ser = serializer.serialize_struct()?;
480                    $(
481                        Compound::serialize_element(&mut ser, &self.$n)?;
482                    )+
483                    Ok(())
484                }
485            }
486        )+
487    }
488}
489
490tuple_impls! {
491    1 => (0 T0)
492    2 => (0 T0 1 T1)
493    3 => (0 T0 1 T1 2 T2)
494    4 => (0 T0 1 T1 2 T2 3 T3)
495    5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
496    6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
497    7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
498    8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
499    9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
500    10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
501    11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
502    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)
503    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)
504    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)
505    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)
506    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)
507}
508
509impl CandidType for std::time::SystemTime {
510    fn _ty() -> Type {
511        TypeInner::Record(vec![
512            Field {
513                id: Label::Named("nanos_since_epoch".to_owned()).into(),
514                ty: u32::ty(),
515            },
516            Field {
517                id: Label::Named("secs_since_epoch".to_owned()).into(),
518                ty: u64::ty(),
519            },
520        ])
521        .into()
522    }
523    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
524    where
525        S: Serializer,
526    {
527        use serde::ser::Error;
528
529        let duration_since_epoch = self
530            .duration_since(std::time::UNIX_EPOCH)
531            .map_err(|_| S::Error::custom("SystemTime must be later than UNIX_EPOCH"))?;
532
533        let secs: u64 = duration_since_epoch.as_secs();
534        let nanos: u32 = duration_since_epoch.subsec_nanos();
535
536        let mut ser = serializer.serialize_struct()?;
537        ser.serialize_element(&nanos)?;
538        ser.serialize_element(&secs)?;
539
540        Ok(())
541    }
542}
543
544impl CandidType for std::time::Duration {
545    fn _ty() -> Type {
546        TypeInner::Record(vec![
547            Field {
548                id: Label::Named("secs".to_owned()).into(),
549                ty: u64::ty(),
550            },
551            Field {
552                id: Label::Named("nanos".to_owned()).into(),
553                ty: u32::ty(),
554            },
555        ])
556        .into()
557    }
558    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
559    where
560        S: Serializer,
561    {
562        let secs: u64 = self.as_secs();
563        let nanos: u32 = self.subsec_nanos();
564
565        let mut ser = serializer.serialize_struct()?;
566        ser.serialize_element(&secs)?;
567        ser.serialize_element(&nanos)?;
568
569        Ok(())
570    }
571}