Skip to main content

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
125#[cfg(target_endian = "little")]
126fn fixed_primitive_byte_size<T: CandidType>() -> Option<usize> {
127    use super::internal::TypeId;
128    let tid = TypeId::of::<T>();
129    if tid == TypeId::of::<bool>() || tid == TypeId::of::<u8>() || tid == TypeId::of::<i8>() {
130        Some(1)
131    } else if tid == TypeId::of::<u16>() || tid == TypeId::of::<i16>() {
132        Some(2)
133    } else if tid == TypeId::of::<u32>() || tid == TypeId::of::<i32>() || tid == TypeId::of::<f32>()
134    {
135        Some(4)
136    } else if tid == TypeId::of::<u64>() || tid == TypeId::of::<i64>() || tid == TypeId::of::<f64>()
137    {
138        Some(8)
139    } else {
140        None
141    }
142}
143
144impl<T> CandidType for [T]
145where
146    T: CandidType,
147{
148    fn _ty() -> Type {
149        TypeInner::Vec(T::ty()).into()
150    }
151    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
152    where
153        S: Serializer,
154    {
155        let mut ser = serializer.serialize_vec(self.len())?;
156        #[cfg(target_endian = "little")]
157        if let Some(element_size) = fixed_primitive_byte_size::<T>() {
158            let bytes = unsafe {
159                std::slice::from_raw_parts(self.as_ptr() as *const u8, self.len() * element_size)
160            };
161            if Compound::try_write_raw_elements(&mut ser, bytes)? {
162                return Ok(());
163            }
164        }
165        for e in self {
166            Compound::serialize_element(&mut ser, &e)?;
167        }
168        Ok(())
169    }
170}
171#[cfg_attr(docsrs, doc(cfg(feature = "serde_bytes")))]
172#[cfg(feature = "serde_bytes")]
173impl CandidType for serde_bytes::ByteBuf {
174    fn _ty() -> Type {
175        TypeInner::Vec(TypeInner::Nat8.into()).into()
176    }
177    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
178    where
179        S: Serializer,
180    {
181        serializer.serialize_blob(self.as_slice())
182    }
183}
184#[cfg_attr(docsrs, doc(cfg(feature = "serde_bytes")))]
185#[cfg(feature = "serde_bytes")]
186impl CandidType for serde_bytes::Bytes {
187    fn _ty() -> Type {
188        TypeInner::Vec(TypeInner::Nat8.into()).into()
189    }
190    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
191    where
192        S: Serializer,
193    {
194        serializer.serialize_blob(self)
195    }
196}
197#[cfg_attr(docsrs, doc(cfg(feature = "serde_bytes")))]
198#[cfg(feature = "serde_bytes")]
199impl<const N: usize> CandidType for serde_bytes::ByteArray<N> {
200    fn _ty() -> Type {
201        TypeInner::Vec(TypeInner::Nat8.into()).into()
202    }
203    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
204    where
205        S: Serializer,
206    {
207        serializer.serialize_blob(self.as_slice())
208    }
209}
210
211macro_rules! map_impl {
212    ($ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)* >) => {
213        impl<K, V $(, $typaram)*> CandidType for $ty<K, V $(, $typaram)*>
214        where
215            K: CandidType $(+ $kbound1 $(+ $kbound2)*)*,
216            V: CandidType,
217            $($typaram: $bound,)*
218        {
219            fn _ty() -> Type {
220                let tuple = TypeInner::Record(vec![
221                    Field {
222                        id: Label::Id(0).into(),
223                        ty: K::ty(),
224                    },
225                    Field {
226                        id: Label::Id(1).into(),
227                        ty: V::ty(),
228                    },
229                ]).into();
230                TypeInner::Vec(tuple).into()
231            }
232            fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
233            where
234                S: Serializer,
235            {
236                let mut ser = serializer.serialize_vec(self.len())?;
237                for e in self.iter() {
238                    Compound::serialize_element(&mut ser, &e)?;
239                }
240                Ok(())
241            }
242        }
243    }
244}
245macro_rules! seq_impl {
246    ($ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)* $(, $typaram:ident : $bound:ident)* >) => {
247        impl<K $(, $typaram)*> CandidType for $ty<K $(, $typaram)*>
248        where
249            K: CandidType $(+ $kbound1 $(+ $kbound2)*)*,
250            $($typaram: $bound,)*
251        {
252            fn _ty() -> Type {
253                TypeInner::Vec(K::ty()).into()
254            }
255            fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
256            where
257                S: Serializer,
258            {
259                let mut ser = serializer.serialize_vec(self.len())?;
260                for e in self.iter() {
261                    Compound::serialize_element(&mut ser, &e)?;
262                }
263                Ok(())
264            }
265        }
266    }
267}
268use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};
269use std::hash::{BuildHasher, Hash};
270map_impl!(BTreeMap<K: Ord, V>);
271map_impl!(HashMap<K: Eq + Hash, V, H: BuildHasher>);
272
273impl<K: CandidType> CandidType for Vec<K> {
274    fn _ty() -> Type {
275        TypeInner::Vec(K::ty()).into()
276    }
277    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
278    where
279        S: Serializer,
280    {
281        self.as_slice().idl_serialize(serializer)
282    }
283}
284seq_impl!(VecDeque<K>);
285seq_impl!(LinkedList<K>);
286seq_impl!(BinaryHeap<K: Ord>);
287seq_impl!(BTreeSet<K: Ord>);
288seq_impl!(HashSet<K: Eq + Hash, H: BuildHasher>);
289
290impl<T: CandidType, const N: usize> CandidType for [T; N] {
291    fn _ty() -> Type {
292        TypeInner::Vec(T::ty()).into()
293    }
294    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
295    where
296        S: Serializer,
297    {
298        self.as_slice().idl_serialize(serializer)
299    }
300}
301
302impl<T, E> CandidType for Result<T, E>
303where
304    T: CandidType,
305    E: CandidType,
306{
307    fn _ty() -> Type {
308        TypeInner::Variant(vec![
309            // Make sure the field id is sorted by idl_hash
310            Field {
311                id: Label::Named("Ok".to_owned()).into(),
312                ty: T::ty(),
313            },
314            Field {
315                id: Label::Named("Err".to_owned()).into(),
316                ty: E::ty(),
317            },
318        ])
319        .into()
320    }
321    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
322    where
323        S: Serializer,
324    {
325        match *self {
326            Result::Ok(ref v) => {
327                let mut ser = serializer.serialize_variant(0)?;
328                Compound::serialize_element(&mut ser, v)
329            }
330            Result::Err(ref e) => {
331                let mut ser = serializer.serialize_variant(1)?;
332                Compound::serialize_element(&mut ser, e)
333            }
334        }
335    }
336}
337
338impl<T> CandidType for Box<T>
339where
340    T: ?Sized + CandidType,
341{
342    fn _ty() -> Type {
343        T::ty()
344    }
345    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
346    where
347        S: Serializer,
348    {
349        (**self).idl_serialize(serializer)
350    }
351}
352
353impl<T> CandidType for std::cmp::Reverse<T>
354where
355    T: CandidType,
356{
357    fn _ty() -> Type {
358        T::ty()
359    }
360    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
361    where
362        S: Serializer,
363    {
364        self.0.idl_serialize(serializer)
365    }
366}
367
368impl<T> CandidType for &T
369where
370    T: ?Sized + CandidType,
371{
372    fn id() -> TypeId {
373        TypeId::of::<&T>()
374    } // ignore lifetime
375    fn _ty() -> Type {
376        T::ty()
377    }
378    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
379    where
380        S: Serializer,
381    {
382        (**self).idl_serialize(serializer)
383    }
384}
385impl<T> CandidType for &mut T
386where
387    T: ?Sized + CandidType,
388{
389    fn id() -> TypeId {
390        TypeId::of::<&T>()
391    } // ignore lifetime
392    fn _ty() -> Type {
393        T::ty()
394    }
395    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
396    where
397        S: Serializer,
398    {
399        (**self).idl_serialize(serializer)
400    }
401}
402
403impl<T> CandidType for std::borrow::Cow<'_, T>
404where
405    T: ?Sized + CandidType + ToOwned,
406{
407    fn _ty() -> Type {
408        T::ty()
409    }
410    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
411    where
412        S: Serializer,
413    {
414        (**self).idl_serialize(serializer)
415    }
416}
417
418impl<T> CandidType for std::cell::Cell<T>
419where
420    T: CandidType + Copy,
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.get().idl_serialize(serializer)
430    }
431}
432
433impl<T> CandidType for std::cell::RefCell<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        use serde::ser::Error;
445        match self.try_borrow() {
446            Ok(v) => v.idl_serialize(serializer),
447            Err(_) => Err(S::Error::custom("already mutably borrowed")),
448        }
449    }
450}
451
452impl<T> CandidType for std::rc::Rc<T>
453where
454    T: CandidType,
455{
456    fn _ty() -> Type {
457        T::ty()
458    }
459    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
460    where
461        S: Serializer,
462    {
463        self.as_ref().idl_serialize(serializer)
464    }
465}
466
467impl<T> CandidType for std::sync::Arc<T>
468where
469    T: CandidType,
470{
471    fn _ty() -> Type {
472        T::ty()
473    }
474    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
475    where
476        S: Serializer,
477    {
478        self.as_ref().idl_serialize(serializer)
479    }
480}
481
482impl<T> CandidType for std::marker::PhantomData<T>
483where
484    T: CandidType,
485{
486    fn _ty() -> Type {
487        T::ty()
488    }
489    fn idl_serialize<S>(&self, _: S) -> Result<(), S::Error>
490    where
491        S: Serializer,
492    {
493        use serde::ser::Error;
494        Err(S::Error::custom("`PhantomData` cannot be serialized"))
495    }
496}
497
498macro_rules! tuple_impls {
499    ($($len:expr => ($($n:tt $name:ident)+))+) => {
500        $(
501            impl<$($name),+> CandidType for ($($name,)+)
502            where
503                $($name: CandidType,)+
504            {
505                fn _ty() -> Type {
506                    TypeInner::Record(vec![
507                        $(Field{ id: Label::Id($n).into(), ty: $name::ty() },)+
508                    ]).into()
509                }
510                fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
511                where S: Serializer,
512                {
513                    let mut ser = serializer.serialize_struct()?;
514                    $(
515                        Compound::serialize_element(&mut ser, &self.$n)?;
516                    )+
517                    Ok(())
518                }
519            }
520        )+
521    }
522}
523
524tuple_impls! {
525    1 => (0 T0)
526    2 => (0 T0 1 T1)
527    3 => (0 T0 1 T1 2 T2)
528    4 => (0 T0 1 T1 2 T2 3 T3)
529    5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
530    6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
531    7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
532    8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
533    9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
534    10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
535    11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
536    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)
537    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)
538    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)
539    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)
540    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)
541}
542
543impl CandidType for std::time::SystemTime {
544    fn _ty() -> Type {
545        TypeInner::Record(vec![
546            Field {
547                id: Label::Named("nanos_since_epoch".to_owned()).into(),
548                ty: u32::ty(),
549            },
550            Field {
551                id: Label::Named("secs_since_epoch".to_owned()).into(),
552                ty: u64::ty(),
553            },
554        ])
555        .into()
556    }
557    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
558    where
559        S: Serializer,
560    {
561        use serde::ser::Error;
562
563        let duration_since_epoch = self
564            .duration_since(std::time::UNIX_EPOCH)
565            .map_err(|_| S::Error::custom("SystemTime must be later than UNIX_EPOCH"))?;
566
567        let secs: u64 = duration_since_epoch.as_secs();
568        let nanos: u32 = duration_since_epoch.subsec_nanos();
569
570        let mut ser = serializer.serialize_struct()?;
571        ser.serialize_element(&nanos)?;
572        ser.serialize_element(&secs)?;
573
574        Ok(())
575    }
576}
577
578impl CandidType for std::time::Duration {
579    fn _ty() -> Type {
580        TypeInner::Record(vec![
581            Field {
582                id: Label::Named("secs".to_owned()).into(),
583                ty: u64::ty(),
584            },
585            Field {
586                id: Label::Named("nanos".to_owned()).into(),
587                ty: u32::ty(),
588            },
589        ])
590        .into()
591    }
592    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
593    where
594        S: Serializer,
595    {
596        let secs: u64 = self.as_secs();
597        let nanos: u32 = self.subsec_nanos();
598
599        let mut ser = serializer.serialize_struct()?;
600        ser.serialize_element(&secs)?;
601        ser.serialize_element(&nanos)?;
602
603        Ok(())
604    }
605}