diff --git a/crates/bevy_remote/src/builtin_methods.rs b/crates/bevy_remote/src/builtin_methods.rs index 69e86dea37..8d78182908 100644 --- a/crates/bevy_remote/src/builtin_methods.rs +++ b/crates/bevy_remote/src/builtin_methods.rs @@ -1,6 +1,7 @@ //! Built-in verbs for the Bevy Remote Protocol. use core::any::TypeId; +use std::borrow::Cow; use anyhow::{anyhow, Result as AnyhowResult}; use bevy_ecs::{ @@ -1268,7 +1269,7 @@ pub fn export_registry_types(In(params): In>, world: &World) -> Br } Some((type_reg.type_info().type_path().into(), schema)) }) - .collect::>(); + .collect::, JsonSchemaBevyType>>(); serde_json::to_value(schemas).map_err(BrpError::internal) } diff --git a/crates/bevy_remote/src/schemas/json_schema.rs b/crates/bevy_remote/src/schemas/json_schema.rs index f8b2ab5e80..e98fd21abd 100644 --- a/crates/bevy_remote/src/schemas/json_schema.rs +++ b/crates/bevy_remote/src/schemas/json_schema.rs @@ -8,6 +8,7 @@ use bevy_reflect::{ use core::any::TypeId; use serde::{Deserialize, Serialize}; use serde_json::Value; +use std::borrow::Cow; use crate::schemas::{ reflect_info::{SchemaInfoReflect, SchemaNumber}, @@ -102,11 +103,11 @@ impl TryFrom<&TypeRegistration> for JsonSchemaBevyType { /// Identifies the JSON Schema version used in the schema. #[derive(Deserialize, Serialize, Debug, Reflect, PartialEq, Clone)] -pub struct SchemaMarker(String); +pub struct SchemaMarker(Cow<'static, str>); impl Default for SchemaMarker { fn default() -> Self { - Self("https://json-schema.org/draft/2020-12/schema".to_string()) + Self("https://json-schema.org/draft/2020-12/schema".into()) } } @@ -125,22 +126,22 @@ pub struct JsonSchemaBevyType { /// This keyword is used to reference a statically identified schema. #[serde(rename = "$ref")] #[serde(skip_serializing_if = "Option::is_none", default)] - pub ref_type: Option, + pub ref_type: Option>, /// Bevy specific field, short path of the type. - #[serde(skip_serializing_if = "String::is_empty", default)] - pub short_path: String, + #[serde(skip_serializing_if = "str::is_empty", default)] + pub short_path: Cow<'static, str>, /// Bevy specific field, full path of the type. - #[serde(skip_serializing_if = "String::is_empty", default)] - pub type_path: String, + #[serde(skip_serializing_if = "str::is_empty", default)] + pub type_path: Cow<'static, str>, /// Bevy specific field, path of the module that type is part of. #[serde(skip_serializing_if = "Option::is_none", default)] - pub module_path: Option, + pub module_path: Option>, /// Bevy specific field, name of the crate that type is part of. #[serde(skip_serializing_if = "Option::is_none", default)] - pub crate_name: Option, + pub crate_name: Option>, /// Bevy specific field, names of the types that type reflects. #[serde(skip_serializing_if = "Vec::is_empty", default)] - pub reflect_types: Vec, + pub reflect_types: Vec>, /// Bevy specific field, [`TypeInfo`] type mapping. pub kind: SchemaKind, /// Bevy specific field, provided when [`SchemaKind`] `kind` field is equal to [`SchemaKind::Map`]. @@ -167,10 +168,10 @@ pub struct JsonSchemaBevyType { /// within this keyword's value, the child instance for that name successfully validates /// against the corresponding schema. #[serde(skip_serializing_if = "HashMap::is_empty", default)] - pub properties: HashMap, + pub properties: HashMap, JsonSchemaVariant>, /// An object instance is valid against this keyword if every item in the array is the name of a property in the instance. #[serde(skip_serializing_if = "Vec::is_empty", default)] - pub required: Vec, + pub required: Vec>, /// An instance validates successfully against this keyword if it validates successfully against exactly one schema defined by this keyword's value. #[serde(skip_serializing_if = "Vec::is_empty", default)] pub one_of: Vec, @@ -452,19 +453,24 @@ mod tests { let schema = export_type::(); assert!( - !schema.reflect_types.contains(&"Component".to_owned()), + !schema.reflect_types.contains(&Cow::Borrowed("Component")), "Should not be a component" ); assert!( - schema.reflect_types.contains(&"Resource".to_owned()), + schema.reflect_types.contains(&Cow::Borrowed("Resource")), "Should be a resource" ); + let _ = schema.properties.get("a").expect("Missing `a` field"); let _ = schema.properties.get("b").expect("Missing `b` field"); assert!( - schema.required.contains(&"a".to_owned()), + schema.required.contains(&Cow::Borrowed("a")), "Field a should be required" ); + assert!( + schema.required.contains(&Cow::Borrowed("b")), + "Field b should be required" + ); } #[test] @@ -482,11 +488,11 @@ mod tests { } let schema = export_type::(); assert!( - schema.reflect_types.contains(&"Component".to_owned()), + schema.reflect_types.contains(&Cow::Borrowed("Component")), "Should be a component" ); assert!( - !schema.reflect_types.contains(&"Resource".to_owned()), + !schema.reflect_types.contains(&Cow::Borrowed("Resource")), "Should not be a resource" ); assert!(schema.properties.is_empty(), "Should not have any field"); @@ -506,11 +512,11 @@ mod tests { } let schema = export_type::(); assert!( - !schema.reflect_types.contains(&"Component".to_owned()), + !schema.reflect_types.contains(&Cow::Borrowed("Component")), "Should not be a component" ); assert!( - !schema.reflect_types.contains(&"Resource".to_owned()), + !schema.reflect_types.contains(&Cow::Borrowed("Resource")), "Should not be a resource" ); assert!(schema.properties.is_empty(), "Should not have any field"); @@ -601,7 +607,7 @@ mod tests { .export_type_json_schema::(&SchemaTypesMetadata::default()) .expect("Failed to export schema"); assert!( - !schema.reflect_types.contains(&"Component".to_owned()), + !schema.reflect_types.contains(&Cow::Borrowed("Component")), "Should not be a component" ); assert!( @@ -621,11 +627,11 @@ mod tests { let schema = export_type::(); assert!( - schema.reflect_types.contains(&"Component".to_owned()), + schema.reflect_types.contains(&Cow::Borrowed("Component")), "Should be a component" ); assert!( - !schema.reflect_types.contains(&"Resource".to_owned()), + !schema.reflect_types.contains(&Cow::Borrowed("Resource")), "Should not be a resource" ); assert!(schema.properties.is_empty(), "Should not have any field"); diff --git a/crates/bevy_remote/src/schemas/mod.rs b/crates/bevy_remote/src/schemas/mod.rs index de606233f5..1d5afdbb49 100644 --- a/crates/bevy_remote/src/schemas/mod.rs +++ b/crates/bevy_remote/src/schemas/mod.rs @@ -10,6 +10,7 @@ use bevy_reflect::{ TypeRegistration, }; use core::any::TypeId; +use std::borrow::Cow; use crate::schemas::json_schema::JsonSchemaBevyType; @@ -23,7 +24,7 @@ pub mod reflect_info; #[reflect(Resource)] pub struct SchemaTypesMetadata { /// Type Data id mapping to human-readable type names. - pub type_data_map: HashMap, + pub type_data_map: HashMap>, } /// Reflect-compatible custom JSON Schema for this type @@ -62,12 +63,12 @@ impl Default for SchemaTypesMetadata { impl SchemaTypesMetadata { /// Map `TypeId` of `TypeData` to a human-readable type name - pub fn map_type_data(&mut self, name: impl Into) { + pub fn map_type_data(&mut self, name: impl Into>) { self.type_data_map.insert(TypeId::of::(), name.into()); } /// Build reflect types list for a given type registration - pub fn get_registered_reflect_types(&self, reg: &TypeRegistration) -> Vec { + pub fn get_registered_reflect_types(&self, reg: &TypeRegistration) -> Vec> { self.type_data_map .iter() .filter_map(|(id, name)| reg.data_by_id(*id).and(Some(name.clone()))) @@ -75,12 +76,16 @@ impl SchemaTypesMetadata { } /// Checks if slice contains a type name that matches the checked `TypeData` - pub fn has_type_data(&self, types_string_slice: &[String]) -> bool { + pub fn has_type_data(&self, types_string_slice: &[Cow<'static, str>]) -> bool { self.has_type_data_by_id(TypeId::of::(), types_string_slice) } /// Checks if slice contains a type name that matches the checked `TypeData` by id. - pub fn has_type_data_by_id(&self, id: TypeId, types_string_slice: &[String]) -> bool { + pub fn has_type_data_by_id( + &self, + id: TypeId, + types_string_slice: &[Cow<'static, str>], + ) -> bool { self.type_data_map .get(&id) .is_some_and(|data_s| types_string_slice.iter().any(|e| e.eq(data_s))) diff --git a/crates/bevy_remote/src/schemas/reflect_info.rs b/crates/bevy_remote/src/schemas/reflect_info.rs index 9d8a66c248..8e2e8e675a 100644 --- a/crates/bevy_remote/src/schemas/reflect_info.rs +++ b/crates/bevy_remote/src/schemas/reflect_info.rs @@ -334,21 +334,21 @@ impl Into for SchemaTypeInfo { type_path: self .type_info .as_ref() - .and_then(|s| Some(s.type_path_table().path().to_owned())) + .and_then(|s| Some(s.type_path_table().path().into())) .unwrap_or_default(), short_path: self .type_info .as_ref() - .and_then(|s| Some(s.type_path_table().short_path().to_owned())) + .and_then(|s| Some(s.type_path_table().short_path().into())) .unwrap_or_default(), crate_name: self .type_info .as_ref() - .and_then(|s| s.type_path_table().crate_name().map(str::to_owned)), + .and_then(|s| s.type_path_table().crate_name().map(Into::into)), module_path: self .type_info .as_ref() - .and_then(|s| s.type_path_table().module_path().map(str::to_owned)), + .and_then(|s| s.type_path_table().module_path().map(Into::into)), minimum: self.range.min.as_ref().and_then(|r| r.get_inclusive()), maximum: self.range.max.as_ref().and_then(|r| r.get_inclusive()), exclusive_minimum: self.range.min.as_ref().and_then(|r| r.get_exclusive()), @@ -396,9 +396,8 @@ impl Into for SchemaTypeInfo { range: MinMaxValues::default(), }; - schema.properties = - [(variant_info.name().to_string(), schema_field.into())].into(); - schema.required = vec![variant_info.name().to_string()]; + schema.properties = [(variant_info.name().into(), schema_field.into())].into(); + schema.required = vec![variant_info.name().into()]; } VariantInfo::Tuple(tuple_variant_info) => { schema.kind = SchemaKind::Value; @@ -414,9 +413,8 @@ impl Into for SchemaTypeInfo { type_id: Some(tuple_variant_info.type_id()), range: MinMaxValues::default(), }; - schema.properties = - [(variant_info.name().to_string(), schema_field.into())].into(); - schema.required = vec![variant_info.name().to_string()]; + schema.properties = [(variant_info.name().into(), schema_field.into())].into(); + schema.required = vec![variant_info.name().into()]; } VariantInfo::Unit(unit_variant_info) => { return JsonSchemaVariant::const_value( @@ -430,11 +428,11 @@ impl Into for SchemaTypeInfo { schema.schema_type = Some(SchemaTypeVariant::Single(SchemaType::Object)); schema.properties = named_fields .iter() - .map(|field| (field.name().to_string(), field.build_schema())) + .map(|field| (field.name().into(), field.build_schema())) .collect(); schema.required = named_fields .iter() - .map(|field| field.name().to_string()) + .map(|field| field.name().into()) .collect(); } InternalSchemaType::UnnamedFieldsHolder(unnamed_fields) => {