use alloc::boxed::Box;
use alloc::collections::BTreeMap;
use alloc::string::String;
use alloc::vec::Vec;
use crate::key_path;
use crate::key_path::GetTypePath;
use crate::struct_::StructValue;
use crate::type_info::GetMeta;
use crate::DescribeType;
use crate::FromReflect;
use crate::GetField;
use crate::Reflect;
use crate::Struct;
use crate::Value;
#[derive(Reflect, Default, Clone, Eq, PartialEq, Debug)]
#[reflect(crate_name(crate))]
struct Foo {
field: i32,
}
#[test]
fn accessing_fields() {
let foo = Foo { field: 42 };
let struct_ = foo.reflect_ref().as_struct().unwrap();
let value = struct_
.field("field")
.unwrap()
.downcast_ref::<i32>()
.unwrap();
assert_eq!(*value, 42);
let value: Value = struct_.to_value();
assert_eq!(value.get_field::<i32>("field").unwrap(), &42);
assert_eq!(value.get_field::<i32>("field".to_owned()).unwrap(), &42);
}
#[test]
fn patching() {
let mut foo = Foo { field: 42 };
let patch = StructValue::default().with_field("field", 1337);
foo.patch(&patch);
assert_eq!(foo.field, 1337);
}
#[test]
fn patching_struct_value() {
let mut value = StructValue::default().with_field("field", 42);
let patch = StructValue::default().with_field("field", 1337);
value.patch(&patch);
assert_eq!(
value.field("field").unwrap().downcast_ref::<i32>().unwrap(),
&1337
);
}
#[test]
fn from_reflect() {
let foo = Foo::default();
let foo_reflect: &dyn Reflect = &foo;
let foo = Foo::from_reflect(foo_reflect).unwrap();
assert_eq!(foo.field, 0);
}
#[test]
fn fields() {
let foo = Foo::default();
for (name, value) in foo.fields() {
if name == "field" {
assert_eq!(foo.field, i32::from_reflect(value).unwrap());
} else {
panic!("Unknown field {name:?}");
}
}
}
#[test]
fn struct_value_from_reflect() {
let value = StructValue::default().with_field("foo", 42);
let reflect = value.as_reflect();
let value = StructValue::from_reflect(reflect).unwrap();
assert_eq!(
value.field("foo").unwrap().downcast_ref::<i32>().unwrap(),
&42,
);
}
#[test]
fn box_dyn_reflect_as_reflect() {
let foo = Foo::default();
let mut box_dyn_reflect = Box::new(foo) as Box<dyn Reflect>;
assert_eq!(
box_dyn_reflect
.reflect_ref()
.as_struct()
.unwrap()
.field("field")
.unwrap()
.downcast_ref::<i32>()
.unwrap(),
&0,
);
box_dyn_reflect.patch(&StructValue::default().with_field("field", 42));
assert_eq!(
box_dyn_reflect
.reflect_ref()
.as_struct()
.unwrap()
.field("field")
.unwrap()
.downcast_ref::<i32>()
.unwrap(),
&42,
);
let foo = Foo::from_reflect(box_dyn_reflect.as_reflect()).unwrap();
assert_eq!(foo, Foo { field: 42 });
}
#[test]
fn deeply_nested() {
#[derive(Reflect, Clone, Debug)]
#[reflect(crate_name(crate))]
struct Foo {
bar: Bar,
}
#[derive(Reflect, Clone, Debug)]
#[reflect(crate_name(crate))]
struct Bar {
baz: Baz,
}
#[derive(Reflect, Clone, Debug)]
#[reflect(crate_name(crate))]
struct Baz {
qux: i32,
}
let foo = Foo {
bar: Bar {
baz: Baz { qux: 42 },
},
};
let &forty_two = (|| {
foo.get_field::<Bar>("bar")?
.get_field::<Baz>("baz")?
.get_field::<i32>("qux")
})()
.unwrap();
assert_eq!(forty_two, 42);
}
#[test]
fn from_reflect_with_value() {
#[derive(Debug, Clone, Reflect, Default)]
#[reflect(crate_name(crate))]
pub struct Foo {
pub number: Number,
}
#[derive(Debug, Clone, Reflect, Default)]
#[reflect(crate_name(crate))]
pub enum Number {
#[default]
One,
Two,
Three,
}
let value = StructValue::new().with_field("number", Number::One);
assert!(Foo::from_reflect(&value).is_some());
}
#[test]
fn accessing_docs_in_type_info() {
#[derive(Reflect, Clone, Debug)]
#[reflect(crate_name(crate))]
struct Foo {
inner: Vec<BTreeMap<String, Vec<Option<Inner>>>>,
}
#[derive(Reflect, Clone, Debug)]
#[reflect(crate_name(crate))]
enum Inner {
Variant {
field: String,
},
}
let type_info = <Foo as DescribeType>::type_descriptor();
assert_eq!(
type_info.get_type().docs(),
&[" Here are the docs.", "", " Foo bar."]
);
let variant_info = type_info
.get_type()
.type_at(&key_path!(.inner[0]["map_key"][0]::Some.0::Variant))
.unwrap()
.as_variant()
.unwrap();
let field = variant_info.field_types().next().unwrap();
assert_eq!(field.name().unwrap(), "field");
assert_eq!(field.docs(), &[" Bingo!"]);
}