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