use crate::{
build::*,
*,
};
use core::marker::PhantomData;
#[cfg(not(feature = "std"))]
use alloc::{
boxed::Box,
string::String,
vec,
};
fn assert_type<T, E>(expected: E)
where
T: TypeInfo + ?Sized,
E: Into<Type>,
{
assert_eq!(T::type_info(), expected.into());
}
macro_rules! assert_type {
( $ty:ty, $expected:expr ) => {{
assert_type::<$ty, _>($expected)
}};
}
#[test]
fn primitives() {
assert_type!(bool, TypeDefPrimitive::Bool);
assert_type!(&str, TypeDefPrimitive::Str);
assert_type!(i8, TypeDefPrimitive::I8);
assert_type!([bool], TypeDefSequence::new(meta_type::<bool>()));
}
#[test]
fn prelude_items() {
assert_type!(String, TypeDefPrimitive::Str);
assert_type!(
Option<u128>,
Type::builder()
.path(Path::prelude("Option"))
.type_params(tuple_meta_type!(u128))
.variant(
Variants::with_fields()
.variant_unit("None")
.variant("Some", Fields::unnamed().field_of::<u128>("T"))
)
);
assert_type!(
Result<bool, String>,
Type::builder()
.path(Path::prelude("Result"))
.type_params(tuple_meta_type!(bool, String))
.variant(
Variants::with_fields()
.variant("Ok", Fields::unnamed().field_of::<bool>("T"))
.variant("Err", Fields::unnamed().field_of::<String>("E"))
)
);
assert_type!(PhantomData<i32>, TypeDefPhantom::new(meta_type::<i32>()));
}
#[test]
fn tuple_primitives() {
assert_type!((), TypeDefTuple::new(tuple_meta_type!()));
assert_type!((bool,), TypeDefTuple::new(tuple_meta_type!(bool)));
assert_type!(
(bool, String),
TypeDefTuple::new(tuple_meta_type!(bool, String))
);
assert_type!(
((i8, i16), (u32, u64)),
TypeDefTuple::new(vec![meta_type::<(i8, i16)>(), meta_type::<(u32, u64)>(),])
);
}
#[test]
fn array_primitives() {
assert_type!([bool; 3], TypeDefArray::new(3, meta_type::<bool>()));
assert_type!([[i32; 5]; 5], TypeDefArray::new(5, meta_type::<[i32; 5]>()));
assert_type!([bool], TypeDefSequence::new(meta_type::<bool>()));
assert_type!(Vec<bool>, TypeDefSequence::new(meta_type::<bool>()));
}
#[test]
fn struct_with_generics() {
#[allow(unused)]
struct MyStruct<T> {
data: T,
}
impl<T> TypeInfo for MyStruct<T>
where
T: TypeInfo + 'static,
{
type Identity = Self;
fn type_info() -> Type {
Type::builder()
.path(Path::new("MyStruct", module_path!()))
.type_params(tuple_meta_type!(T))
.composite(Fields::named().field_of::<T>("data", "T"))
.into()
}
}
let struct_bool_type_info = Type::builder()
.path(Path::from_segments(vec!["scale_info", "tests", "MyStruct"]).unwrap())
.type_params(tuple_meta_type!(bool))
.composite(Fields::named().field_of::<bool>("data", "T"));
assert_type!(MyStruct<bool>, struct_bool_type_info);
type SelfTyped = MyStruct<Box<MyStruct<bool>>>;
let expected_type = Type::builder()
.path(Path::new("MyStruct", "scale_info::tests"))
.type_params(tuple_meta_type!(Box<MyStruct<bool>>))
.composite(Fields::named().field_of::<Box<MyStruct<bool>>>("data", "T"));
assert_type!(SelfTyped, expected_type);
}
#[test]
fn basic_struct_with_phantoms() {
#[allow(unused)]
struct SomeStruct<T> {
a: u8,
marker: PhantomData<T>,
}
impl<T> TypeInfo for SomeStruct<T>
where
T: TypeInfo + 'static,
{
type Identity = Self;
fn type_info() -> Type {
Type::builder()
.path(Path::new("SomeStruct", module_path!()))
.type_params(tuple_meta_type!(T))
.composite(Fields::named().field_of::<u8>("a", "u8"))
}
}
let struct_bool_type_info = Type::builder()
.path(Path::from_segments(vec!["scale_info", "tests", "SomeStruct"]).unwrap())
.type_params(tuple_meta_type!(bool))
.composite(Fields::named().field_of::<u8>("a", "u8"));
assert_type!(SomeStruct<bool>, struct_bool_type_info);
}