From c30db9a28e4d7787905aeef6db6b3af86bac01db Mon Sep 17 00:00:00 2001 From: Night_Hunter Date: Thu, 26 Dec 2024 01:41:03 +1300 Subject: [PATCH 1/5] use trait based loader --- .../src/file_system/de/array.rs | 8 ++--- .../src/file_system/de/enums.rs | 16 ++++----- .../src/file_system/de/list.rs | 10 +++--- .../src/file_system/de/map.rs | 8 ++--- .../src/file_system/de/mod.rs | 32 +++++++++-------- .../src/file_system/de/set.rs | 10 +++--- .../src/file_system/de/structs.rs | 18 +++++----- .../src/file_system/de/tuple.rs | 14 ++++---- .../src/file_system/de/tuple_struct.rs | 14 ++++---- .../src/file_system/de/value.rs | 36 ++++++++++--------- 10 files changed, 86 insertions(+), 80 deletions(-) diff --git a/crates/bevy_editor_settings/src/file_system/de/array.rs b/crates/bevy_editor_settings/src/file_system/de/array.rs index 9610a5e3..7b52eb7a 100644 --- a/crates/bevy_editor_settings/src/file_system/de/array.rs +++ b/crates/bevy_editor_settings/src/file_system/de/array.rs @@ -3,7 +3,7 @@ use bevy::{ reflect::{Array, ArrayInfo}, }; -use super::LoadStructure; +use super::{LoadStructure, StructureLoader}; pub struct LoadArray<'a> { pub array_info: &'a ArrayInfo, @@ -11,8 +11,8 @@ pub struct LoadArray<'a> { pub toml_array: &'a toml::value::Array, } -impl LoadArray<'_> { - pub fn load_array(self) { +impl StructureLoader for LoadArray<'_> { + fn load(self) { if self.toml_array.len() != self.array_info.capacity() { warn!( "Preferences: Expected Array length {}, got {}", @@ -57,7 +57,7 @@ mod tests { toml_array: toml_value.as_array().unwrap(), array: &mut array, } - .load_array(); + .load(); assert_eq!(array, [1, 2]); } } diff --git a/crates/bevy_editor_settings/src/file_system/de/enums.rs b/crates/bevy_editor_settings/src/file_system/de/enums.rs index 4f11979c..d2670748 100644 --- a/crates/bevy_editor_settings/src/file_system/de/enums.rs +++ b/crates/bevy_editor_settings/src/file_system/de/enums.rs @@ -3,7 +3,7 @@ use bevy::{ reflect::{DynamicEnum, DynamicVariant, Enum, EnumInfo, VariantInfo}, }; -use super::{structs::LoadStruct, tuple::LoadTuple}; +use super::{structs::LoadStruct, tuple::LoadTuple, StructureLoader}; pub struct LoadEnum<'a> { pub enum_info: &'a EnumInfo, @@ -11,8 +11,8 @@ pub struct LoadEnum<'a> { pub enm: &'a mut dyn Enum, } -impl LoadEnum<'_> { - pub fn load_enum(self) { +impl StructureLoader for LoadEnum<'_> { + fn load(self) { match self.toml_value { toml::Value::String(str_val) => { if let Some(VariantInfo::Unit(variant)) = self.enum_info.variant(str_val) { @@ -54,7 +54,7 @@ impl LoadEnum<'_> { table: map, strct: &mut dyn_struct, } - .load_struct(); + .load(); let dyn_enum = DynamicEnum::new( variant_info.name(), @@ -85,7 +85,7 @@ impl LoadEnum<'_> { table: array, tuple: &mut dyn_tuple, } - .load_tuple(); + .load(); let dyn_enum = DynamicEnum::new( variant_info.name(), @@ -131,7 +131,7 @@ mod tests { toml_value: &toml_value, enm: &mut enum_test, } - .load_enum(); + .load(); assert_eq!(enum_test, TestEnum::Variant1); } @@ -156,7 +156,7 @@ mod tests { toml_value: &toml_value, enm: &mut enum_test, } - .load_enum(); + .load(); assert_eq!( enum_test, @@ -187,7 +187,7 @@ mod tests { toml_value: &toml_value, enm: &mut enum_test, } - .load_enum(); + .load(); assert_eq!(enum_test, TestEnum::Variant4(1, 2)); } diff --git a/crates/bevy_editor_settings/src/file_system/de/list.rs b/crates/bevy_editor_settings/src/file_system/de/list.rs index 8b852bb6..766fc1ef 100644 --- a/crates/bevy_editor_settings/src/file_system/de/list.rs +++ b/crates/bevy_editor_settings/src/file_system/de/list.rs @@ -5,7 +5,7 @@ use bevy::{ use crate::MergeStrategy; -use super::LoadStructure; +use super::{LoadStructure, StructureLoader}; pub struct LoadList<'a> { pub list_info: &'a ListInfo, @@ -14,8 +14,8 @@ pub struct LoadList<'a> { pub custom_attributes: Option<&'a CustomAttributes>, } -impl LoadList<'_> { - pub fn load_list(self) { +impl StructureLoader for LoadList<'_> { + fn load(self) { let merge_strategy = self .custom_attributes .and_then(|attrs| attrs.get::()) @@ -68,7 +68,7 @@ mod tests { toml_array: toml_value.as_array().unwrap(), custom_attributes: None, } - .load_list(); + .load(); assert_eq!(list, vec![1, 2]); } @@ -104,7 +104,7 @@ mod tests { toml_array: toml_value.as_array().unwrap(), custom_attributes: Some(attrs), } - .load_list(); + .load(); assert_eq!(list.list, vec![1, 2, 3, 4]); } } diff --git a/crates/bevy_editor_settings/src/file_system/de/map.rs b/crates/bevy_editor_settings/src/file_system/de/map.rs index 6754d685..64e3d99d 100644 --- a/crates/bevy_editor_settings/src/file_system/de/map.rs +++ b/crates/bevy_editor_settings/src/file_system/de/map.rs @@ -3,7 +3,7 @@ use bevy::{ reflect::{Map, MapInfo}, }; -use super::LoadStructure; +use super::{LoadStructure, StructureLoader}; pub struct LoadMap<'a> { pub map: &'a mut dyn Map, @@ -11,8 +11,8 @@ pub struct LoadMap<'a> { pub table: &'a toml::value::Table, } -impl LoadMap<'_> { - pub fn load_map(self) { +impl StructureLoader for LoadMap<'_> { + fn load(self) { if !self .map_info .key_info() @@ -66,7 +66,7 @@ mod tests { map: &mut map, table: &table, } - .load_map(); + .load(); assert_eq!(map.get("key"), Some(&1)); } diff --git a/crates/bevy_editor_settings/src/file_system/de/mod.rs b/crates/bevy_editor_settings/src/file_system/de/mod.rs index 84c27e45..a7ca30d3 100644 --- a/crates/bevy_editor_settings/src/file_system/de/mod.rs +++ b/crates/bevy_editor_settings/src/file_system/de/mod.rs @@ -44,6 +44,10 @@ pub fn load_toml_file(path: impl AsRef) -> Result { pub type_info: &'static TypeInfo, pub table: &'a toml::Value, @@ -51,8 +55,8 @@ pub struct LoadStructure<'a> { pub custom_attributes: Option<&'a CustomAttributes>, } -impl LoadStructure<'_> { - pub fn load(self) { +impl StructureLoader for LoadStructure<'_> { + fn load(self) { match self.type_info { TypeInfo::Opaque(opaque_info) => { LoadValue { @@ -60,7 +64,7 @@ impl LoadStructure<'_> { toml_value: self.table, value: self.structure, } - .load_value(); + .load(); } TypeInfo::Struct(struct_info) => { if let Some(table) = self.table.as_table() { @@ -73,7 +77,7 @@ impl LoadStructure<'_> { table, strct, } - .load_struct(); + .load(); } } TypeInfo::TupleStruct(tuple_struct_info) => { @@ -87,7 +91,7 @@ impl LoadStructure<'_> { table: array_value, tuple_struct, } - .load_tuple_struct(); + .load(); } } TypeInfo::Tuple(tuple_info) => { @@ -101,7 +105,7 @@ impl LoadStructure<'_> { table: array_value, tuple, } - .load_tuple(); + .load(); } } TypeInfo::List(list_info) => { @@ -116,7 +120,7 @@ impl LoadStructure<'_> { toml_array: array_value, custom_attributes: self.custom_attributes, } - .load_list(); + .load(); } } TypeInfo::Array(array_info) => { @@ -130,7 +134,7 @@ impl LoadStructure<'_> { array, toml_array: array_value, } - .load_array(); + .load(); } } TypeInfo::Map(map_info) => { @@ -144,7 +148,7 @@ impl LoadStructure<'_> { map, table: toml_map, } - .load_map(); + .load(); } } TypeInfo::Set(set_info) => { @@ -158,7 +162,7 @@ impl LoadStructure<'_> { set, toml_array, } - .load_set(); + .load(); } } TypeInfo::Enum(enum_info) => { @@ -172,7 +176,7 @@ impl LoadStructure<'_> { enm, toml_value: self.table, } - .load_enum(); + .load(); } } } @@ -216,7 +220,7 @@ pub fn load_preferences(world: &mut World, table: toml::Table, settings_type: Se table, strct, } - .load_struct(); + .load(); } } } @@ -248,7 +252,7 @@ pub fn load_preferences(world: &mut World, table: toml::Table, settings_type: Se enm, toml_value: value, } - .load_enum(); + .load(); } } } @@ -283,7 +287,7 @@ pub fn load_preferences(world: &mut World, table: toml::Table, settings_type: Se table: array_value, tuple_struct, } - .load_tuple_struct(); + .load(); } } } diff --git a/crates/bevy_editor_settings/src/file_system/de/set.rs b/crates/bevy_editor_settings/src/file_system/de/set.rs index 2881062d..c152dafe 100644 --- a/crates/bevy_editor_settings/src/file_system/de/set.rs +++ b/crates/bevy_editor_settings/src/file_system/de/set.rs @@ -1,6 +1,6 @@ use bevy::reflect::{Set, SetInfo}; -use super::value::LoadValue; +use super::{value::LoadValue, StructureLoader}; pub struct LoadSet<'a> { pub set: &'a mut dyn Set, @@ -8,8 +8,8 @@ pub struct LoadSet<'a> { pub toml_array: &'a toml::value::Array, } -impl LoadSet<'_> { - pub fn load_set(self) { +impl StructureLoader for LoadSet<'_> { + fn load(self) { for toml_value in self.toml_array.iter() { let mut value = super::default::default_value(&self.set_info.value_ty()).unwrap(); @@ -18,7 +18,7 @@ impl LoadSet<'_> { toml_value, value: value.as_mut(), } - .load_value(); + .load(); self.set.insert_boxed(value); } @@ -47,7 +47,7 @@ mod tests { toml_array: toml_value.as_array().unwrap(), set: &mut set, } - .load_set(); + .load(); assert_eq!(set.len(), 2); assert!(set.contains(&1)); diff --git a/crates/bevy_editor_settings/src/file_system/de/structs.rs b/crates/bevy_editor_settings/src/file_system/de/structs.rs index 0b7295db..16063ca8 100644 --- a/crates/bevy_editor_settings/src/file_system/de/structs.rs +++ b/crates/bevy_editor_settings/src/file_system/de/structs.rs @@ -1,6 +1,6 @@ use bevy::reflect::Struct; -use super::{struct_utils::StructLikeInfo, LoadStructure}; +use super::{struct_utils::StructLikeInfo, LoadStructure, StructureLoader}; pub struct LoadStruct<'a> { pub struct_info: &'a dyn StructLikeInfo, @@ -8,8 +8,8 @@ pub struct LoadStruct<'a> { pub strct: &'a mut dyn Struct, } -impl LoadStruct<'_> { - pub fn load_struct(self) { +impl StructureLoader for LoadStruct<'_> { + fn load(self) { let struct_info = self.struct_info; let table = self.table; let strct = self.strct; @@ -66,7 +66,7 @@ mod tests { #[tracing_test::traced_test] #[test] - fn load_struct_basic_values() { + fn load_basic_values() { let mut struct_info = Values::default(); let table = values_toml(); @@ -75,7 +75,7 @@ mod tests { table: &table, strct: &mut struct_info, } - .load_struct(); + .load(); assert_eq!( struct_info, @@ -92,7 +92,7 @@ mod tests { values: Values, } - fn load_struct_with_struct_toml() -> toml::value::Table { + fn load_with_struct_toml() -> toml::value::Table { let mut table = toml::value::Table::default(); table.insert("values".to_string(), toml::Value::Table(values_toml())); table @@ -100,17 +100,17 @@ mod tests { #[tracing_test::traced_test] #[test] - fn load_struct_with_struct() { + fn load_with_struct() { let mut struct_info = StructWithStruct::default(); - let table = load_struct_with_struct_toml(); + let table = load_with_struct_toml(); LoadStruct { struct_info: struct_info.reflect_type_info().as_struct().unwrap(), table: &table, strct: &mut struct_info, } - .load_struct(); + .load(); assert_eq!( struct_info, diff --git a/crates/bevy_editor_settings/src/file_system/de/tuple.rs b/crates/bevy_editor_settings/src/file_system/de/tuple.rs index 13b0ca32..494c5e4b 100644 --- a/crates/bevy_editor_settings/src/file_system/de/tuple.rs +++ b/crates/bevy_editor_settings/src/file_system/de/tuple.rs @@ -1,6 +1,6 @@ use bevy::reflect::Tuple; -use super::{tuple_utils::TupleLikeInfo, LoadStructure}; +use super::{tuple_utils::TupleLikeInfo, LoadStructure, StructureLoader}; pub struct LoadTuple<'a> { pub tuple_info: &'a dyn TupleLikeInfo, @@ -8,8 +8,8 @@ pub struct LoadTuple<'a> { pub tuple: &'a mut dyn Tuple, } -impl LoadTuple<'_> { - pub fn load_tuple(self) { +impl StructureLoader for LoadTuple<'_> { + fn load(self) { for i in 0..self.tuple_info.field_len() { let Some(toml_value) = self.table.get(i) else { continue; @@ -41,7 +41,7 @@ mod tests { #[tracing_test::traced_test] #[test] - fn load_tuple() { + fn load() { let mut tuple = (0, 0); let toml_value = tuple_test_toml(); @@ -50,7 +50,7 @@ mod tests { table: toml_value.as_array().unwrap(), tuple: &mut tuple, } - .load_tuple(); + .load(); assert_eq!(tuple, (1, 2)); } @@ -60,7 +60,7 @@ mod tests { #[tracing_test::traced_test] #[test] - fn load_tuple_struct_struct() { + fn load_struct_struct() { let mut tuple = ((0, 0), (0, 0)); let toml_value = tuple_struct_struct_toml(); @@ -69,7 +69,7 @@ mod tests { table: toml_value.as_array().unwrap(), tuple: &mut tuple, } - .load_tuple(); + .load(); assert_eq!(tuple, ((1, 2), (1, 2))); } diff --git a/crates/bevy_editor_settings/src/file_system/de/tuple_struct.rs b/crates/bevy_editor_settings/src/file_system/de/tuple_struct.rs index 17200f90..7776bdba 100644 --- a/crates/bevy_editor_settings/src/file_system/de/tuple_struct.rs +++ b/crates/bevy_editor_settings/src/file_system/de/tuple_struct.rs @@ -1,6 +1,6 @@ use bevy::reflect::TupleStruct; -use super::{tuple_utils::TupleLikeInfo, LoadStructure}; +use super::{tuple_utils::TupleLikeInfo, LoadStructure, StructureLoader}; pub struct LoadTupleStruct<'a> { pub tuple_struct_info: &'a dyn TupleLikeInfo, @@ -8,8 +8,8 @@ pub struct LoadTupleStruct<'a> { pub tuple_struct: &'a mut dyn TupleStruct, } -impl LoadTupleStruct<'_> { - pub fn load_tuple_struct(self) { +impl StructureLoader for LoadTupleStruct<'_> { + fn load(self) { for i in 0..self.tuple_struct_info.field_len() { let Some(toml_value) = self.table.get(i) else { continue; @@ -48,7 +48,7 @@ mod tests { #[tracing_test::traced_test] #[test] - fn load_tuple_struct() { + fn load() { let mut tuple_struct = TupleStructTest::default(); let toml_value = tuple_struct_test_toml(); @@ -57,7 +57,7 @@ mod tests { table: toml_value.as_array().unwrap(), tuple_struct: &mut tuple_struct, } - .load_tuple_struct(); + .load(); assert_eq!(tuple_struct, TupleStructTest(1, 2)); } @@ -70,7 +70,7 @@ mod tests { #[tracing_test::traced_test] #[test] - fn load_tuple_struct_struct() { + fn load_struct() { let mut tuple_struct = TupleStructStruct::default(); let toml_value = tuple_struct_struct_toml(); @@ -79,7 +79,7 @@ mod tests { table: toml_value.as_array().unwrap(), tuple_struct: &mut tuple_struct, } - .load_tuple_struct(); + .load(); assert_eq!(tuple_struct, TupleStructStruct(TupleStructTest(1, 2))); } diff --git a/crates/bevy_editor_settings/src/file_system/de/value.rs b/crates/bevy_editor_settings/src/file_system/de/value.rs index 3d6e0979..b7f36822 100644 --- a/crates/bevy_editor_settings/src/file_system/de/value.rs +++ b/crates/bevy_editor_settings/src/file_system/de/value.rs @@ -1,14 +1,16 @@ use bevy::prelude::warn; use bevy::reflect::{PartialReflect, Type}; +use super::StructureLoader; + pub struct LoadValue<'a> { pub value_info: &'a Type, pub toml_value: &'a toml::Value, pub value: &'a mut dyn PartialReflect, } -impl LoadValue<'_> { - pub fn load_value(self) { +impl StructureLoader for LoadValue<'_> { + fn load(self) { let value_info = self.value_info; match self.toml_value { toml::Value::String(str_val) => { @@ -84,7 +86,7 @@ mod tests { toml_value, value: &mut value, } - .load_value(); + .load(); assert_eq!(value, "Hello"); } @@ -98,7 +100,7 @@ mod tests { toml_value, value: &mut value, } - .load_value(); + .load(); assert_eq!(value, std::f64::consts::PI); } @@ -112,7 +114,7 @@ mod tests { toml_value, value: &mut value, } - .load_value(); + .load(); assert_eq!(value, std::f32::consts::PI); } @@ -126,7 +128,7 @@ mod tests { toml_value, value: &mut value, } - .load_value(); + .load(); assert!(value); } @@ -140,7 +142,7 @@ mod tests { toml_value, value: &mut value, } - .load_value(); + .load(); assert_eq!(value, 42.0); } @@ -154,7 +156,7 @@ mod tests { toml_value, value: &mut value, } - .load_value(); + .load(); assert_eq!(value, 42.0); } @@ -168,7 +170,7 @@ mod tests { toml_value, value: &mut value, } - .load_value(); + .load(); assert_eq!(value, 42); } @@ -182,7 +184,7 @@ mod tests { toml_value, value: &mut value, } - .load_value(); + .load(); assert_eq!(value, 42); } @@ -196,7 +198,7 @@ mod tests { toml_value, value: &mut value, } - .load_value(); + .load(); assert_eq!(value, 42); } @@ -210,7 +212,7 @@ mod tests { toml_value, value: &mut value, } - .load_value(); + .load(); assert_eq!(value, 42); } @@ -224,7 +226,7 @@ mod tests { toml_value, value: &mut value, } - .load_value(); + .load(); assert_eq!(value, 42); } @@ -238,7 +240,7 @@ mod tests { toml_value, value: &mut value, } - .load_value(); + .load(); assert_eq!(value, 42); } @@ -252,7 +254,7 @@ mod tests { toml_value, value: &mut value, } - .load_value(); + .load(); assert_eq!(value, 42); } @@ -266,7 +268,7 @@ mod tests { toml_value, value: &mut value, } - .load_value(); + .load(); assert_eq!(value, 42); } @@ -280,7 +282,7 @@ mod tests { toml_value, value: &mut value, } - .load_value(); + .load(); assert_eq!(value, 42); } } From 34bbad471938ab67810d89dae0d762d6ef446eda Mon Sep 17 00:00:00 2001 From: Night_Hunter Date: Thu, 26 Dec 2024 02:25:50 +1300 Subject: [PATCH 2/5] start on diff --- crates/bevy_editor_settings/src/diff/mod.rs | 73 +++++++++++++++++++ .../bevy_editor_settings/src/diff/structs.rs | 0 crates/bevy_editor_settings/src/lib.rs | 1 + 3 files changed, 74 insertions(+) create mode 100644 crates/bevy_editor_settings/src/diff/mod.rs create mode 100644 crates/bevy_editor_settings/src/diff/structs.rs diff --git a/crates/bevy_editor_settings/src/diff/mod.rs b/crates/bevy_editor_settings/src/diff/mod.rs new file mode 100644 index 00000000..6c54fac2 --- /dev/null +++ b/crates/bevy_editor_settings/src/diff/mod.rs @@ -0,0 +1,73 @@ +mod structs; + +use bevy::reflect::{PartialReflect, Reflect, Struct, TypeInfo}; + +pub trait Diff: Reflect { + fn diff(&self, other: &Self) -> Vec; +} + +#[derive(Debug, Clone, PartialEq)] +struct DiffResult { + field_name: String, + old_value: String, + new_value: String, +} + +#[derive(Debug, Clone, Reflect)] +struct SomeStruct { + a: u32, + b: u32, +} + +impl Diff for SomeStruct { + fn diff(&self, other: &Self) -> Vec { + let mut results = Vec::new(); + let struct_self = self.as_partial_reflect().reflect_ref().as_struct().unwrap(); + let struct_other = other + .as_partial_reflect() + .reflect_ref() + .as_struct() + .unwrap(); + + for index in 0..struct_self.field_len() { + let field = struct_self.field_at(index).unwrap(); + let field_other = struct_other.field_at(index).unwrap(); + let type_info = field.get_represented_type_info().unwrap(); + if let TypeInfo::Opaque(_) = type_info { + if field.represents::() { + let value = field.try_downcast_ref::().unwrap(); + let value_other = field_other.try_downcast_ref::().unwrap(); + if value != value_other { + results.push(DiffResult { + field_name: struct_self.name_at(index).unwrap().to_string(), + old_value: value.to_string(), + new_value: value_other.to_string(), + }); + } + } + } + } + results + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_diff() { + let a = SomeStruct { a: 1, b: 2 }; + let b = SomeStruct { a: 1, b: 3 }; + let res = a.diff(&b); + println!("{:?}", res); + assert_eq!( + res, + vec![DiffResult { + field_name: "b".to_string(), + old_value: "2".to_string(), + new_value: "3".to_string(), + }] + ); + } +} diff --git a/crates/bevy_editor_settings/src/diff/structs.rs b/crates/bevy_editor_settings/src/diff/structs.rs new file mode 100644 index 00000000..e69de29b diff --git a/crates/bevy_editor_settings/src/lib.rs b/crates/bevy_editor_settings/src/lib.rs index 0fdf291e..5abc4fb7 100644 --- a/crates/bevy_editor_settings/src/lib.rs +++ b/crates/bevy_editor_settings/src/lib.rs @@ -3,6 +3,7 @@ use bevy::prelude::*; mod file_system; +mod diff; /// Annotation for a type to show which type of settings it belongs to. #[derive(Debug, Clone, PartialEq, Eq, Reflect)] From bb3b85449a385e0b8757f4eb41729ec373cd38cc Mon Sep 17 00:00:00 2001 From: Night_Hunter Date: Thu, 26 Dec 2024 02:39:55 +1300 Subject: [PATCH 3/5] move to a toml based input --- .../src/file_system/de/array.rs | 19 +++-- .../src/file_system/de/enums.rs | 26 +++--- .../src/file_system/de/list.rs | 18 ++--- .../src/file_system/de/map.rs | 15 ++-- .../src/file_system/de/mod.rs | 81 ++++++------------- .../src/file_system/de/set.rs | 15 ++-- .../src/file_system/de/structs.rs | 18 ++--- .../src/file_system/de/tuple.rs | 18 ++--- .../src/file_system/de/tuple_struct.rs | 18 ++--- .../src/file_system/de/value.rs | 54 +++++-------- 10 files changed, 112 insertions(+), 170 deletions(-) diff --git a/crates/bevy_editor_settings/src/file_system/de/array.rs b/crates/bevy_editor_settings/src/file_system/de/array.rs index 7b52eb7a..e34af31e 100644 --- a/crates/bevy_editor_settings/src/file_system/de/array.rs +++ b/crates/bevy_editor_settings/src/file_system/de/array.rs @@ -8,22 +8,23 @@ use super::{LoadStructure, StructureLoader}; pub struct LoadArray<'a> { pub array_info: &'a ArrayInfo, pub array: &'a mut dyn Array, - pub toml_array: &'a toml::value::Array, } -impl StructureLoader for LoadArray<'_> { - fn load(self) { - if self.toml_array.len() != self.array_info.capacity() { +impl<'a> StructureLoader for LoadArray<'a> { + type Input = &'a toml::value::Array; + + fn load(self, input: Self::Input) { + if input.len() != self.array_info.capacity() { warn!( "Preferences: Expected Array length {}, got {}", self.array_info.capacity(), - self.toml_array.len() + input.len() ); return; } for i in 0..self.array_info.capacity() { - let Some(toml_value) = self.toml_array.get(i) else { + let Some(toml_value) = input.get(i) else { continue; }; @@ -31,11 +32,10 @@ impl StructureLoader for LoadArray<'_> { LoadStructure { type_info: field_mut.get_represented_type_info().unwrap(), - table: toml_value, structure: field_mut, custom_attributes: None, } - .load(); + .load(toml_value); } } } @@ -54,10 +54,9 @@ mod tests { let toml_value = toml::Value::Array(vec![toml::Value::Integer(1), toml::Value::Integer(2)]); LoadArray { array_info: array.reflect_type_info().as_array().unwrap(), - toml_array: toml_value.as_array().unwrap(), array: &mut array, } - .load(); + .load(toml_value.as_array().unwrap()); assert_eq!(array, [1, 2]); } } diff --git a/crates/bevy_editor_settings/src/file_system/de/enums.rs b/crates/bevy_editor_settings/src/file_system/de/enums.rs index d2670748..2fa2a493 100644 --- a/crates/bevy_editor_settings/src/file_system/de/enums.rs +++ b/crates/bevy_editor_settings/src/file_system/de/enums.rs @@ -7,13 +7,14 @@ use super::{structs::LoadStruct, tuple::LoadTuple, StructureLoader}; pub struct LoadEnum<'a> { pub enum_info: &'a EnumInfo, - pub toml_value: &'a toml::Value, pub enm: &'a mut dyn Enum, } -impl StructureLoader for LoadEnum<'_> { - fn load(self) { - match self.toml_value { +impl<'a> StructureLoader for LoadEnum<'a> { + type Input = &'a toml::Value; + + fn load(self, input: Self::Input) { + match input { toml::Value::String(str_val) => { if let Some(VariantInfo::Unit(variant)) = self.enum_info.variant(str_val) { let dyn_enum = DynamicEnum::new(variant.name(), DynamicVariant::Unit); @@ -51,10 +52,9 @@ impl StructureLoader for LoadEnum<'_> { LoadStruct { struct_info, - table: map, strct: &mut dyn_struct, } - .load(); + .load(map); let dyn_enum = DynamicEnum::new( variant_info.name(), @@ -82,10 +82,9 @@ impl StructureLoader for LoadEnum<'_> { LoadTuple { tuple_info: tuple_variant_info, - table: array, tuple: &mut dyn_tuple, } - .load(); + .load(array); let dyn_enum = DynamicEnum::new( variant_info.name(), @@ -97,7 +96,7 @@ impl StructureLoader for LoadEnum<'_> { } } _ => { - warn!("Preferences: Unsupported type: {:?}", self.toml_value); + warn!("Preferences: Unsupported type: {:?}", input); } } } @@ -128,10 +127,9 @@ mod tests { let toml_value = toml::Value::String("Variant1".to_string()); LoadEnum { enum_info: enum_test.reflect_type_info().as_enum().unwrap(), - toml_value: &toml_value, enm: &mut enum_test, } - .load(); + .load(&toml_value); assert_eq!(enum_test, TestEnum::Variant1); } @@ -153,10 +151,9 @@ mod tests { let toml_value = enum_test_toml(); LoadEnum { enum_info: enum_test.reflect_type_info().as_enum().unwrap(), - toml_value: &toml_value, enm: &mut enum_test, } - .load(); + .load(&toml_value); assert_eq!( enum_test, @@ -184,10 +181,9 @@ mod tests { let toml_value = enum_test_tuple_toml(); LoadEnum { enum_info: enum_test.reflect_type_info().as_enum().unwrap(), - toml_value: &toml_value, enm: &mut enum_test, } - .load(); + .load(&toml_value); assert_eq!(enum_test, TestEnum::Variant4(1, 2)); } diff --git a/crates/bevy_editor_settings/src/file_system/de/list.rs b/crates/bevy_editor_settings/src/file_system/de/list.rs index 766fc1ef..7b9edcb1 100644 --- a/crates/bevy_editor_settings/src/file_system/de/list.rs +++ b/crates/bevy_editor_settings/src/file_system/de/list.rs @@ -10,12 +10,13 @@ use super::{LoadStructure, StructureLoader}; pub struct LoadList<'a> { pub list_info: &'a ListInfo, pub list: &'a mut dyn List, - pub toml_array: &'a toml::value::Array, pub custom_attributes: Option<&'a CustomAttributes>, } -impl StructureLoader for LoadList<'_> { - fn load(self) { +impl<'a> StructureLoader for LoadList<'a> { + type Input = &'a toml::value::Array; + + fn load(self, input: Self::Input) { let merge_strategy = self .custom_attributes .and_then(|attrs| attrs.get::()) @@ -31,7 +32,7 @@ impl StructureLoader for LoadList<'_> { self.list.drain(); } - for toml_value in self.toml_array.iter() { + for toml_value in input.iter() { let Some(mut value) = super::default::default_data_type(item_info) else { warn!("Unable to create default value for list item"); return; @@ -39,11 +40,10 @@ impl StructureLoader for LoadList<'_> { LoadStructure { type_info: item_info, - table: toml_value, structure: value.as_mut(), custom_attributes: None, } - .load(); + .load(toml_value); self.list.push(value); } @@ -65,10 +65,9 @@ mod tests { LoadList { list_info: list.reflect_type_info().as_list().unwrap(), list: &mut list, - toml_array: toml_value.as_array().unwrap(), custom_attributes: None, } - .load(); + .load(toml_value.as_array().unwrap()); assert_eq!(list, vec![1, 2]); } @@ -101,10 +100,9 @@ mod tests { LoadList { list_info: list.list.reflect_type_info().as_list().unwrap(), list: &mut list.list, - toml_array: toml_value.as_array().unwrap(), custom_attributes: Some(attrs), } - .load(); + .load(toml_value.as_array().unwrap()); assert_eq!(list.list, vec![1, 2, 3, 4]); } } diff --git a/crates/bevy_editor_settings/src/file_system/de/map.rs b/crates/bevy_editor_settings/src/file_system/de/map.rs index 64e3d99d..8aec596a 100644 --- a/crates/bevy_editor_settings/src/file_system/de/map.rs +++ b/crates/bevy_editor_settings/src/file_system/de/map.rs @@ -8,11 +8,12 @@ use super::{LoadStructure, StructureLoader}; pub struct LoadMap<'a> { pub map: &'a mut dyn Map, pub map_info: &'a MapInfo, - pub table: &'a toml::value::Table, } -impl StructureLoader for LoadMap<'_> { - fn load(self) { +impl<'a> StructureLoader for LoadMap<'a> { + type Input = &'a toml::value::Table; + + fn load(self, input: Self::Input) { if !self .map_info .key_info() @@ -23,7 +24,7 @@ impl StructureLoader for LoadMap<'_> { return; } - for (key, toml_value) in self.table.iter() { + for (key, toml_value) in input.iter() { let Some(value_info) = self.map_info.value_info() else { warn!("Preferences: Expected Map value info"); return; @@ -36,11 +37,10 @@ impl StructureLoader for LoadMap<'_> { LoadStructure { type_info: value_info, - table: toml_value, structure: value.as_mut(), custom_attributes: None, } - .load(); + .load(toml_value); self.map.insert_boxed(Box::new(key.clone()), value); } @@ -64,9 +64,8 @@ mod tests { LoadMap { map_info: map.reflect_type_info().as_map().unwrap(), map: &mut map, - table: &table, } - .load(); + .load(&table); assert_eq!(map.get("key"), Some(&1)); } diff --git a/crates/bevy_editor_settings/src/file_system/de/mod.rs b/crates/bevy_editor_settings/src/file_system/de/mod.rs index a7ca30d3..2e5b0924 100644 --- a/crates/bevy_editor_settings/src/file_system/de/mod.rs +++ b/crates/bevy_editor_settings/src/file_system/de/mod.rs @@ -45,71 +45,70 @@ pub fn load_toml_file(path: impl AsRef) -> Result { pub type_info: &'static TypeInfo, - pub table: &'a toml::Value, pub structure: &'a mut dyn PartialReflect, pub custom_attributes: Option<&'a CustomAttributes>, } -impl StructureLoader for LoadStructure<'_> { - fn load(self) { +impl<'a> StructureLoader for LoadStructure<'a> { + type Input = &'a toml::Value; + + fn load(self, input: Self::Input) { match self.type_info { TypeInfo::Opaque(opaque_info) => { LoadValue { value_info: opaque_info.ty(), - toml_value: self.table, value: self.structure, } - .load(); + .load(input); } TypeInfo::Struct(struct_info) => { - if let Some(table) = self.table.as_table() { + if let Some(table) = input.as_table() { let ReflectMut::Struct(strct) = self.structure.reflect_mut() else { warn!("Preferences: Expected Struct"); return; }; LoadStruct { struct_info, - table, strct, } - .load(); + .load(table); } } TypeInfo::TupleStruct(tuple_struct_info) => { - if let Some(array_value) = self.table.as_array() { + if let Some(array_value) = input.as_array() { let ReflectMut::TupleStruct(tuple_struct) = self.structure.reflect_mut() else { warn!("Preferences: Expected TupleStruct"); return; }; LoadTupleStruct { tuple_struct_info, - table: array_value, tuple_struct, } - .load(); + .load(array_value); } } TypeInfo::Tuple(tuple_info) => { - if let Some(array_value) = self.table.as_array() { + if let Some(array_value) = input.as_array() { let ReflectMut::Tuple(tuple) = self.structure.reflect_mut() else { warn!("Preferences: Expected Tuple"); return; }; LoadTuple { tuple_info, - table: array_value, tuple, } - .load(); + .load(array_value); } } TypeInfo::List(list_info) => { - if let Some(array_value) = self.table.as_array() { + if let Some(array_value) = input.as_array() { let ReflectMut::List(list) = self.structure.reflect_mut() else { warn!("Preferences: Expected List"); return; @@ -117,14 +116,13 @@ impl StructureLoader for LoadStructure<'_> { LoadList { list_info, list, - toml_array: array_value, custom_attributes: self.custom_attributes, } - .load(); + .load(array_value); } } TypeInfo::Array(array_info) => { - if let Some(array_value) = self.table.as_array() { + if let Some(array_value) = input.as_array() { let ReflectMut::Array(array) = self.structure.reflect_mut() else { warn!("Preferences: Expected Array"); return; @@ -132,37 +130,26 @@ impl StructureLoader for LoadStructure<'_> { LoadArray { array_info, array, - toml_array: array_value, } - .load(); + .load(array_value); } } TypeInfo::Map(map_info) => { - if let Some(toml_map) = self.table.as_table() { + if let Some(toml_map) = input.as_table() { let ReflectMut::Map(map) = self.structure.reflect_mut() else { warn!("Preferences: Expected Map"); return; }; - LoadMap { - map_info, - map, - table: toml_map, - } - .load(); + LoadMap { map_info, map }.load(toml_map); } } TypeInfo::Set(set_info) => { - if let Some(toml_array) = self.table.as_array() { + if let Some(toml_array) = input.as_array() { let ReflectMut::Set(set) = self.structure.reflect_mut() else { warn!("Preferences: Expected Set"); return; }; - LoadSet { - set_info, - set, - toml_array, - } - .load(); + LoadSet { set_info, set }.load(toml_array); } } TypeInfo::Enum(enum_info) => { @@ -171,12 +158,7 @@ impl StructureLoader for LoadStructure<'_> { return; }; - LoadEnum { - enum_info, - enm, - toml_value: self.table, - } - .load(); + LoadEnum { enum_info, enm }.load(input); } } } @@ -215,12 +197,7 @@ pub fn load_preferences(world: &mut World, table: toml::Table, settings_type: Se .unwrap_or_else(|| strct.reflect_type_ident().unwrap().to_snake_case()); if let Some(table) = table.get(&name).and_then(|v| v.as_table()) { - LoadStruct { - struct_info, - table, - strct, - } - .load(); + LoadStruct { struct_info, strct }.load(table); } } } @@ -247,12 +224,7 @@ pub fn load_preferences(world: &mut World, table: toml::Table, settings_type: Se if let Some(table) = table.get(&name).and_then(|v| v.as_table()) { if let Some(value) = table.get("variant") { - LoadEnum { - enum_info, - enm, - toml_value: value, - } - .load(); + LoadEnum { enum_info, enm }.load(value); } } } @@ -284,10 +256,9 @@ pub fn load_preferences(world: &mut World, table: toml::Table, settings_type: Se { LoadTupleStruct { tuple_struct_info, - table: array_value, tuple_struct, } - .load(); + .load(array_value); } } } diff --git a/crates/bevy_editor_settings/src/file_system/de/set.rs b/crates/bevy_editor_settings/src/file_system/de/set.rs index c152dafe..38f02125 100644 --- a/crates/bevy_editor_settings/src/file_system/de/set.rs +++ b/crates/bevy_editor_settings/src/file_system/de/set.rs @@ -5,20 +5,20 @@ use super::{value::LoadValue, StructureLoader}; pub struct LoadSet<'a> { pub set: &'a mut dyn Set, pub set_info: &'a SetInfo, - pub toml_array: &'a toml::value::Array, } -impl StructureLoader for LoadSet<'_> { - fn load(self) { - for toml_value in self.toml_array.iter() { +impl<'a> StructureLoader for LoadSet<'a> { + type Input = &'a toml::value::Array; + + fn load(self, input: Self::Input) { + for toml_value in input.iter() { let mut value = super::default::default_value(&self.set_info.value_ty()).unwrap(); LoadValue { value_info: &self.set_info.value_ty(), - toml_value, value: value.as_mut(), } - .load(); + .load(toml_value); self.set.insert_boxed(value); } @@ -44,10 +44,9 @@ mod tests { LoadSet { set_info, - toml_array: toml_value.as_array().unwrap(), set: &mut set, } - .load(); + .load(toml_value.as_array().unwrap()); assert_eq!(set.len(), 2); assert!(set.contains(&1)); diff --git a/crates/bevy_editor_settings/src/file_system/de/structs.rs b/crates/bevy_editor_settings/src/file_system/de/structs.rs index 16063ca8..e4c90b68 100644 --- a/crates/bevy_editor_settings/src/file_system/de/structs.rs +++ b/crates/bevy_editor_settings/src/file_system/de/structs.rs @@ -4,14 +4,15 @@ use super::{struct_utils::StructLikeInfo, LoadStructure, StructureLoader}; pub struct LoadStruct<'a> { pub struct_info: &'a dyn StructLikeInfo, - pub table: &'a toml::Table, pub strct: &'a mut dyn Struct, } -impl StructureLoader for LoadStruct<'_> { - fn load(self) { +impl<'a> StructureLoader for LoadStruct<'a> { + type Input = &'a toml::Table; + + fn load(self, input: Self::Input) { let struct_info = self.struct_info; - let table = self.table; + let table = input; let strct = self.strct; for i in 0..struct_info.field_len() { let field = struct_info.field_at(i).unwrap(); @@ -25,11 +26,10 @@ impl StructureLoader for LoadStruct<'_> { let field_attrs = field.custom_attributes(); LoadStructure { type_info: field_mut.get_represented_type_info().unwrap(), - table: toml_value, structure: field_mut, custom_attributes: Some(field_attrs), } - .load(); + .load(toml_value); } } } @@ -72,10 +72,9 @@ mod tests { LoadStruct { struct_info: struct_info.reflect_type_info().as_struct().unwrap(), - table: &table, strct: &mut struct_info, } - .load(); + .load(&table); assert_eq!( struct_info, @@ -107,10 +106,9 @@ mod tests { LoadStruct { struct_info: struct_info.reflect_type_info().as_struct().unwrap(), - table: &table, strct: &mut struct_info, } - .load(); + .load(&table); assert_eq!( struct_info, diff --git a/crates/bevy_editor_settings/src/file_system/de/tuple.rs b/crates/bevy_editor_settings/src/file_system/de/tuple.rs index 494c5e4b..1f6aa25a 100644 --- a/crates/bevy_editor_settings/src/file_system/de/tuple.rs +++ b/crates/bevy_editor_settings/src/file_system/de/tuple.rs @@ -4,14 +4,15 @@ use super::{tuple_utils::TupleLikeInfo, LoadStructure, StructureLoader}; pub struct LoadTuple<'a> { pub tuple_info: &'a dyn TupleLikeInfo, - pub table: &'a toml::value::Array, pub tuple: &'a mut dyn Tuple, } -impl StructureLoader for LoadTuple<'_> { - fn load(self) { +impl<'a> StructureLoader for LoadTuple<'a> { + type Input = &'a toml::value::Array; + + fn load(self, input: Self::Input) { for i in 0..self.tuple_info.field_len() { - let Some(toml_value) = self.table.get(i) else { + let Some(toml_value) = input.get(i) else { continue; }; @@ -20,11 +21,10 @@ impl StructureLoader for LoadTuple<'_> { LoadStructure { type_info: field_mut.get_represented_type_info().unwrap(), - table: toml_value, structure: field_mut, custom_attributes: Some(field_attrs), } - .load(); + .load(toml_value); } } } @@ -47,10 +47,9 @@ mod tests { let toml_value = tuple_test_toml(); LoadTuple { tuple_info: tuple.reflect_type_info().as_tuple().unwrap(), - table: toml_value.as_array().unwrap(), tuple: &mut tuple, } - .load(); + .load(toml_value.as_array().unwrap()); assert_eq!(tuple, (1, 2)); } @@ -66,10 +65,9 @@ mod tests { let toml_value = tuple_struct_struct_toml(); LoadTuple { tuple_info: tuple.reflect_type_info().as_tuple().unwrap(), - table: toml_value.as_array().unwrap(), tuple: &mut tuple, } - .load(); + .load(toml_value.as_array().unwrap()); assert_eq!(tuple, ((1, 2), (1, 2))); } diff --git a/crates/bevy_editor_settings/src/file_system/de/tuple_struct.rs b/crates/bevy_editor_settings/src/file_system/de/tuple_struct.rs index 7776bdba..124518ef 100644 --- a/crates/bevy_editor_settings/src/file_system/de/tuple_struct.rs +++ b/crates/bevy_editor_settings/src/file_system/de/tuple_struct.rs @@ -4,14 +4,15 @@ use super::{tuple_utils::TupleLikeInfo, LoadStructure, StructureLoader}; pub struct LoadTupleStruct<'a> { pub tuple_struct_info: &'a dyn TupleLikeInfo, - pub table: &'a toml::value::Array, pub tuple_struct: &'a mut dyn TupleStruct, } -impl StructureLoader for LoadTupleStruct<'_> { - fn load(self) { +impl<'a> StructureLoader for LoadTupleStruct<'a> { + type Input = &'a toml::value::Array; + + fn load(self, input: Self::Input) { for i in 0..self.tuple_struct_info.field_len() { - let Some(toml_value) = self.table.get(i) else { + let Some(toml_value) = input.get(i) else { continue; }; @@ -24,11 +25,10 @@ impl StructureLoader for LoadTupleStruct<'_> { LoadStructure { type_info: field_mut.get_represented_type_info().unwrap(), - table: toml_value, structure: field_mut, custom_attributes: Some(field_attrs), } - .load(); + .load(toml_value); } } } @@ -54,10 +54,9 @@ mod tests { let toml_value = tuple_struct_test_toml(); LoadTupleStruct { tuple_struct_info: tuple_struct.reflect_type_info().as_tuple_struct().unwrap(), - table: toml_value.as_array().unwrap(), tuple_struct: &mut tuple_struct, } - .load(); + .load(toml_value.as_array().unwrap()); assert_eq!(tuple_struct, TupleStructTest(1, 2)); } @@ -76,10 +75,9 @@ mod tests { let toml_value = tuple_struct_struct_toml(); LoadTupleStruct { tuple_struct_info: tuple_struct.reflect_type_info().as_tuple_struct().unwrap(), - table: toml_value.as_array().unwrap(), tuple_struct: &mut tuple_struct, } - .load(); + .load(toml_value.as_array().unwrap()); assert_eq!(tuple_struct, TupleStructStruct(TupleStructTest(1, 2))); } diff --git a/crates/bevy_editor_settings/src/file_system/de/value.rs b/crates/bevy_editor_settings/src/file_system/de/value.rs index b7f36822..ae75219c 100644 --- a/crates/bevy_editor_settings/src/file_system/de/value.rs +++ b/crates/bevy_editor_settings/src/file_system/de/value.rs @@ -5,14 +5,15 @@ use super::StructureLoader; pub struct LoadValue<'a> { pub value_info: &'a Type, - pub toml_value: &'a toml::Value, pub value: &'a mut dyn PartialReflect, } -impl StructureLoader for LoadValue<'_> { - fn load(self) { +impl<'a> StructureLoader for LoadValue<'a> { + type Input = &'a toml::Value; + + fn load(self, input: Self::Input) { let value_info = self.value_info; - match self.toml_value { + match input { toml::Value::String(str_val) => { if value_info.is::() { self.value.apply(str_val); @@ -83,10 +84,9 @@ mod tests { let toml_value = &toml::Value::String("Hello".to_string()); LoadValue { value_info: value.reflect_type_info().as_opaque().unwrap().ty(), - toml_value, value: &mut value, } - .load(); + .load(toml_value); assert_eq!(value, "Hello"); } @@ -97,10 +97,9 @@ mod tests { let toml_value = &toml::Value::Float(std::f64::consts::PI); LoadValue { value_info: value.reflect_type_info().as_opaque().unwrap().ty(), - toml_value, value: &mut value, } - .load(); + .load(toml_value); assert_eq!(value, std::f64::consts::PI); } @@ -111,10 +110,9 @@ mod tests { let toml_value = &toml::Value::Float(std::f64::consts::PI); LoadValue { value_info: value.reflect_type_info().as_opaque().unwrap().ty(), - toml_value, value: &mut value, } - .load(); + .load(toml_value); assert_eq!(value, std::f32::consts::PI); } @@ -125,10 +123,9 @@ mod tests { let toml_value = &toml::Value::Boolean(true); LoadValue { value_info: value.reflect_type_info().as_opaque().unwrap().ty(), - toml_value, value: &mut value, } - .load(); + .load(toml_value); assert!(value); } @@ -139,10 +136,9 @@ mod tests { let toml_value = &toml::Value::Integer(42); LoadValue { value_info: value.reflect_type_info().as_opaque().unwrap().ty(), - toml_value, value: &mut value, } - .load(); + .load(toml_value); assert_eq!(value, 42.0); } @@ -153,10 +149,9 @@ mod tests { let toml_value = &toml::Value::Integer(42); LoadValue { value_info: value.reflect_type_info().as_opaque().unwrap().ty(), - toml_value, value: &mut value, } - .load(); + .load(toml_value); assert_eq!(value, 42.0); } @@ -167,10 +162,9 @@ mod tests { let toml_value = &toml::Value::Integer(42); LoadValue { value_info: value.reflect_type_info().as_opaque().unwrap().ty(), - toml_value, value: &mut value, } - .load(); + .load(toml_value); assert_eq!(value, 42); } @@ -181,10 +175,9 @@ mod tests { let toml_value = &toml::Value::Integer(42); LoadValue { value_info: value.reflect_type_info().as_opaque().unwrap().ty(), - toml_value, value: &mut value, } - .load(); + .load(toml_value); assert_eq!(value, 42); } @@ -195,10 +188,9 @@ mod tests { let toml_value = &toml::Value::Integer(42); LoadValue { value_info: value.reflect_type_info().as_opaque().unwrap().ty(), - toml_value, value: &mut value, } - .load(); + .load(toml_value); assert_eq!(value, 42); } @@ -209,10 +201,9 @@ mod tests { let toml_value = &toml::Value::Integer(42); LoadValue { value_info: value.reflect_type_info().as_opaque().unwrap().ty(), - toml_value, value: &mut value, } - .load(); + .load(toml_value); assert_eq!(value, 42); } @@ -223,10 +214,9 @@ mod tests { let toml_value = &toml::Value::Integer(42); LoadValue { value_info: value.reflect_type_info().as_opaque().unwrap().ty(), - toml_value, value: &mut value, } - .load(); + .load(toml_value); assert_eq!(value, 42); } @@ -237,10 +227,9 @@ mod tests { let toml_value = &toml::Value::Integer(42); LoadValue { value_info: value.reflect_type_info().as_opaque().unwrap().ty(), - toml_value, value: &mut value, } - .load(); + .load(toml_value); assert_eq!(value, 42); } @@ -251,10 +240,9 @@ mod tests { let toml_value = &toml::Value::Integer(42); LoadValue { value_info: value.reflect_type_info().as_opaque().unwrap().ty(), - toml_value, value: &mut value, } - .load(); + .load(toml_value); assert_eq!(value, 42); } @@ -265,10 +253,9 @@ mod tests { let toml_value = &toml::Value::Integer(42); LoadValue { value_info: value.reflect_type_info().as_opaque().unwrap().ty(), - toml_value, value: &mut value, } - .load(); + .load(toml_value); assert_eq!(value, 42); } @@ -279,10 +266,9 @@ mod tests { let toml_value = &toml::Value::Integer(42); LoadValue { value_info: value.reflect_type_info().as_opaque().unwrap().ty(), - toml_value, value: &mut value, } - .load(); + .load(toml_value); assert_eq!(value, 42); } } From 3db2ca91258e2e16d2c966218872adce1217ff44 Mon Sep 17 00:00:00 2001 From: Night_Hunter Date: Thu, 26 Dec 2024 16:57:03 +1300 Subject: [PATCH 4/5] move utils --- crates/bevy_editor_settings/src/file_system/de/default.rs | 3 ++- crates/bevy_editor_settings/src/file_system/de/mod.rs | 2 -- crates/bevy_editor_settings/src/file_system/de/structs.rs | 4 +++- crates/bevy_editor_settings/src/file_system/de/tuple.rs | 4 +++- .../bevy_editor_settings/src/file_system/de/tuple_struct.rs | 4 +++- crates/bevy_editor_settings/src/lib.rs | 1 + crates/bevy_editor_settings/src/utils/mod.rs | 2 ++ .../src/{file_system/de => utils}/struct_utils.rs | 2 +- .../src/{file_system/de => utils}/tuple_utils.rs | 2 +- 9 files changed, 16 insertions(+), 8 deletions(-) create mode 100644 crates/bevy_editor_settings/src/utils/mod.rs rename crates/bevy_editor_settings/src/{file_system/de => utils}/struct_utils.rs (97%) rename crates/bevy_editor_settings/src/{file_system/de => utils}/tuple_utils.rs (96%) diff --git a/crates/bevy_editor_settings/src/file_system/de/default.rs b/crates/bevy_editor_settings/src/file_system/de/default.rs index 588e5e58..837e86e7 100644 --- a/crates/bevy_editor_settings/src/file_system/de/default.rs +++ b/crates/bevy_editor_settings/src/file_system/de/default.rs @@ -3,7 +3,8 @@ use bevy::reflect::{ EnumInfo, ListInfo, MapInfo, PartialReflect, SetInfo, Type, TypeInfo, }; -use super::{struct_utils::StructLikeInfo, tuple_utils::TupleLikeInfo}; +use crate::utils::{struct_utils::StructLikeInfo, tuple_utils::TupleLikeInfo}; + pub fn default_data_type(type_info: &TypeInfo) -> Option> { match type_info { diff --git a/crates/bevy_editor_settings/src/file_system/de/mod.rs b/crates/bevy_editor_settings/src/file_system/de/mod.rs index 2e5b0924..20318b80 100644 --- a/crates/bevy_editor_settings/src/file_system/de/mod.rs +++ b/crates/bevy_editor_settings/src/file_system/de/mod.rs @@ -4,11 +4,9 @@ mod enums; mod list; mod map; mod set; -mod struct_utils; mod structs; mod tuple; mod tuple_struct; -mod tuple_utils; mod value; use array::LoadArray; diff --git a/crates/bevy_editor_settings/src/file_system/de/structs.rs b/crates/bevy_editor_settings/src/file_system/de/structs.rs index e4c90b68..efee05e2 100644 --- a/crates/bevy_editor_settings/src/file_system/de/structs.rs +++ b/crates/bevy_editor_settings/src/file_system/de/structs.rs @@ -1,6 +1,8 @@ use bevy::reflect::Struct; -use super::{struct_utils::StructLikeInfo, LoadStructure, StructureLoader}; +use crate::utils::struct_utils::StructLikeInfo; + +use super::{LoadStructure, StructureLoader}; pub struct LoadStruct<'a> { pub struct_info: &'a dyn StructLikeInfo, diff --git a/crates/bevy_editor_settings/src/file_system/de/tuple.rs b/crates/bevy_editor_settings/src/file_system/de/tuple.rs index 1f6aa25a..e3a7fd0f 100644 --- a/crates/bevy_editor_settings/src/file_system/de/tuple.rs +++ b/crates/bevy_editor_settings/src/file_system/de/tuple.rs @@ -1,6 +1,8 @@ use bevy::reflect::Tuple; -use super::{tuple_utils::TupleLikeInfo, LoadStructure, StructureLoader}; +use crate::utils::tuple_utils::TupleLikeInfo; + +use super::{ LoadStructure, StructureLoader}; pub struct LoadTuple<'a> { pub tuple_info: &'a dyn TupleLikeInfo, diff --git a/crates/bevy_editor_settings/src/file_system/de/tuple_struct.rs b/crates/bevy_editor_settings/src/file_system/de/tuple_struct.rs index 124518ef..a85d2976 100644 --- a/crates/bevy_editor_settings/src/file_system/de/tuple_struct.rs +++ b/crates/bevy_editor_settings/src/file_system/de/tuple_struct.rs @@ -1,6 +1,8 @@ use bevy::reflect::TupleStruct; -use super::{tuple_utils::TupleLikeInfo, LoadStructure, StructureLoader}; +use crate::utils::tuple_utils::TupleLikeInfo; + +use super::{LoadStructure, StructureLoader}; pub struct LoadTupleStruct<'a> { pub tuple_struct_info: &'a dyn TupleLikeInfo, diff --git a/crates/bevy_editor_settings/src/lib.rs b/crates/bevy_editor_settings/src/lib.rs index 5abc4fb7..11594ea2 100644 --- a/crates/bevy_editor_settings/src/lib.rs +++ b/crates/bevy_editor_settings/src/lib.rs @@ -4,6 +4,7 @@ use bevy::prelude::*; mod file_system; mod diff; +pub(crate) mod utils; /// Annotation for a type to show which type of settings it belongs to. #[derive(Debug, Clone, PartialEq, Eq, Reflect)] diff --git a/crates/bevy_editor_settings/src/utils/mod.rs b/crates/bevy_editor_settings/src/utils/mod.rs new file mode 100644 index 00000000..9bb3fef8 --- /dev/null +++ b/crates/bevy_editor_settings/src/utils/mod.rs @@ -0,0 +1,2 @@ +pub mod struct_utils; +pub mod tuple_utils; \ No newline at end of file diff --git a/crates/bevy_editor_settings/src/file_system/de/struct_utils.rs b/crates/bevy_editor_settings/src/utils/struct_utils.rs similarity index 97% rename from crates/bevy_editor_settings/src/file_system/de/struct_utils.rs rename to crates/bevy_editor_settings/src/utils/struct_utils.rs index 00e35f0e..5d271556 100644 --- a/crates/bevy_editor_settings/src/file_system/de/struct_utils.rs +++ b/crates/bevy_editor_settings/src/utils/struct_utils.rs @@ -2,7 +2,7 @@ use bevy::reflect::{NamedField, StructInfo, StructVariantInfo}; use core::slice::Iter; /// A helper trait for accessing type information from struct-like types. -pub(super) trait StructLikeInfo { +pub trait StructLikeInfo { #[allow(dead_code)] fn field(&self, name: &str) -> Option<&NamedField>; fn field_at(&self, index: usize) -> Option<&NamedField>; diff --git a/crates/bevy_editor_settings/src/file_system/de/tuple_utils.rs b/crates/bevy_editor_settings/src/utils/tuple_utils.rs similarity index 96% rename from crates/bevy_editor_settings/src/file_system/de/tuple_utils.rs rename to crates/bevy_editor_settings/src/utils/tuple_utils.rs index f3b1aa99..2a6f8575 100644 --- a/crates/bevy_editor_settings/src/file_system/de/tuple_utils.rs +++ b/crates/bevy_editor_settings/src/utils/tuple_utils.rs @@ -1,6 +1,6 @@ use bevy::reflect::{TupleInfo, TupleStructInfo, TupleVariantInfo, UnnamedField}; -pub(super) trait TupleLikeInfo { +pub trait TupleLikeInfo { fn field_at(&self, index: usize) -> Option<&UnnamedField>; fn field_len(&self) -> usize; } From a4428afa39c28aaa3c1b48b243a12365a0bdec38 Mon Sep 17 00:00:00 2001 From: Night_Hunter Date: Thu, 26 Dec 2024 21:20:06 +1300 Subject: [PATCH 5/5] basic saving and change detection --- crates/bevy_editor_settings/src/diff/mod.rs | 125 +++++++++++------- .../bevy_editor_settings/src/diff/opaque.rs | 68 ++++++++++ .../bevy_editor_settings/src/diff/structs.rs | 32 +++++ .../src/file_system/mod.rs | 1 + .../src/file_system/ser/mod.rs | 93 +++++++++++++ .../src/file_system/ser/opaque.rs | 63 +++++++++ .../src/file_system/ser/structs.rs | 28 ++++ 7 files changed, 365 insertions(+), 45 deletions(-) create mode 100644 crates/bevy_editor_settings/src/diff/opaque.rs create mode 100644 crates/bevy_editor_settings/src/file_system/ser/mod.rs create mode 100644 crates/bevy_editor_settings/src/file_system/ser/opaque.rs create mode 100644 crates/bevy_editor_settings/src/file_system/ser/structs.rs diff --git a/crates/bevy_editor_settings/src/diff/mod.rs b/crates/bevy_editor_settings/src/diff/mod.rs index 6c54fac2..f2a614da 100644 --- a/crates/bevy_editor_settings/src/diff/mod.rs +++ b/crates/bevy_editor_settings/src/diff/mod.rs @@ -1,9 +1,51 @@ +mod opaque; mod structs; -use bevy::reflect::{PartialReflect, Reflect, Struct, TypeInfo}; +use bevy::{ + prelude::warn, + reflect::{PartialReflect, Reflect, ReflectRef, Struct, TypeInfo}, + utils::HashMap, +}; +use opaque::DiffOpaque; +use structs::DiffStructs; -pub trait Diff: Reflect { - fn diff(&self, other: &Self) -> Vec; +#[derive(Debug, Clone)] +pub(crate) enum DiffType { + Opaque, + Struct(HashMap), +} + +pub trait Diff { + type Input; + + fn diff(&self, input1: Self::Input, input2: Self::Input) -> Option; +} + +pub struct DiffStructures<'a> { + pub type_info: &'a TypeInfo, +} + +impl<'a> Diff for DiffStructures<'a> { + type Input = &'a dyn PartialReflect; + + fn diff(&self, input1: Self::Input, input2: Self::Input) -> Option { + match self.type_info { + TypeInfo::Struct(struct_info) => match (input1.reflect_ref(), input2.reflect_ref()) { + (ReflectRef::Struct(struct1), ReflectRef::Struct(struct2)) => { + DiffStructs { struct_info }.diff(struct1, struct2) + } + _ => { + warn!("Diffing not implemented for type: {:?}", self.type_info); + None + } + }, + TypeInfo::Opaque(opaque_info) => DiffOpaque { opaque_info }.diff(input1, input2), + _ => { + warn!("Diffing not implemented for type: {:?}", self.type_info); + None + } + } + } } #[derive(Debug, Clone, PartialEq)] @@ -19,55 +61,48 @@ struct SomeStruct { b: u32, } -impl Diff for SomeStruct { - fn diff(&self, other: &Self) -> Vec { - let mut results = Vec::new(); - let struct_self = self.as_partial_reflect().reflect_ref().as_struct().unwrap(); - let struct_other = other - .as_partial_reflect() - .reflect_ref() - .as_struct() - .unwrap(); - - for index in 0..struct_self.field_len() { - let field = struct_self.field_at(index).unwrap(); - let field_other = struct_other.field_at(index).unwrap(); - let type_info = field.get_represented_type_info().unwrap(); - if let TypeInfo::Opaque(_) = type_info { - if field.represents::() { - let value = field.try_downcast_ref::().unwrap(); - let value_other = field_other.try_downcast_ref::().unwrap(); - if value != value_other { - results.push(DiffResult { - field_name: struct_self.name_at(index).unwrap().to_string(), - old_value: value.to_string(), - new_value: value_other.to_string(), - }); - } - } - } - } - results - } +#[derive(Debug, Clone, Reflect)] +struct Wrapper { + struct1: SomeStruct, + something: u32, } #[cfg(test)] mod tests { + use bevy::reflect::DynamicTyped as _; + use super::*; #[test] fn test_diff() { - let a = SomeStruct { a: 1, b: 2 }; - let b = SomeStruct { a: 1, b: 3 }; - let res = a.diff(&b); - println!("{:?}", res); - assert_eq!( - res, - vec![DiffResult { - field_name: "b".to_string(), - old_value: "2".to_string(), - new_value: "3".to_string(), - }] - ); + let struct1 = SomeStruct { a: 1, b: 2 }; + let struct2 = SomeStruct { a: 1, b: 3 }; + + let wrapper1 = Wrapper { + struct1, + something: 1, + }; + + let wrapper2 = Wrapper { + struct1: struct2, + something: 1, + }; + + let diff = DiffStructures { + type_info: wrapper1.reflect_type_info(), + } + .diff(&wrapper1, &wrapper2) + .unwrap(); + + println!("{:?}", diff); + + // assert_eq!( + // diff, + // vec![DiffResult { + // field_name: "b".to_string(), + // old_value: "2".to_string(), + // new_value: "3".to_string(), + // }] + // ); } } diff --git a/crates/bevy_editor_settings/src/diff/opaque.rs b/crates/bevy_editor_settings/src/diff/opaque.rs new file mode 100644 index 00000000..1b39b05b --- /dev/null +++ b/crates/bevy_editor_settings/src/diff/opaque.rs @@ -0,0 +1,68 @@ +use bevy::reflect::{OpaqueInfo, PartialReflect}; + +use super::{Diff, DiffResult, DiffType}; + +macro_rules! diff_types { + ($type_info:expr, $input1:expr, $input2:expr, $($type_v:ty),*) => { + $( + if diff_type::<$type_v>(&$type_info, $input1, $input2){ + return Some(DiffType::Opaque); + }; + )* + }; + +} + +pub struct DiffOpaque<'a> { + pub opaque_info: &'a OpaqueInfo, +} + +impl<'a> Diff for DiffOpaque<'a> { + type Input = &'a dyn PartialReflect; + + fn diff(&self, input1: Self::Input, input2: Self::Input) -> Option { + diff_types!( + self.opaque_info, + input1, + input2, + bool, + u8, + u16, + u32, + u64, + i32, + i64, + f32, + f64, + String, + &str + ); + + None + } +} + +#[inline] +fn diff_type( + opaque_info: &OpaqueInfo, + input1: &dyn PartialReflect, + input2: &dyn PartialReflect, +) -> bool +where + T: PartialEq + 'static, +{ + if opaque_info.is::() { + let value1 = input1.try_downcast_ref::(); + let value2 = input2.try_downcast_ref::(); + + if value1.is_none() || value2.is_none() { + return false; + } + let value1 = value1.unwrap(); + let value2 = value2.unwrap(); + if value1 != value2 { + return true; + } + } + false +} diff --git a/crates/bevy_editor_settings/src/diff/structs.rs b/crates/bevy_editor_settings/src/diff/structs.rs index e69de29b..c74bc144 100644 --- a/crates/bevy_editor_settings/src/diff/structs.rs +++ b/crates/bevy_editor_settings/src/diff/structs.rs @@ -0,0 +1,32 @@ +use bevy::{reflect::Struct, utils::hashbrown::HashMap}; + +use crate::utils::struct_utils::StructLikeInfo; + +use super::{Diff, DiffResult, DiffType}; + +pub struct DiffStructs<'a> { + pub struct_info: &'a dyn StructLikeInfo, +} + +impl<'a> Diff for DiffStructs<'a> { + type Input = &'a dyn Struct; + + fn diff(&self, input1: Self::Input, input2: Self::Input) -> Option { + let mut results = HashMap::new(); + + for index in 0..self.struct_info.field_len() { + let field = input1.field_at(index).unwrap(); + let field_other = input2.field_at(index).unwrap(); + let type_info = field.get_represented_type_info().unwrap(); + if let Some(output) = (super::DiffStructures { type_info }).diff(field, field_other) { + results.insert(self.struct_info.field_at(index).unwrap().name().to_string(), output); + } + } + + if results.is_empty() { + None + } else { + Some(DiffType::Struct(results)) + } + } +} diff --git a/crates/bevy_editor_settings/src/file_system/mod.rs b/crates/bevy_editor_settings/src/file_system/mod.rs index 560f7cd8..9811e01a 100644 --- a/crates/bevy_editor_settings/src/file_system/mod.rs +++ b/crates/bevy_editor_settings/src/file_system/mod.rs @@ -4,6 +4,7 @@ use bevy::log::{error, warn}; use de::{load_preferences, load_toml_file}; pub mod de; +pub mod ser; use crate::{GlobalSettingsPath, SettingsType}; diff --git a/crates/bevy_editor_settings/src/file_system/ser/mod.rs b/crates/bevy_editor_settings/src/file_system/ser/mod.rs new file mode 100644 index 00000000..f824abcc --- /dev/null +++ b/crates/bevy_editor_settings/src/file_system/ser/mod.rs @@ -0,0 +1,93 @@ +mod opaque; +mod structs; + +use bevy::reflect::{PartialReflect, ReflectRef}; +use opaque::OpaqueSaver; +use structs::StructSaver; + +use crate::diff::DiffType; + +trait StructureSaver { + fn save(self, input: DiffType); +} + +struct SaveStructures<'a> { + toml: &'a mut toml::Value, + structure: &'a dyn PartialReflect, +} + +impl<'a> StructureSaver for SaveStructures<'a> { + fn save(self, input: DiffType) { + match input { + DiffType::Opaque => { + let ReflectRef::Opaque(opaque_info) = self.structure.reflect_ref() else { + return; + }; + + OpaqueSaver { + value: opaque_info, + toml: self.toml, + } + .save(DiffType::Opaque); + } + DiffType::Struct(fields) => { + let ReflectRef::Struct(structure) = self.structure.reflect_ref() else { + return; + }; + let toml::Value::Table(table) = self.toml else { + return; + }; + StructSaver { + strct: structure, + toml: table, + } + .save(DiffType::Struct(fields)); + } + } + } +} + +#[cfg(test)] +mod tests { + use bevy::reflect::DynamicTyped as _; + use bevy::reflect::Reflect; + use bevy::reflect::Struct; + + use crate::diff::Diff; + use crate::diff::DiffStructures; + + use super::*; + + #[derive(Debug, Clone, Reflect, Default, PartialEq)] + struct Values { + pub int1: u32, + pub int2: String, + } + + #[test] + fn test_save_struct() { + let values1 = Values { int1: 1, int2: "Hello".to_string() }; + let values2 = Values { int1: 3, int2: "World".to_string() }; + let mut toml_value = toml::Value::Table(toml::value::Table::default()); + + let toml_table = toml_value.as_table_mut().unwrap(); + toml_table.insert( + "testing".to_string(), + toml::Value::Table(toml::value::Table::default()), + ); + + let diff = DiffStructures { + type_info: values1.reflect_type_info(), + } + .diff(&values1, &values2) + .unwrap(); + + SaveStructures { + toml: toml_table.get_mut("testing").unwrap(), + structure: &values2, + } + .save(diff); + + println!("{}", toml::to_string_pretty(&toml_table).unwrap()); + } +} diff --git a/crates/bevy_editor_settings/src/file_system/ser/opaque.rs b/crates/bevy_editor_settings/src/file_system/ser/opaque.rs new file mode 100644 index 00000000..0853d27e --- /dev/null +++ b/crates/bevy_editor_settings/src/file_system/ser/opaque.rs @@ -0,0 +1,63 @@ +use bevy::reflect::{OpaqueInfo, PartialReflect, TypeInfo}; + +use super::{DiffType, StructureSaver}; + +pub struct OpaqueSaver<'a> { + pub value: &'a dyn PartialReflect, + pub toml: &'a mut toml::Value, +} + +impl<'a> StructureSaver for OpaqueSaver<'a> { + fn save(self, input: DiffType) { + if let DiffType::Opaque = input { + let type_info = self.value.get_represented_type_info().unwrap(); + + check_and_save_opaque::(type_info, self.value, self.toml, |value, toml| { + *toml = toml::Value::Boolean(*value); + }); + check_and_save_opaque::(type_info, self.value, self.toml, |value, toml| { + *toml = toml::Value::Integer(*value as i64); + }); + check_and_save_opaque::(type_info, self.value, self.toml, |value, toml| { + *toml = toml::Value::Integer(*value as i64); + }); + check_and_save_opaque::(type_info, self.value, self.toml, |value, toml| { + *toml = toml::Value::Integer(*value as i64); + }); + check_and_save_opaque::(type_info, self.value, self.toml, |value, toml| { + *toml = toml::Value::Integer(*value as i64); + }); + check_and_save_opaque::(type_info, self.value, self.toml, |value, toml| { + *toml = toml::Value::Integer(*value as i64); + }); + check_and_save_opaque::(type_info, self.value, self.toml, |value, toml| { + *toml = toml::Value::Integer(*value as i64); + }); + check_and_save_opaque::(type_info, self.value, self.toml, |value, toml| { + *toml = toml::Value::Float(f64::from(*value)); + }); + check_and_save_opaque::(type_info, self.value, self.toml, |value, toml| { + *toml = toml::Value::Float(*value); + }); + check_and_save_opaque::(type_info, self.value, self.toml, |value, toml| { + *toml = toml::Value::String(value.clone()); + }); + } + } +} + +#[inline] +fn check_and_save_opaque( + type_info: &TypeInfo, + value: &dyn PartialReflect, + toml: &mut toml::Value, + f: F, +) where + T: 'static, + F: FnOnce(&T, &mut toml::Value), +{ + if type_info.is::() { + let value = value.try_downcast_ref::().unwrap(); + f(value, toml); + } +} diff --git a/crates/bevy_editor_settings/src/file_system/ser/structs.rs b/crates/bevy_editor_settings/src/file_system/ser/structs.rs new file mode 100644 index 00000000..7b6feb2e --- /dev/null +++ b/crates/bevy_editor_settings/src/file_system/ser/structs.rs @@ -0,0 +1,28 @@ +use bevy::{reflect::Struct, utils::hashbrown::HashMap}; + +use crate::utils::struct_utils::StructLikeInfo; + +use super::{DiffType, SaveStructures, StructureSaver}; + +pub struct StructSaver<'a> { + pub strct: &'a dyn Struct, + pub toml: &'a mut toml::value::Table, +} + +impl<'a> StructureSaver for StructSaver<'a> { + fn save(self, input: DiffType) { + if let DiffType::Struct(results) = input { + for (key, value) in results { + if let Some(field) = self.strct.field(&key) { + let mut toml_value = toml::Value::Boolean(false); + SaveStructures { + toml: &mut toml_value, + structure: field, + } + .save(value); + self.toml.insert(key, toml_value); + } + } + } + } +}