Apply feedback

This commit is contained in:
Piotr Siuszko 2025-06-08 10:37:27 +02:00
parent b84e878ab2
commit 10dabadd08
5 changed files with 44 additions and 48 deletions

View File

@ -9,8 +9,9 @@ license = "MIT OR Apache-2.0"
keywords = ["bevy"] keywords = ["bevy"]
[features] [features]
default = ["http"] default = ["http","bevy_asset"]
http = ["dep:async-io", "dep:smol-hyper"] http = ["dep:async-io", "dep:smol-hyper"]
bevy_asset = ["dep:bevy_asset"]
[dependencies] [dependencies]
# bevy # bevy
@ -26,7 +27,7 @@ bevy_platform = { path = "../bevy_platform", version = "0.16.0-dev", default-fea
"std", "std",
"serialize", "serialize",
] } ] }
bevy_asset = { path = "../bevy_asset", version = "0.16.0-dev" } bevy_asset = { path = "../bevy_asset", version = "0.16.0-dev", optional = true}
# other # other
anyhow = "1" anyhow = "1"

View File

@ -1231,25 +1231,21 @@ pub fn export_registry_types(In(params): In<Option<Value>>, world: &World) -> Br
let types = types.read(); let types = types.read();
let schemas = types let schemas = types
.iter() .iter()
.filter(|type_reg| { .filter_map(|type_reg| {
let path_table = type_reg.type_info().type_path_table(); let path_table = type_reg.type_info().type_path_table();
if let Some(crate_name) = &path_table.crate_name() { if let Some(crate_name) = &path_table.crate_name() {
if !filter.with_crates.is_empty() if !filter.with_crates.is_empty()
&& !filter.with_crates.iter().any(|c| crate_name.eq(c)) && !filter.with_crates.iter().any(|c| crate_name.eq(c))
{ {
return false; return None;
} }
if !filter.without_crates.is_empty() if !filter.without_crates.is_empty()
&& filter.without_crates.iter().any(|c| crate_name.eq(c)) && filter.without_crates.iter().any(|c| crate_name.eq(c))
{ {
return false; return None;
} }
} }
let (id, schema) = export_type(type_reg, extra_info);
true
})
.flat_map(|e| {
let (id, schema) = export_type(e, extra_info);
if !filter.type_limit.with.is_empty() if !filter.type_limit.with.is_empty()
&& !filter && !filter
@ -1269,7 +1265,7 @@ pub fn export_registry_types(In(params): In<Option<Value>>, world: &World) -> Br
{ {
return None; return None;
} }
Some((id, schema)) Some((id.to_string(), schema))
}) })
.collect::<HashMap<String, JsonSchemaBevyType>>(); .collect::<HashMap<String, JsonSchemaBevyType>>();

View File

@ -364,6 +364,8 @@
//! [fully-qualified type names]: bevy_reflect::TypePath::type_path //! [fully-qualified type names]: bevy_reflect::TypePath::type_path
//! [fully-qualified type name]: bevy_reflect::TypePath::type_path //! [fully-qualified type name]: bevy_reflect::TypePath::type_path
extern crate alloc;
use async_channel::{Receiver, Sender}; use async_channel::{Receiver, Sender};
use bevy_app::{prelude::*, MainScheduleOrder}; use bevy_app::{prelude::*, MainScheduleOrder};
use bevy_derive::{Deref, DerefMut}; use bevy_derive::{Deref, DerefMut};

View File

@ -1,5 +1,6 @@
//! Module with JSON Schema type for Bevy Registry Types. //! Module with JSON Schema type for Bevy Registry Types.
//! It tries to follow this standard: <https://json-schema.org/specification> //! It tries to follow this standard: <https://json-schema.org/specification>
use alloc::borrow::Cow;
use bevy_platform::collections::HashMap; use bevy_platform::collections::HashMap;
use bevy_reflect::{ use bevy_reflect::{
GetTypeRegistration, NamedField, OpaqueInfo, TypeInfo, TypeRegistration, TypeRegistry, GetTypeRegistration, NamedField, OpaqueInfo, TypeInfo, TypeRegistration, TypeRegistry,
@ -14,11 +15,11 @@ use crate::schemas::SchemaTypesMetadata;
/// Helper trait for converting `TypeRegistration` to `JsonSchemaBevyType` /// Helper trait for converting `TypeRegistration` to `JsonSchemaBevyType`
pub trait TypeRegistrySchemaReader { pub trait TypeRegistrySchemaReader {
/// Export type JSON Schema. /// Export type JSON Schema.
fn export_type_json_schema<T: GetTypeRegistration>( fn export_type_json_schema<T: GetTypeRegistration + 'static>(
&self, &self,
extra_info: &SchemaTypesMetadata, extra_info: &SchemaTypesMetadata,
) -> Option<JsonSchemaBevyType> { ) -> Option<JsonSchemaBevyType> {
self.export_type_json_schema_for_id(extra_info, T::get_type_registration().type_id()) self.export_type_json_schema_for_id(extra_info, TypeId::of::<T>())
} }
/// Export type JSON Schema. /// Export type JSON Schema.
fn export_type_json_schema_for_id( fn export_type_json_schema_for_id(
@ -43,11 +44,8 @@ impl TypeRegistrySchemaReader for TypeRegistry {
pub fn export_type( pub fn export_type(
reg: &TypeRegistration, reg: &TypeRegistration,
metadata: &SchemaTypesMetadata, metadata: &SchemaTypesMetadata,
) -> (String, JsonSchemaBevyType) { ) -> (Cow<'static, str>, JsonSchemaBevyType) {
( (reg.type_info().type_path().into(), (reg, metadata).into())
reg.type_info().type_path().to_owned(),
(reg, metadata).into(),
)
} }
impl From<(&TypeRegistration, &SchemaTypesMetadata)> for JsonSchemaBevyType { impl From<(&TypeRegistration, &SchemaTypesMetadata)> for JsonSchemaBevyType {
@ -517,7 +515,7 @@ mod tests {
register.register_type_data::<EnumComponent, ReflectCustomData>(); register.register_type_data::<EnumComponent, ReflectCustomData>();
} }
let mut metadata = SchemaTypesMetadata::default(); let mut metadata = SchemaTypesMetadata::default();
metadata.register_type::<ReflectCustomData>("CustomData"); metadata.map_type_data::<ReflectCustomData>("CustomData");
let type_registry = atr.read(); let type_registry = atr.read();
let foo_registration = type_registry let foo_registration = type_registry
.get(TypeId::of::<EnumComponent>()) .get(TypeId::of::<EnumComponent>())
@ -525,19 +523,19 @@ mod tests {
.clone(); .clone();
let (_, schema) = export_type(&foo_registration, &metadata); let (_, schema) = export_type(&foo_registration, &metadata);
assert!( assert!(
!metadata.has_data_type::<ReflectComponent>(&schema.reflect_types), !metadata.has_type_data::<ReflectComponent>(&schema.reflect_types),
"Should not be a component" "Should not be a component"
); );
assert!( assert!(
!metadata.has_data_type::<ReflectResource>(&schema.reflect_types), !metadata.has_type_data::<ReflectResource>(&schema.reflect_types),
"Should not be a resource" "Should not be a resource"
); );
assert!( assert!(
metadata.has_data_type::<ReflectDefault>(&schema.reflect_types), metadata.has_type_data::<ReflectDefault>(&schema.reflect_types),
"Should have default" "Should have default"
); );
assert!( assert!(
metadata.has_data_type::<ReflectCustomData>(&schema.reflect_types), metadata.has_type_data::<ReflectCustomData>(&schema.reflect_types),
"Should have CustomData" "Should have CustomData"
); );
assert!(schema.properties.is_empty(), "Should not have any field"); assert!(schema.properties.is_empty(), "Should not have any field");
@ -619,10 +617,9 @@ mod tests {
assert_normalized_values(schema_as_value, value); assert_normalized_values(schema_as_value, value);
} }
fn assert_normalized_values(one: Value, two: Value) { /// This function exist to avoid false failures due to ordering differences between `serde_json` values.
let mut one = one.clone(); fn assert_normalized_values(mut one: Value, mut two: Value) {
normalize_json(&mut one); normalize_json(&mut one);
let mut two = two.clone();
normalize_json(&mut two); normalize_json(&mut two);
assert_eq!(one, two); assert_eq!(one, two);

View File

@ -1,6 +1,4 @@
//! Module with schemas used for various BRP endpoints //! Module with schemas used for various BRP endpoints
use bevy_asset::{ReflectAsset, ReflectHandle};
use bevy_ecs::{ use bevy_ecs::{
reflect::{ReflectComponent, ReflectResource}, reflect::{ReflectComponent, ReflectResource},
resource::Resource, resource::Resource,
@ -20,48 +18,50 @@ pub mod open_rpc;
#[derive(Debug, Resource, Reflect)] #[derive(Debug, Resource, Reflect)]
#[reflect(Resource)] #[reflect(Resource)]
pub struct SchemaTypesMetadata { pub struct SchemaTypesMetadata {
/// data types id mapping to strings. /// Type Data id mapping to strings.
pub data_types: HashMap<TypeId, String>, pub type_data_map: HashMap<TypeId, String>,
} }
impl Default for SchemaTypesMetadata { impl Default for SchemaTypesMetadata {
fn default() -> Self { fn default() -> Self {
let mut data_types = Self { let mut data_types = Self {
data_types: Default::default(), type_data_map: Default::default(),
}; };
data_types.register_type::<ReflectComponent>("Component"); data_types.map_type_data::<ReflectComponent>("Component");
data_types.register_type::<ReflectResource>("Resource"); data_types.map_type_data::<ReflectResource>("Resource");
data_types.register_type::<ReflectDefault>("Default"); data_types.map_type_data::<ReflectDefault>("Default");
data_types.register_type::<ReflectAsset>("Asset"); #[cfg(feature = "bevy_asset")]
data_types.register_type::<ReflectHandle>("AssetHandle"); data_types.map_type_data::<bevy_asset::ReflectAsset>("Asset");
data_types.register_type::<ReflectSerialize>("Serialize"); #[cfg(feature = "bevy_asset")]
data_types.register_type::<ReflectDeserialize>("Deserialize"); data_types.map_type_data::<bevy_asset::ReflectHandle>("AssetHandle");
data_types.map_type_data::<ReflectSerialize>("Serialize");
data_types.map_type_data::<ReflectDeserialize>("Deserialize");
data_types data_types
} }
} }
impl SchemaTypesMetadata { impl SchemaTypesMetadata {
/// Map `TypeId` of `TypeData` to string /// Map `TypeId` of `TypeData` to string
pub fn register_type<T: TypeData>(&mut self, name: impl Into<String>) { pub fn map_type_data<T: TypeData>(&mut self, name: impl Into<String>) {
self.data_types.insert(TypeId::of::<T>(), name.into()); self.type_data_map.insert(TypeId::of::<T>(), name.into());
} }
/// build reflect types list for a given type registration /// Build reflect types list for a given type registration
pub fn get_registered_reflect_types(&self, reg: &TypeRegistration) -> Vec<String> { pub fn get_registered_reflect_types(&self, reg: &TypeRegistration) -> Vec<String> {
self.data_types self.type_data_map
.iter() .iter()
.flat_map(|(id, name)| reg.data_by_id(*id).and(Some(name.clone()))) .filter_map(|(id, name)| reg.data_by_id(*id).and(Some(name.clone())))
.collect() .collect()
} }
/// checks if slice contains string value that matches checked `TypeData` /// Checks if slice contains string value that matches checked `TypeData`
pub fn has_data_type<T: TypeData>(&self, types_string_slice: &[String]) -> bool { pub fn has_type_data<T: TypeData>(&self, types_string_slice: &[String]) -> bool {
self.has_data_type_by_id(TypeId::of::<T>(), types_string_slice) self.has_type_data_by_id(TypeId::of::<T>(), types_string_slice)
} }
/// Checks if slice contains string value that matches checked `TypeData` by id. /// Checks if slice contains string value that matches checked `TypeData` by id.
pub fn has_data_type_by_id(&self, id: TypeId, types_string_slice: &[String]) -> bool { pub fn has_type_data_by_id(&self, id: TypeId, types_string_slice: &[String]) -> bool {
self.data_types self.type_data_map
.get(&id) .get(&id)
.is_some_and(|data_s| types_string_slice.iter().any(|e| e.eq(data_s))) .is_some_and(|data_s| types_string_slice.iter().any(|e| e.eq(data_s)))
} }