Schema types metadata (#19524)
# Objective - Currently there is predefinied list of supported DataTypes that can be detected on Bevy JSON Schema generation and mapped as reflect_types array elements. - Make it possible to register custom `reflectTypes` mappings for Bevy JSON Schema. ## Solution - Create a `SchemaTypesMetadata` Resource that will hold mappings for `TypeId` of `TypeData`. List is bigger from beggining and it is possible to expand it without forking package. ## Testing - I use it for quite a while in my game, I have a fork of bevy_remote with more changes that later I want to merge to main as well. --------- Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
This commit is contained in:
parent
ffd6c9e1c9
commit
84f21f7c8a
@ -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
|
||||||
@ -28,6 +29,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", optional = true }
|
||||||
|
|
||||||
# other
|
# other
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
|
@ -24,7 +24,10 @@ use serde_json::{Map, Value};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
error_codes,
|
error_codes,
|
||||||
schemas::{json_schema::JsonSchemaBevyType, open_rpc::OpenRpcDocument},
|
schemas::{
|
||||||
|
json_schema::{export_type, JsonSchemaBevyType},
|
||||||
|
open_rpc::OpenRpcDocument,
|
||||||
|
},
|
||||||
BrpError, BrpResult,
|
BrpError, BrpResult,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1223,24 +1226,27 @@ pub fn export_registry_types(In(params): In<Option<Value>>, world: &World) -> Br
|
|||||||
Some(params) => parse(params)?,
|
Some(params) => parse(params)?,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let extra_info = world.resource::<crate::schemas::SchemaTypesMetadata>();
|
||||||
let types = world.resource::<AppTypeRegistry>();
|
let types = world.resource::<AppTypeRegistry>();
|
||||||
let types = types.read();
|
let types = types.read();
|
||||||
let schemas = types
|
let schemas = types
|
||||||
.iter()
|
.iter()
|
||||||
.map(crate::schemas::json_schema::export_type)
|
.filter_map(|type_reg| {
|
||||||
.filter(|(_, schema)| {
|
let path_table = type_reg.type_info().type_path_table();
|
||||||
if let Some(crate_name) = &schema.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);
|
||||||
|
|
||||||
if !filter.type_limit.with.is_empty()
|
if !filter.type_limit.with.is_empty()
|
||||||
&& !filter
|
&& !filter
|
||||||
.type_limit
|
.type_limit
|
||||||
@ -1248,7 +1254,7 @@ pub fn export_registry_types(In(params): In<Option<Value>>, world: &World) -> Br
|
|||||||
.iter()
|
.iter()
|
||||||
.any(|c| schema.reflect_types.iter().any(|cc| c.eq(cc)))
|
.any(|c| schema.reflect_types.iter().any(|cc| c.eq(cc)))
|
||||||
{
|
{
|
||||||
return false;
|
return None;
|
||||||
}
|
}
|
||||||
if !filter.type_limit.without.is_empty()
|
if !filter.type_limit.without.is_empty()
|
||||||
&& filter
|
&& filter
|
||||||
@ -1257,10 +1263,9 @@ pub fn export_registry_types(In(params): In<Option<Value>>, world: &World) -> Br
|
|||||||
.iter()
|
.iter()
|
||||||
.any(|c| schema.reflect_types.iter().any(|cc| c.eq(cc)))
|
.any(|c| schema.reflect_types.iter().any(|cc| c.eq(cc)))
|
||||||
{
|
{
|
||||||
return false;
|
return None;
|
||||||
}
|
}
|
||||||
|
Some((id.to_string(), schema))
|
||||||
true
|
|
||||||
})
|
})
|
||||||
.collect::<HashMap<String, JsonSchemaBevyType>>();
|
.collect::<HashMap<String, JsonSchemaBevyType>>();
|
||||||
|
|
||||||
|
@ -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};
|
||||||
@ -539,6 +541,7 @@ impl Plugin for RemotePlugin {
|
|||||||
.insert_after(Last, RemoteLast);
|
.insert_after(Last, RemoteLast);
|
||||||
|
|
||||||
app.insert_resource(remote_methods)
|
app.insert_resource(remote_methods)
|
||||||
|
.init_resource::<schemas::SchemaTypesMetadata>()
|
||||||
.init_resource::<RemoteWatchingRequests>()
|
.init_resource::<RemoteWatchingRequests>()
|
||||||
.add_systems(PreStartup, setup_mailbox_channel)
|
.add_systems(PreStartup, setup_mailbox_channel)
|
||||||
.configure_sets(
|
.configure_sets(
|
||||||
|
@ -1,47 +1,63 @@
|
|||||||
//! 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 bevy_ecs::reflect::{ReflectComponent, ReflectResource};
|
use alloc::borrow::Cow;
|
||||||
use bevy_platform::collections::HashMap;
|
use bevy_platform::collections::HashMap;
|
||||||
use bevy_reflect::{
|
use bevy_reflect::{
|
||||||
prelude::ReflectDefault, NamedField, OpaqueInfo, ReflectDeserialize, ReflectSerialize,
|
GetTypeRegistration, NamedField, OpaqueInfo, TypeInfo, TypeRegistration, TypeRegistry,
|
||||||
TypeInfo, TypeRegistration, VariantInfo,
|
VariantInfo,
|
||||||
};
|
};
|
||||||
use core::any::TypeId;
|
use core::any::TypeId;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::{json, Map, Value};
|
use serde_json::{json, Map, Value};
|
||||||
|
|
||||||
/// Exports schema info for a given type
|
use crate::schemas::SchemaTypesMetadata;
|
||||||
pub fn export_type(reg: &TypeRegistration) -> (String, JsonSchemaBevyType) {
|
|
||||||
(reg.type_info().type_path().to_owned(), reg.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_registered_reflect_types(reg: &TypeRegistration) -> Vec<String> {
|
/// Helper trait for converting `TypeRegistration` to `JsonSchemaBevyType`
|
||||||
// Vec could be moved to allow registering more types by game maker.
|
pub trait TypeRegistrySchemaReader {
|
||||||
let registered_reflect_types: [(TypeId, &str); 5] = [
|
/// Export type JSON Schema.
|
||||||
{ (TypeId::of::<ReflectComponent>(), "Component") },
|
fn export_type_json_schema<T: GetTypeRegistration + 'static>(
|
||||||
{ (TypeId::of::<ReflectResource>(), "Resource") },
|
&self,
|
||||||
{ (TypeId::of::<ReflectDefault>(), "Default") },
|
extra_info: &SchemaTypesMetadata,
|
||||||
{ (TypeId::of::<ReflectSerialize>(), "Serialize") },
|
) -> Option<JsonSchemaBevyType> {
|
||||||
{ (TypeId::of::<ReflectDeserialize>(), "Deserialize") },
|
self.export_type_json_schema_for_id(extra_info, TypeId::of::<T>())
|
||||||
];
|
|
||||||
let mut result = Vec::new();
|
|
||||||
for (id, name) in registered_reflect_types {
|
|
||||||
if reg.data_by_id(id).is_some() {
|
|
||||||
result.push(name.to_owned());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
result
|
/// Export type JSON Schema.
|
||||||
|
fn export_type_json_schema_for_id(
|
||||||
|
&self,
|
||||||
|
extra_info: &SchemaTypesMetadata,
|
||||||
|
type_id: TypeId,
|
||||||
|
) -> Option<JsonSchemaBevyType>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&TypeRegistration> for JsonSchemaBevyType {
|
impl TypeRegistrySchemaReader for TypeRegistry {
|
||||||
fn from(reg: &TypeRegistration) -> Self {
|
fn export_type_json_schema_for_id(
|
||||||
|
&self,
|
||||||
|
extra_info: &SchemaTypesMetadata,
|
||||||
|
type_id: TypeId,
|
||||||
|
) -> Option<JsonSchemaBevyType> {
|
||||||
|
let type_reg = self.get(type_id)?;
|
||||||
|
Some((type_reg, extra_info).into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Exports schema info for a given type
|
||||||
|
pub fn export_type(
|
||||||
|
reg: &TypeRegistration,
|
||||||
|
metadata: &SchemaTypesMetadata,
|
||||||
|
) -> (Cow<'static, str>, JsonSchemaBevyType) {
|
||||||
|
(reg.type_info().type_path().into(), (reg, metadata).into())
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<(&TypeRegistration, &SchemaTypesMetadata)> for JsonSchemaBevyType {
|
||||||
|
fn from(value: (&TypeRegistration, &SchemaTypesMetadata)) -> Self {
|
||||||
|
let (reg, metadata) = value;
|
||||||
let t = reg.type_info();
|
let t = reg.type_info();
|
||||||
let binding = t.type_path_table();
|
let binding = t.type_path_table();
|
||||||
|
|
||||||
let short_path = binding.short_path();
|
let short_path = binding.short_path();
|
||||||
let type_path = binding.path();
|
let type_path = binding.path();
|
||||||
let mut typed_schema = JsonSchemaBevyType {
|
let mut typed_schema = JsonSchemaBevyType {
|
||||||
reflect_types: get_registered_reflect_types(reg),
|
reflect_types: metadata.get_registered_reflect_types(reg),
|
||||||
short_path: short_path.to_owned(),
|
short_path: short_path.to_owned(),
|
||||||
type_path: type_path.to_owned(),
|
type_path: type_path.to_owned(),
|
||||||
crate_name: binding.crate_name().map(str::to_owned),
|
crate_name: binding.crate_name().map(str::to_owned),
|
||||||
@ -351,8 +367,12 @@ impl SchemaJsonReference for &NamedField {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use bevy_ecs::prelude::ReflectComponent;
|
||||||
|
use bevy_ecs::prelude::ReflectResource;
|
||||||
|
|
||||||
use bevy_ecs::{component::Component, reflect::AppTypeRegistry, resource::Resource};
|
use bevy_ecs::{component::Component, reflect::AppTypeRegistry, resource::Resource};
|
||||||
use bevy_reflect::Reflect;
|
use bevy_reflect::prelude::ReflectDefault;
|
||||||
|
use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn reflect_export_struct() {
|
fn reflect_export_struct() {
|
||||||
@ -373,7 +393,7 @@ mod tests {
|
|||||||
.get(TypeId::of::<Foo>())
|
.get(TypeId::of::<Foo>())
|
||||||
.expect("SHOULD BE REGISTERED")
|
.expect("SHOULD BE REGISTERED")
|
||||||
.clone();
|
.clone();
|
||||||
let (_, schema) = export_type(&foo_registration);
|
let (_, schema) = export_type(&foo_registration, &SchemaTypesMetadata::default());
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
!schema.reflect_types.contains(&"Component".to_owned()),
|
!schema.reflect_types.contains(&"Component".to_owned()),
|
||||||
@ -418,7 +438,7 @@ mod tests {
|
|||||||
.get(TypeId::of::<EnumComponent>())
|
.get(TypeId::of::<EnumComponent>())
|
||||||
.expect("SHOULD BE REGISTERED")
|
.expect("SHOULD BE REGISTERED")
|
||||||
.clone();
|
.clone();
|
||||||
let (_, schema) = export_type(&foo_registration);
|
let (_, schema) = export_type(&foo_registration, &SchemaTypesMetadata::default());
|
||||||
assert!(
|
assert!(
|
||||||
schema.reflect_types.contains(&"Component".to_owned()),
|
schema.reflect_types.contains(&"Component".to_owned()),
|
||||||
"Should be a component"
|
"Should be a component"
|
||||||
@ -453,7 +473,7 @@ mod tests {
|
|||||||
.get(TypeId::of::<EnumComponent>())
|
.get(TypeId::of::<EnumComponent>())
|
||||||
.expect("SHOULD BE REGISTERED")
|
.expect("SHOULD BE REGISTERED")
|
||||||
.clone();
|
.clone();
|
||||||
let (_, schema) = export_type(&foo_registration);
|
let (_, schema) = export_type(&foo_registration, &SchemaTypesMetadata::default());
|
||||||
assert!(
|
assert!(
|
||||||
!schema.reflect_types.contains(&"Component".to_owned()),
|
!schema.reflect_types.contains(&"Component".to_owned()),
|
||||||
"Should not be a component"
|
"Should not be a component"
|
||||||
@ -466,6 +486,62 @@ mod tests {
|
|||||||
assert!(schema.one_of.len() == 3, "Should have 3 possible schemas");
|
assert!(schema.one_of.len() == 3, "Should have 3 possible schemas");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn reflect_struct_with_custom_type_data() {
|
||||||
|
#[derive(Reflect, Default, Deserialize, Serialize)]
|
||||||
|
#[reflect(Default)]
|
||||||
|
enum EnumComponent {
|
||||||
|
ValueOne(i32),
|
||||||
|
ValueTwo {
|
||||||
|
test: i32,
|
||||||
|
},
|
||||||
|
#[default]
|
||||||
|
NoValue,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ReflectCustomData;
|
||||||
|
|
||||||
|
impl<T: Reflect> bevy_reflect::FromType<T> for ReflectCustomData {
|
||||||
|
fn from_type() -> Self {
|
||||||
|
ReflectCustomData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let atr = AppTypeRegistry::default();
|
||||||
|
{
|
||||||
|
let mut register = atr.write();
|
||||||
|
register.register::<EnumComponent>();
|
||||||
|
register.register_type_data::<EnumComponent, ReflectCustomData>();
|
||||||
|
}
|
||||||
|
let mut metadata = SchemaTypesMetadata::default();
|
||||||
|
metadata.map_type_data::<ReflectCustomData>("CustomData");
|
||||||
|
let type_registry = atr.read();
|
||||||
|
let foo_registration = type_registry
|
||||||
|
.get(TypeId::of::<EnumComponent>())
|
||||||
|
.expect("SHOULD BE REGISTERED")
|
||||||
|
.clone();
|
||||||
|
let (_, schema) = export_type(&foo_registration, &metadata);
|
||||||
|
assert!(
|
||||||
|
!metadata.has_type_data::<ReflectComponent>(&schema.reflect_types),
|
||||||
|
"Should not be a component"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
!metadata.has_type_data::<ReflectResource>(&schema.reflect_types),
|
||||||
|
"Should not be a resource"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
metadata.has_type_data::<ReflectDefault>(&schema.reflect_types),
|
||||||
|
"Should have default"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
metadata.has_type_data::<ReflectCustomData>(&schema.reflect_types),
|
||||||
|
"Should have CustomData"
|
||||||
|
);
|
||||||
|
assert!(schema.properties.is_empty(), "Should not have any field");
|
||||||
|
assert!(schema.one_of.len() == 3, "Should have 3 possible schemas");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn reflect_export_tuple_struct() {
|
fn reflect_export_tuple_struct() {
|
||||||
#[derive(Reflect, Component, Default, Deserialize, Serialize)]
|
#[derive(Reflect, Component, Default, Deserialize, Serialize)]
|
||||||
@ -482,7 +558,7 @@ mod tests {
|
|||||||
.get(TypeId::of::<TupleStructType>())
|
.get(TypeId::of::<TupleStructType>())
|
||||||
.expect("SHOULD BE REGISTERED")
|
.expect("SHOULD BE REGISTERED")
|
||||||
.clone();
|
.clone();
|
||||||
let (_, schema) = export_type(&foo_registration);
|
let (_, schema) = export_type(&foo_registration, &SchemaTypesMetadata::default());
|
||||||
assert!(
|
assert!(
|
||||||
schema.reflect_types.contains(&"Component".to_owned()),
|
schema.reflect_types.contains(&"Component".to_owned()),
|
||||||
"Should be a component"
|
"Should be a component"
|
||||||
@ -513,7 +589,7 @@ mod tests {
|
|||||||
.get(TypeId::of::<Foo>())
|
.get(TypeId::of::<Foo>())
|
||||||
.expect("SHOULD BE REGISTERED")
|
.expect("SHOULD BE REGISTERED")
|
||||||
.clone();
|
.clone();
|
||||||
let (_, schema) = export_type(&foo_registration);
|
let (_, schema) = export_type(&foo_registration, &SchemaTypesMetadata::default());
|
||||||
let schema_as_value = serde_json::to_value(&schema).expect("Should serialize");
|
let schema_as_value = serde_json::to_value(&schema).expect("Should serialize");
|
||||||
let value = json!({
|
let value = json!({
|
||||||
"shortPath": "Foo",
|
"shortPath": "Foo",
|
||||||
@ -538,6 +614,31 @@ mod tests {
|
|||||||
"a"
|
"a"
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
assert_eq!(schema_as_value, value);
|
assert_normalized_values(schema_as_value, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This function exist to avoid false failures due to ordering differences between `serde_json` values.
|
||||||
|
fn assert_normalized_values(mut one: Value, mut two: Value) {
|
||||||
|
normalize_json(&mut one);
|
||||||
|
normalize_json(&mut two);
|
||||||
|
assert_eq!(one, two);
|
||||||
|
|
||||||
|
/// Recursively sorts arrays in a `serde_json::Value`
|
||||||
|
fn normalize_json(value: &mut Value) {
|
||||||
|
match value {
|
||||||
|
Value::Array(arr) => {
|
||||||
|
for v in arr.iter_mut() {
|
||||||
|
normalize_json(v);
|
||||||
|
}
|
||||||
|
arr.sort_by_key(ToString::to_string); // Sort by stringified version
|
||||||
|
}
|
||||||
|
Value::Object(map) => {
|
||||||
|
for (_k, v) in map.iter_mut() {
|
||||||
|
normalize_json(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,68 @@
|
|||||||
//! Module with schemas used for various BRP endpoints
|
//! Module with schemas used for various BRP endpoints
|
||||||
|
use bevy_ecs::{
|
||||||
|
reflect::{ReflectComponent, ReflectResource},
|
||||||
|
resource::Resource,
|
||||||
|
};
|
||||||
|
use bevy_platform::collections::HashMap;
|
||||||
|
use bevy_reflect::{
|
||||||
|
prelude::ReflectDefault, Reflect, ReflectDeserialize, ReflectSerialize, TypeData,
|
||||||
|
TypeRegistration,
|
||||||
|
};
|
||||||
|
use core::any::TypeId;
|
||||||
|
|
||||||
pub mod json_schema;
|
pub mod json_schema;
|
||||||
pub mod open_rpc;
|
pub mod open_rpc;
|
||||||
|
|
||||||
|
/// Holds mapping of reflect [type data](TypeData) to strings,
|
||||||
|
/// later on used in Bevy Json Schema.
|
||||||
|
#[derive(Debug, Resource, Reflect)]
|
||||||
|
#[reflect(Resource)]
|
||||||
|
pub struct SchemaTypesMetadata {
|
||||||
|
/// Type Data id mapping to strings.
|
||||||
|
pub type_data_map: HashMap<TypeId, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for SchemaTypesMetadata {
|
||||||
|
fn default() -> Self {
|
||||||
|
let mut data_types = Self {
|
||||||
|
type_data_map: Default::default(),
|
||||||
|
};
|
||||||
|
data_types.map_type_data::<ReflectComponent>("Component");
|
||||||
|
data_types.map_type_data::<ReflectResource>("Resource");
|
||||||
|
data_types.map_type_data::<ReflectDefault>("Default");
|
||||||
|
#[cfg(feature = "bevy_asset")]
|
||||||
|
data_types.map_type_data::<bevy_asset::ReflectAsset>("Asset");
|
||||||
|
#[cfg(feature = "bevy_asset")]
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SchemaTypesMetadata {
|
||||||
|
/// Map `TypeId` of `TypeData` to string
|
||||||
|
pub fn map_type_data<T: TypeData>(&mut self, name: impl Into<String>) {
|
||||||
|
self.type_data_map.insert(TypeId::of::<T>(), name.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Build reflect types list for a given type registration
|
||||||
|
pub fn get_registered_reflect_types(&self, reg: &TypeRegistration) -> Vec<String> {
|
||||||
|
self.type_data_map
|
||||||
|
.iter()
|
||||||
|
.filter_map(|(id, name)| reg.data_by_id(*id).and(Some(name.clone())))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if slice contains string value that matches checked `TypeData`
|
||||||
|
pub fn has_type_data<T: TypeData>(&self, types_string_slice: &[String]) -> bool {
|
||||||
|
self.has_type_data_by_id(TypeId::of::<T>(), types_string_slice)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if slice contains string value that matches checked `TypeData` by id.
|
||||||
|
pub fn has_type_data_by_id(&self, id: TypeId, types_string_slice: &[String]) -> bool {
|
||||||
|
self.type_data_map
|
||||||
|
.get(&id)
|
||||||
|
.is_some_and(|data_s| types_string_slice.iter().any(|e| e.eq(data_s)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user