From dd20a3bd34d80e54b0bc7adcef17efab6145bd8c Mon Sep 17 00:00:00 2001 From: Piotr Siuszko Date: Thu, 10 Jul 2025 19:23:10 +0200 Subject: [PATCH] Remove ReflectJsonSchema, functionality is provided by CustomInternalSchemaData --- crates/bevy_remote/src/builtin_methods.rs | 2 +- crates/bevy_remote/src/schemas/json_schema.rs | 25 ++- crates/bevy_remote/src/schemas/mod.rs | 151 ++++++++---------- crates/bevy_remote/src/schemas/open_rpc.rs | 27 +--- .../bevy_remote/src/schemas/reflect_info.rs | 40 ++++- 5 files changed, 124 insertions(+), 121 deletions(-) diff --git a/crates/bevy_remote/src/builtin_methods.rs b/crates/bevy_remote/src/builtin_methods.rs index 4c66f1c639..49e520b00e 100644 --- a/crates/bevy_remote/src/builtin_methods.rs +++ b/crates/bevy_remote/src/builtin_methods.rs @@ -1871,7 +1871,7 @@ mod tests { let mut register = atr.write(); register.register::(); register.register::(); - register.register_force_as_array::(); + register.registry_force_schema_to_be_array::(); } let mut world = World::new(); world.insert_resource(atr); diff --git a/crates/bevy_remote/src/schemas/json_schema.rs b/crates/bevy_remote/src/schemas/json_schema.rs index 3fdfcd28f4..ef23d69adf 100644 --- a/crates/bevy_remote/src/schemas/json_schema.rs +++ b/crates/bevy_remote/src/schemas/json_schema.rs @@ -449,7 +449,8 @@ impl SchemaType { mod tests { use crate::schemas::open_rpc::OpenRpcDocument; use crate::schemas::reflect_info::ReferenceLocation; - use crate::schemas::ReflectJsonSchema; + use crate::schemas::CustomInternalSchemaData; + use crate::schemas::ExternalSchemaSource; use super::*; use bevy_ecs::prelude::ReflectComponent; @@ -631,7 +632,7 @@ mod tests { { let mut register = atr.write(); register.register::(); - register.register_type_data::(); + register.register_type_data::(); } let type_registry = atr.read(); let schema = type_registry @@ -656,20 +657,16 @@ mod tests { #[test] fn reflect_export_with_custom_schema() { + /// Custom type for testing purposes. #[derive(Reflect, Component)] struct SomeType; - impl bevy_reflect::FromType for ReflectJsonSchema { - fn from_type() -> Self { - JsonSchemaBevyType { - ref_type: Some(TypeReferencePath::new_ref( - ReferenceLocation::Url, - "raw.githubusercontent.com/open-rpc/meta-schema/master/schema.json", - )), - description: Some("Custom type for testing purposes.".into()), - ..Default::default() - } - .into() + impl ExternalSchemaSource for SomeType { + fn get_external_schema_source() -> TypeReferencePath { + TypeReferencePath::new_ref( + ReferenceLocation::Url, + "raw.githubusercontent.com/open-rpc/meta-schema/master/schema.json", + ) } } @@ -677,7 +674,7 @@ mod tests { { let mut register = atr.write(); register.register::(); - register.register_type_data::(); + register.register_type_data::(); } let type_registry = atr.read(); let schema = type_registry diff --git a/crates/bevy_remote/src/schemas/mod.rs b/crates/bevy_remote/src/schemas/mod.rs index c46479d917..bd274d2435 100644 --- a/crates/bevy_remote/src/schemas/mod.rs +++ b/crates/bevy_remote/src/schemas/mod.rs @@ -1,6 +1,5 @@ //! Module with schemas used for various BRP endpoints use alloc::borrow::Cow; -use bevy_derive::Deref; use bevy_ecs::{ reflect::{ReflectComponent, ReflectResource}, resource::Resource, @@ -13,9 +12,8 @@ use bevy_reflect::{ use core::any::TypeId; use crate::schemas::{ - json_schema::JsonSchemaBevyType, open_rpc::OpenRpcDocument, - reflect_info::{FieldsInformation, InternalSchemaType}, + reflect_info::{FieldsInformation, InternalSchemaType, TypeReferencePath}, }; pub mod json_schema; @@ -36,18 +34,17 @@ pub struct SchemaTypesMetadata { #[reflect(Resource)] pub struct CustomInternalSchemaData(pub InternalSchemaType); -impl CustomInternalSchemaData { - /// Creates a new `CustomInternalSchema` with a forced array type. Works for structs only. - pub fn force_array() -> Option { - match T::get_type_registration().type_info() { - bevy_reflect::TypeInfo::Struct(struct_info) => Some(CustomInternalSchemaData( - InternalSchemaType::FieldsHolder(FieldsInformation::new( - struct_info.iter(), - reflect_info::FieldType::ForceUnnamed(struct_info.ty().id()), - )), - )), - _ => None, - } +/// Trait for external schema sources. +pub trait ExternalSchemaSource { + /// Get the external schema source. + fn get_external_schema_source() -> TypeReferencePath; +} + +impl FromType for CustomInternalSchemaData { + fn from_type() -> Self { + Self(InternalSchemaType::ExternalSource( + T::get_external_schema_source(), + )) } } @@ -57,60 +54,60 @@ pub(crate) trait RegisterReflectJsonSchemas { fn register_schema_base_types(&mut self) { #[cfg(feature = "bevy_math")] { - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); - self.register_force_as_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); + self.registry_force_schema_to_be_array::(); } self.register_type_internal::(); - self.register_type_data_internal::(); + self.register_type_data_internal::(); } /// Registers a type by value. fn register_data_type_by_value(&mut self, data: D) @@ -125,13 +122,21 @@ pub(crate) trait RegisterReflectJsonSchemas { where T: Reflect + TypePath + GetTypeRegistration, D: TypeData + FromType; - fn register_force_as_array(&mut self) + /// Registers a [`CustomInternalSchemaData`] data type for a type that will force to treat the type as an array during building the [`JsonSchemaBevyType`] for given type. + /// It is useful when you want to force the type to be treated as an array in the schema, for example when type has custom serialization. + fn registry_force_schema_to_be_array(&mut self) where T: Reflect + TypePath + GetTypeRegistration, { - let Some(data) = CustomInternalSchemaData::force_array::() else { + let bevy_reflect::TypeInfo::Struct(struct_info) = T::get_type_registration().type_info() + else { return; }; + let data = + CustomInternalSchemaData(InternalSchemaType::FieldsHolder(FieldsInformation::new( + struct_info.iter(), + reflect_info::FieldType::ForceUnnamed(struct_info.ty().id()), + ))); self.register_data_type_by_value::(data); } } @@ -195,22 +200,6 @@ impl RegisterReflectJsonSchemas for bevy_app::App { } } -/// Reflect-compatible custom JSON Schema for this type -#[derive(Clone, Deref)] -pub struct ReflectJsonSchema(pub JsonSchemaBevyType); - -impl From<&JsonSchemaBevyType> for ReflectJsonSchema { - fn from(schema: &JsonSchemaBevyType) -> Self { - Self(schema.clone()) - } -} - -impl From for ReflectJsonSchema { - fn from(schema: JsonSchemaBevyType) -> Self { - Self(schema) - } -} - impl Default for SchemaTypesMetadata { fn default() -> Self { let mut data_types = Self { diff --git a/crates/bevy_remote/src/schemas/open_rpc.rs b/crates/bevy_remote/src/schemas/open_rpc.rs index 160edd38fe..e76c5ca93f 100644 --- a/crates/bevy_remote/src/schemas/open_rpc.rs +++ b/crates/bevy_remote/src/schemas/open_rpc.rs @@ -1,15 +1,12 @@ //! Module with trimmed down `OpenRPC` document structs. //! It tries to follow this standard: use bevy_platform::collections::HashMap; -use bevy_reflect::{FromType, Reflect}; +use bevy_reflect::Reflect; use bevy_utils::default; use serde::{Deserialize, Serialize}; use crate::{ - schemas::{ - reflect_info::{ReferenceLocation, TypeReferencePath}, - ReflectJsonSchema, - }, + schemas::reflect_info::{ReferenceLocation, TypeReferencePath}, RemoteMethods, }; @@ -29,20 +26,12 @@ pub struct OpenRpcDocument { pub servers: Option>, } -impl FromType for ReflectJsonSchema { - fn from_type() -> Self { - JsonSchemaBevyType { - ref_type: Some(TypeReferencePath::new_ref( - ReferenceLocation::Url, - "raw.githubusercontent.com/open-rpc/meta-schema/master/schema.json", - )), - description: Some( - "Represents an `OpenRPC` document as defined by the `OpenRPC` specification." - .into(), - ), - ..default() - } - .into() +impl super::ExternalSchemaSource for OpenRpcDocument { + fn get_external_schema_source() -> TypeReferencePath { + TypeReferencePath::new_ref( + ReferenceLocation::Url, + "raw.githubusercontent.com/open-rpc/meta-schema/master/schema.json", + ) } } diff --git a/crates/bevy_remote/src/schemas/reflect_info.rs b/crates/bevy_remote/src/schemas/reflect_info.rs index baed8f61c0..37520419d2 100644 --- a/crates/bevy_remote/src/schemas/reflect_info.rs +++ b/crates/bevy_remote/src/schemas/reflect_info.rs @@ -531,7 +531,16 @@ impl TypeReferencePath { } impl Display for TypeReferencePath { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{}{}", self.location, encode_to_uri(&self.id)) + write!( + f, + "{}{}", + self.location, + if self.location == ReferenceLocation::Definitions { + encode_to_uri(&self.id) + } else { + (*self.id).to_string() + } + ) } } @@ -929,6 +938,8 @@ pub enum InternalSchemaType { /// Optional field data for the primitive type. field_data: Option, }, + /// Variant for external source types. + ExternalSource(TypeReferencePath), /// Variant for regular primitive types and other simple types. Regular(TypeId), } @@ -1100,7 +1111,7 @@ impl InternalSchemaType { InternalSchemaType::Regular(t) => { _ = dependencies.insert(*t); } - InternalSchemaType::PrimitiveType { .. } => {} + InternalSchemaType::PrimitiveType { .. } | InternalSchemaType::ExternalSource(_) => {} } dependencies } @@ -1137,7 +1148,9 @@ impl From<&InternalSchemaType> for Option { InternalSchemaType::Regular(type_id) => { Some(SchemaTypeVariant::Single((*type_id).into())) } - InternalSchemaType::EnumHolder(_) | InternalSchemaType::Optional { generic: _ } => None, + InternalSchemaType::EnumHolder(_) + | InternalSchemaType::Optional { generic: _ } + | InternalSchemaType::ExternalSource(_) => None, } } } @@ -1472,9 +1485,7 @@ impl TypeDefinitionBuilder for TypeRegistry { let internal = InternalSchemaType::from_type_registration(type_reg, self); let mut id: Option = Some(type_reg.type_info().type_path().into()); - if let Some(custom_schema) = &type_reg.data::() { - return Some((id, custom_schema.0.clone())); - } + let range: MinMaxValues = type_id.into(); let type_path_table = type_reg.type_info().type_path_table(); let (type_path, short_path, crate_name, module_path) = ( @@ -1512,6 +1523,16 @@ impl TypeDefinitionBuilder for TypeRegistry { }; schema.schema_type = (&internal).into(); match internal { + InternalSchemaType::ExternalSource(source) => { + return Some(( + None, + JsonSchemaBevyType { + description: schema.description, + ref_type: Some(source), + ..Default::default() + }, + )); + } InternalSchemaType::PrimitiveType { type_id: _, primitive: _, @@ -1641,6 +1662,13 @@ impl TypeDefinitionBuilder for TypeRegistry { let internal = InternalSchemaType::from_type_registration(type_reg, self); schema.schema_type = (&internal).into(); match internal { + InternalSchemaType::ExternalSource(source) => { + return Some(JsonSchemaBevyType { + description: schema.description, + ref_type: Some(source), + ..Default::default() + }); + } InternalSchemaType::PrimitiveType { type_id, primitive: _,