scale_info/
impls.rs

1// Copyright 2019-2022 Parity Technologies (UK) Ltd.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::prelude::{
16    borrow::{Cow, ToOwned},
17    boxed::Box,
18    collections::{BTreeMap, BTreeSet, BinaryHeap, VecDeque},
19    fmt,
20    marker::PhantomData,
21    ops::{Range, RangeInclusive},
22    rc::Rc,
23    string::String,
24    sync::Arc,
25    time::Duration,
26    vec::Vec,
27};
28
29use crate::{
30    build::*, MetaType, Path, Type, TypeDefArray, TypeDefCompact, TypeDefPrimitive,
31    TypeDefSequence, TypeDefTuple, TypeInfo,
32};
33use core::num::{
34    NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroU128, NonZeroU16,
35    NonZeroU32, NonZeroU64, NonZeroU8,
36};
37
38macro_rules! impl_metadata_for_primitives {
39    ( $( $t:ty => $ident_kind:expr, )* ) => { $(
40        impl TypeInfo for $t {
41            type Identity = Self;
42
43            fn type_info() -> Type {
44                $ident_kind.into()
45            }
46        }
47    )* }
48}
49
50impl_metadata_for_primitives!(
51    bool => TypeDefPrimitive::Bool,
52    char => TypeDefPrimitive::Char,
53    u8 => TypeDefPrimitive::U8,
54    u16 => TypeDefPrimitive::U16,
55    u32 => TypeDefPrimitive::U32,
56    u64 => TypeDefPrimitive::U64,
57    u128 => TypeDefPrimitive::U128,
58    i8 => TypeDefPrimitive::I8,
59    i16 => TypeDefPrimitive::I16,
60    i32 => TypeDefPrimitive::I32,
61    i64 => TypeDefPrimitive::I64,
62    i128 => TypeDefPrimitive::I128,
63);
64
65impl<T: TypeInfo + 'static, const N: usize> TypeInfo for [T; N] {
66    type Identity = Self;
67
68    fn type_info() -> Type {
69        TypeDefArray::new(N as u32, MetaType::new::<T>()).into()
70    }
71}
72
73macro_rules! impl_metadata_for_tuple {
74    ( $($ty:ident),* ) => {
75        impl<$($ty),*> TypeInfo for ($($ty,)*)
76        where
77            $(
78                $ty: TypeInfo+ 'static,
79            )*
80        {
81            type Identity = Self;
82
83            fn type_info() -> Type {
84                TypeDefTuple::new(tuple_meta_type!($($ty),*)).into()
85            }
86        }
87    }
88}
89
90impl_metadata_for_tuple!();
91impl_metadata_for_tuple!(A);
92impl_metadata_for_tuple!(A, B);
93impl_metadata_for_tuple!(A, B, C);
94impl_metadata_for_tuple!(A, B, C, D);
95impl_metadata_for_tuple!(A, B, C, D, E);
96impl_metadata_for_tuple!(A, B, C, D, E, F);
97impl_metadata_for_tuple!(A, B, C, D, E, F, G);
98impl_metadata_for_tuple!(A, B, C, D, E, F, G, H);
99impl_metadata_for_tuple!(A, B, C, D, E, F, G, H, I);
100impl_metadata_for_tuple!(A, B, C, D, E, F, G, H, I, J);
101impl_metadata_for_tuple!(A, B, C, D, E, F, G, H, I, J, K);
102impl_metadata_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);
103impl_metadata_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M);
104impl_metadata_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
105impl_metadata_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
106impl_metadata_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
107impl_metadata_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q);
108impl_metadata_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R);
109impl_metadata_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S);
110impl_metadata_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T);
111
112macro_rules! impl_for_non_zero {
113    ( $( $t: ty: $inner: ty ),* $(,)? ) => {
114        $(
115            impl TypeInfo for $t {
116                type Identity = Self;
117                fn type_info() -> Type {
118                    Type::builder()
119                        .path(Path::prelude(stringify!($t)))
120                        .composite(Fields::unnamed().field(|f| f.ty::<$inner>()))
121                }
122            }
123        )*
124    };
125}
126
127impl_for_non_zero!(
128    NonZeroI8: i8,
129    NonZeroI16: i16,
130    NonZeroI32: i32,
131    NonZeroI64: i64,
132    NonZeroI128: i128,
133    NonZeroU8: u8,
134    NonZeroU16: u16,
135    NonZeroU32: u32,
136    NonZeroU64: u64,
137    NonZeroU128: u128
138);
139
140impl TypeInfo for Duration {
141    type Identity = Self;
142
143    fn type_info() -> Type {
144        Type::builder().path(Path::prelude("Duration")).composite(
145            Fields::unnamed()
146                .field(|f| {
147                    // Seconds
148                    f.ty::<u64>().type_name("u64")
149                })
150                .field(|f| {
151                    // Nanoseconds
152                    f.ty::<u32>().type_name("u32")
153                }),
154        )
155    }
156}
157
158impl<T> TypeInfo for Vec<T>
159where
160    T: TypeInfo + 'static,
161{
162    type Identity = [T];
163
164    fn type_info() -> Type {
165        Self::Identity::type_info()
166    }
167}
168
169impl<T> TypeInfo for VecDeque<T>
170where
171    T: TypeInfo + 'static,
172{
173    type Identity = [T];
174
175    fn type_info() -> Type {
176        Self::Identity::type_info()
177    }
178}
179
180impl<T> TypeInfo for Option<T>
181where
182    T: TypeInfo + 'static,
183{
184    type Identity = Self;
185
186    fn type_info() -> Type {
187        Type::builder()
188            .path(Path::prelude("Option"))
189            .type_params(type_params![T])
190            .variant(
191                Variants::new()
192                    .variant("None", |v| v.index(0))
193                    .variant("Some", |v| {
194                        v.index(1).fields(Fields::unnamed().field(|f| f.ty::<T>()))
195                    }),
196            )
197    }
198}
199
200impl<T, E> TypeInfo for Result<T, E>
201where
202    T: TypeInfo + 'static,
203    E: TypeInfo + 'static,
204{
205    type Identity = Self;
206
207    fn type_info() -> Type {
208        Type::builder()
209            .path(Path::prelude("Result"))
210            .type_params(type_params!(T, E))
211            .variant(
212                Variants::new()
213                    .variant("Ok", |v| {
214                        v.index(0).fields(Fields::unnamed().field(|f| f.ty::<T>()))
215                    })
216                    .variant("Err", |v| {
217                        v.index(1).fields(Fields::unnamed().field(|f| f.ty::<E>()))
218                    }),
219            )
220    }
221}
222
223impl<T> TypeInfo for Cow<'static, T>
224where
225    T: ToOwned + TypeInfo + ?Sized + 'static,
226{
227    type Identity = Self;
228
229    fn type_info() -> Type {
230        Type::builder()
231            .path(Path::prelude("Cow"))
232            .type_params(type_params!(T))
233            .composite(Fields::unnamed().field(|f| f.ty::<T>()))
234    }
235}
236
237impl<K, V> TypeInfo for BTreeMap<K, V>
238where
239    K: TypeInfo + 'static,
240    V: TypeInfo + 'static,
241{
242    type Identity = Self;
243
244    fn type_info() -> Type {
245        Type::builder()
246            .path(Path::prelude("BTreeMap"))
247            .type_params(type_params![K, V])
248            .composite(Fields::unnamed().field(|f| f.ty::<[(K, V)]>()))
249    }
250}
251
252impl<T> TypeInfo for BTreeSet<T>
253where
254    T: TypeInfo + 'static,
255{
256    type Identity = Self;
257
258    fn type_info() -> Type {
259        Type::builder()
260            .path(Path::prelude("BTreeSet"))
261            .type_params(type_params![T])
262            .composite(Fields::unnamed().field(|f| f.ty::<[T]>()))
263    }
264}
265
266impl<T> TypeInfo for BinaryHeap<T>
267where
268    T: TypeInfo + 'static,
269{
270    type Identity = Self;
271
272    fn type_info() -> Type {
273        Type::builder()
274            .path(Path::prelude("BinaryHeap"))
275            .type_params(type_params![T])
276            .composite(Fields::unnamed().field(|f| f.ty::<[T]>()))
277    }
278}
279
280impl<T> TypeInfo for Box<T>
281where
282    T: TypeInfo + ?Sized + 'static,
283{
284    type Identity = T;
285
286    fn type_info() -> Type {
287        Self::Identity::type_info()
288    }
289}
290
291impl<T> TypeInfo for Rc<T>
292where
293    T: TypeInfo + ?Sized + 'static,
294{
295    type Identity = T;
296
297    fn type_info() -> Type {
298        Self::Identity::type_info()
299    }
300}
301
302impl<T> TypeInfo for Arc<T>
303where
304    T: TypeInfo + ?Sized + 'static,
305{
306    type Identity = T;
307
308    fn type_info() -> Type {
309        Self::Identity::type_info()
310    }
311}
312
313impl<T> TypeInfo for &T
314where
315    T: TypeInfo + ?Sized + 'static,
316{
317    type Identity = T;
318
319    fn type_info() -> Type {
320        Self::Identity::type_info()
321    }
322}
323
324impl<T> TypeInfo for &mut T
325where
326    T: TypeInfo + ?Sized + 'static,
327{
328    type Identity = T;
329
330    fn type_info() -> Type {
331        Self::Identity::type_info()
332    }
333}
334
335impl<T> TypeInfo for [T]
336where
337    T: TypeInfo + 'static,
338{
339    type Identity = Self;
340
341    fn type_info() -> Type {
342        TypeDefSequence::of::<T>().into()
343    }
344}
345
346impl TypeInfo for str {
347    type Identity = Self;
348
349    fn type_info() -> Type {
350        TypeDefPrimitive::Str.into()
351    }
352}
353
354impl TypeInfo for String {
355    type Identity = str;
356
357    fn type_info() -> Type {
358        Self::Identity::type_info()
359    }
360}
361
362pub(crate) type PhantomIdentity = PhantomData<()>;
363
364impl<T> TypeInfo for PhantomData<T> {
365    type Identity = PhantomIdentity;
366
367    fn type_info() -> Type {
368        // Fields of this type should be filtered out and never appear in the type graph.
369        Type::builder()
370            .path(Path::prelude("PhantomData"))
371            .docs(&["PhantomData placeholder, this type should be filtered out"])
372            .composite(Fields::unit())
373    }
374}
375
376impl<T> TypeInfo for scale::Compact<T>
377where
378    T: TypeInfo + 'static,
379{
380    type Identity = Self;
381    fn type_info() -> Type {
382        TypeDefCompact::new(MetaType::new::<T>()).into()
383    }
384}
385
386impl<Idx> TypeInfo for Range<Idx>
387where
388    Idx: TypeInfo + 'static + PartialOrd + fmt::Debug,
389{
390    type Identity = Self;
391    fn type_info() -> Type {
392        Type::builder()
393            .path(Path::prelude("Range"))
394            .type_params(type_params![Idx])
395            .composite(
396                Fields::named()
397                    .field(|f| f.name("start").ty::<Idx>().type_name("Idx"))
398                    .field(|f| f.name("end").ty::<Idx>().type_name("Idx")),
399            )
400    }
401}
402
403impl<Idx> TypeInfo for RangeInclusive<Idx>
404where
405    Idx: TypeInfo + 'static + PartialOrd + fmt::Debug,
406{
407    type Identity = Self;
408    fn type_info() -> Type {
409        Type::builder()
410            .path(Path::prelude("RangeInclusive"))
411            .type_params(type_params![Idx])
412            .composite(
413                Fields::named()
414                    .field(|f| f.name("start").ty::<Idx>().type_name("Idx"))
415                    .field(|f| f.name("end").ty::<Idx>().type_name("Idx")),
416            )
417    }
418}
419
420#[cfg(feature = "bit-vec")]
421mod bit_vec {
422    use super::*;
423
424    impl<T, O> TypeInfo for bitvec::vec::BitVec<T, O>
425    where
426        T: bitvec::store::BitStore + TypeInfo + 'static,
427        O: bitvec::order::BitOrder + TypeInfo + 'static,
428    {
429        type Identity = Self;
430
431        fn type_info() -> Type {
432            crate::TypeDefBitSequence::new::<T, O>().into()
433        }
434    }
435
436    impl TypeInfo for bitvec::order::Lsb0 {
437        type Identity = Self;
438
439        fn type_info() -> Type {
440            Type::builder()
441                .path(Path::new("Lsb0", "bitvec::order"))
442                .composite(Fields::unit())
443        }
444    }
445
446    impl TypeInfo for bitvec::order::Msb0 {
447        type Identity = Self;
448
449        fn type_info() -> Type {
450            Type::builder()
451                .path(Path::new("Msb0", "bitvec::order"))
452                .composite(Fields::unit())
453        }
454    }
455}