Cleanup and refactor
This commit is contained in:
parent
2f03beb2d0
commit
27366c9f4f
@ -9,10 +9,11 @@ license = "MIT OR Apache-2.0"
|
|||||||
keywords = ["bevy"]
|
keywords = ["bevy"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["http", "bevy_asset", "documentation"]
|
default = ["http", "bevy_asset", "documentation", "bevy_math"]
|
||||||
documentation = ["bevy_reflect/documentation"]
|
documentation = ["bevy_reflect/documentation"]
|
||||||
http = ["dep:async-io", "dep:smol-hyper"]
|
http = ["dep:async-io", "dep:smol-hyper"]
|
||||||
bevy_asset = ["dep:bevy_asset"]
|
bevy_asset = ["dep:bevy_asset"]
|
||||||
|
bevy_math = ["dep:bevy_math", "bevy_reflect/glam"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# bevy
|
# bevy
|
||||||
@ -31,6 +32,7 @@ bevy_platform = { path = "../bevy_platform", version = "0.17.0-dev", default-fea
|
|||||||
"serialize",
|
"serialize",
|
||||||
] }
|
] }
|
||||||
bevy_asset = { path = "../bevy_asset", version = "0.17.0-dev", optional = true }
|
bevy_asset = { path = "../bevy_asset", version = "0.17.0-dev", optional = true }
|
||||||
|
bevy_math = { path = "../bevy_math", version = "0.17.0-dev", optional = true }
|
||||||
|
|
||||||
# other
|
# other
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
|
|||||||
@ -518,7 +518,8 @@ impl Default for RemotePlugin {
|
|||||||
|
|
||||||
impl Plugin for RemotePlugin {
|
impl Plugin for RemotePlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.register_type::<schemas::open_rpc::OpenRpcDocument>().register_type_data::<schemas::open_rpc::OpenRpcDocument, schemas::ReflectJsonSchema>();
|
app.register_type::<schemas::open_rpc::OpenRpcDocument>()
|
||||||
|
.register_type_data::<schemas::open_rpc::OpenRpcDocument, schemas::ReflectJsonSchema>();
|
||||||
|
|
||||||
let mut remote_methods = RemoteMethods::new();
|
let mut remote_methods = RemoteMethods::new();
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use crate::schemas::{
|
use crate::schemas::{
|
||||||
reflect_info::{SchemaInfoReflect, SchemaNumber},
|
reflect_info::{SchemaNumber, TypeReferenceId, TypeReferencePath},
|
||||||
ReflectJsonSchema, SchemaTypesMetadata,
|
ReflectJsonSchema, SchemaTypesMetadata,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -82,8 +82,7 @@ impl TryFrom<(&TypeRegistration, &SchemaTypesMetadata)> for JsonSchemaBevyType {
|
|||||||
if let Some(s) = reg.data::<ReflectJsonSchema>() {
|
if let Some(s) = reg.data::<ReflectJsonSchema>() {
|
||||||
return Ok(s.0.clone());
|
return Ok(s.0.clone());
|
||||||
}
|
}
|
||||||
let type_info = reg.type_info();
|
let base_schema = super::reflect_info::build_schema(reg);
|
||||||
let base_schema = type_info.build_schema();
|
|
||||||
|
|
||||||
let JsonSchemaVariant::Schema(mut typed_schema) = base_schema else {
|
let JsonSchemaVariant::Schema(mut typed_schema) = base_schema else {
|
||||||
return Err(InvalidJsonSchema::InvalidType);
|
return Err(InvalidJsonSchema::InvalidType);
|
||||||
@ -126,7 +125,7 @@ pub struct JsonSchemaBevyType {
|
|||||||
/// This keyword is used to reference a statically identified schema.
|
/// This keyword is used to reference a statically identified schema.
|
||||||
#[serde(rename = "$ref")]
|
#[serde(rename = "$ref")]
|
||||||
#[serde(skip_serializing_if = "Option::is_none", default)]
|
#[serde(skip_serializing_if = "Option::is_none", default)]
|
||||||
pub ref_type: Option<Cow<'static, str>>,
|
pub ref_type: Option<TypeReferencePath>,
|
||||||
/// Bevy specific field, short path of the type.
|
/// Bevy specific field, short path of the type.
|
||||||
#[serde(skip_serializing_if = "str::is_empty", default)]
|
#[serde(skip_serializing_if = "str::is_empty", default)]
|
||||||
pub short_path: Cow<'static, str>,
|
pub short_path: Cow<'static, str>,
|
||||||
@ -144,16 +143,22 @@ pub struct JsonSchemaBevyType {
|
|||||||
pub reflect_type_data: Vec<Cow<'static, str>>,
|
pub reflect_type_data: Vec<Cow<'static, str>>,
|
||||||
/// Bevy specific field, [`TypeInfo`] type mapping.
|
/// Bevy specific field, [`TypeInfo`] type mapping.
|
||||||
pub kind: SchemaKind,
|
pub kind: SchemaKind,
|
||||||
/// Bevy specific field, provided when [`SchemaKind`] `kind` field is equal to [`SchemaKind::Map`].
|
/// JSON Schema specific field.
|
||||||
///
|
/// This keyword is used to reference a constant value.
|
||||||
/// It contains type info of key of the Map.
|
#[serde(rename = "const")]
|
||||||
#[serde(skip_serializing_if = "Option::is_none", default)]
|
#[serde(skip_serializing_if = "Option::is_none", default)]
|
||||||
pub key_type: Option<JsonSchemaVariant>,
|
#[reflect(ignore)]
|
||||||
|
pub const_value: Option<Value>,
|
||||||
/// Bevy specific field, provided when [`SchemaKind`] `kind` field is equal to [`SchemaKind::Map`].
|
/// Bevy specific field, provided when [`SchemaKind`] `kind` field is equal to [`SchemaKind::Map`].
|
||||||
///
|
///
|
||||||
/// It contains type info of value of the Map.
|
/// It contains type info of value of the Map.
|
||||||
#[serde(skip_serializing_if = "Option::is_none", default)]
|
#[serde(skip_serializing_if = "Option::is_none", default)]
|
||||||
pub value_type: Option<JsonSchemaVariant>,
|
pub value_type: Option<JsonSchemaVariant>,
|
||||||
|
/// Bevy specific field, provided when [`SchemaKind`] `kind` field is equal to [`SchemaKind::Map`].
|
||||||
|
///
|
||||||
|
/// It contains type info of key of the Map.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none", default)]
|
||||||
|
pub key_type: Option<JsonSchemaVariant>,
|
||||||
/// The type keyword is fundamental to JSON Schema. It specifies the data type for a schema.
|
/// The type keyword is fundamental to JSON Schema. It specifies the data type for a schema.
|
||||||
#[serde(skip_serializing_if = "Option::is_none", default)]
|
#[serde(skip_serializing_if = "Option::is_none", default)]
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
@ -231,11 +236,16 @@ pub struct JsonSchemaBevyType {
|
|||||||
pub exclusive_maximum: Option<SchemaNumber>,
|
pub exclusive_maximum: Option<SchemaNumber>,
|
||||||
/// Type description
|
/// Type description
|
||||||
#[serde(skip_serializing_if = "Option::is_none", default)]
|
#[serde(skip_serializing_if = "Option::is_none", default)]
|
||||||
pub description: Option<String>,
|
pub description: Option<Cow<'static, str>>,
|
||||||
/// Default value for the schema.
|
/// Default value for the schema.
|
||||||
#[serde(skip_serializing_if = "Option::is_none", default, rename = "default")]
|
#[serde(skip_serializing_if = "Option::is_none", default, rename = "default")]
|
||||||
#[reflect(ignore)]
|
#[reflect(ignore)]
|
||||||
pub default_value: Option<Value>,
|
pub default_value: Option<Value>,
|
||||||
|
/// Definitions for the schema.
|
||||||
|
#[serde(skip_serializing_if = "HashMap::is_empty", default)]
|
||||||
|
#[reflect(ignore)]
|
||||||
|
#[serde(rename = "$defs")]
|
||||||
|
pub definitions: HashMap<TypeReferenceId, Box<JsonSchemaVariant>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents different types of JSON Schema values that can be used in schema definitions.
|
/// Represents different types of JSON Schema values that can be used in schema definitions.
|
||||||
@ -250,19 +260,6 @@ pub enum JsonSchemaVariant {
|
|||||||
/// This is commonly used for properties like `additionalProperties` where
|
/// This is commonly used for properties like `additionalProperties` where
|
||||||
/// a boolean true/false indicates whether additional properties are allowed.
|
/// a boolean true/false indicates whether additional properties are allowed.
|
||||||
BoolValue(bool),
|
BoolValue(bool),
|
||||||
/// A constant value with an optional description.
|
|
||||||
///
|
|
||||||
/// This variant represents a JSON Schema `const` keyword, which specifies
|
|
||||||
/// that a value must be exactly equal to the given constant value.
|
|
||||||
Const {
|
|
||||||
/// The constant value that must be matched exactly.
|
|
||||||
#[reflect(ignore)]
|
|
||||||
#[serde(rename = "const")]
|
|
||||||
value: Value,
|
|
||||||
/// Optional human-readable description of the constant value.
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none", default)]
|
|
||||||
description: Option<String>,
|
|
||||||
},
|
|
||||||
/// A full JSON Schema definition.
|
/// A full JSON Schema definition.
|
||||||
///
|
///
|
||||||
/// This variant contains a complete schema object that defines the structure,
|
/// This variant contains a complete schema object that defines the structure,
|
||||||
@ -270,28 +267,6 @@ pub enum JsonSchemaVariant {
|
|||||||
Schema(#[reflect(ignore)] Box<JsonSchemaBevyType>),
|
Schema(#[reflect(ignore)] Box<JsonSchemaBevyType>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl JsonSchemaVariant {
|
|
||||||
/// Creates a new constant value variant from any serializable type.
|
|
||||||
///
|
|
||||||
/// This is a convenience constructor that serializes the provided value
|
|
||||||
/// to JSON and wraps it in the `Const` variant with an optional description.
|
|
||||||
///
|
|
||||||
/// # Arguments
|
|
||||||
///
|
|
||||||
/// * `serializable` - Any value that implements `Serialize`
|
|
||||||
/// * `description` - Optional description for the constant value
|
|
||||||
///
|
|
||||||
/// # Returns
|
|
||||||
///
|
|
||||||
/// A new `JsonSchemaVariant::Const` with the serialized value
|
|
||||||
pub fn const_value(serializable: impl Serialize, description: Option<String>) -> Self {
|
|
||||||
Self::Const {
|
|
||||||
value: serde_json::to_value(serializable).unwrap_or_default(),
|
|
||||||
description,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Kind of json schema, maps [`TypeInfo`] type
|
/// Kind of json schema, maps [`TypeInfo`] type
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default, Reflect)]
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default, Reflect)]
|
||||||
pub enum SchemaKind {
|
pub enum SchemaKind {
|
||||||
@ -312,7 +287,7 @@ pub enum SchemaKind {
|
|||||||
TupleStruct,
|
TupleStruct,
|
||||||
/// Set of unique values
|
/// Set of unique values
|
||||||
Set,
|
Set,
|
||||||
/// Single value, eg. primitive types
|
/// Single value, eg. primitive types or enum variant
|
||||||
Value,
|
Value,
|
||||||
/// Opaque type
|
/// Opaque type
|
||||||
Opaque,
|
Opaque,
|
||||||
@ -336,10 +311,29 @@ pub enum SchemaTypeVariant {
|
|||||||
Multiple(Vec<SchemaType>),
|
Multiple(Vec<SchemaType>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SchemaTypeVariant {
|
||||||
|
/// Adds a new type to the variant.
|
||||||
|
pub fn with(self, new: SchemaType) -> Self {
|
||||||
|
match self {
|
||||||
|
Self::Single(t) => match t.eq(&new) {
|
||||||
|
true => Self::Single(t),
|
||||||
|
false => Self::Multiple(vec![t, new]),
|
||||||
|
},
|
||||||
|
Self::Multiple(mut types) => match types.contains(&new) {
|
||||||
|
true => Self::Multiple(types),
|
||||||
|
false => {
|
||||||
|
types.push(new);
|
||||||
|
Self::Multiple(types)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Type of json schema
|
/// Type of json schema
|
||||||
/// More [here](https://json-schema.org/draft-07/draft-handrews-json-schema-01#rfc.section.4.2.1)
|
/// More [here](https://json-schema.org/draft-07/draft-handrews-json-schema-01#rfc.section.4.2.1)
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug, Serialize, Deserialize, Clone, PartialEq, Reflect, Default, Eq, PartialOrd, Ord,
|
Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Reflect, Default, Eq, PartialOrd, Ord,
|
||||||
)]
|
)]
|
||||||
#[serde(rename_all = "lowercase")]
|
#[serde(rename_all = "lowercase")]
|
||||||
pub enum SchemaType {
|
pub enum SchemaType {
|
||||||
@ -403,7 +397,7 @@ impl SchemaType {
|
|||||||
/// Returns the primitive type corresponding to the given type ID, if it exists.
|
/// Returns the primitive type corresponding to the given type ID, if it exists.
|
||||||
pub fn try_get_primitive_type_from_type_id(type_id: TypeId) -> Option<Self> {
|
pub fn try_get_primitive_type_from_type_id(type_id: TypeId) -> Option<Self> {
|
||||||
let schema_type: SchemaType = type_id.into();
|
let schema_type: SchemaType = type_id.into();
|
||||||
if schema_type.eq(&Self::Object) {
|
if schema_type.eq(&Self::Object) || schema_type.eq(&Self::Array) {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(schema_type)
|
Some(schema_type)
|
||||||
@ -413,6 +407,8 @@ impl SchemaType {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use crate::schemas::reflect_info::ReferenceLocation;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use bevy_ecs::prelude::ReflectComponent;
|
use bevy_ecs::prelude::ReflectComponent;
|
||||||
use bevy_ecs::prelude::ReflectResource;
|
use bevy_ecs::prelude::ReflectResource;
|
||||||
@ -434,10 +430,6 @@ mod tests {
|
|||||||
else {
|
else {
|
||||||
panic!("Failed to export JSON schema for Foo");
|
panic!("Failed to export JSON schema for Foo");
|
||||||
};
|
};
|
||||||
eprintln!(
|
|
||||||
"{}",
|
|
||||||
serde_json::to_string_pretty(&schema).expect("Failed to serialize schema")
|
|
||||||
);
|
|
||||||
schema
|
schema
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -482,12 +474,13 @@ mod tests {
|
|||||||
#[derive(Reflect, Component, Default, Deserialize, Serialize)]
|
#[derive(Reflect, Component, Default, Deserialize, Serialize)]
|
||||||
#[reflect(Component, Default, Serialize, Deserialize)]
|
#[reflect(Component, Default, Serialize, Deserialize)]
|
||||||
enum EnumComponent {
|
enum EnumComponent {
|
||||||
ValueOne(i32),
|
ValueOne(Option<i32>, i32),
|
||||||
ValueTwo {
|
ValueTwo {
|
||||||
#[reflect(@111..5555i32)]
|
#[reflect(@111..5555i32)]
|
||||||
test: i32,
|
test: i32,
|
||||||
},
|
},
|
||||||
#[default]
|
#[default]
|
||||||
|
/// default option
|
||||||
NoValue,
|
NoValue,
|
||||||
}
|
}
|
||||||
let schema = export_type::<EnumComponent>();
|
let schema = export_type::<EnumComponent>();
|
||||||
@ -540,7 +533,7 @@ mod tests {
|
|||||||
#[derive(Reflect, Default, Deserialize, Serialize)]
|
#[derive(Reflect, Default, Deserialize, Serialize)]
|
||||||
#[reflect(Default)]
|
#[reflect(Default)]
|
||||||
enum EnumComponent {
|
enum EnumComponent {
|
||||||
ValueOne(i32),
|
ValueOne(i32, #[reflect(@..155i16)] i16),
|
||||||
ValueTwo {
|
ValueTwo {
|
||||||
test: i32,
|
test: i32,
|
||||||
},
|
},
|
||||||
@ -569,6 +562,7 @@ mod tests {
|
|||||||
let schema = type_registry
|
let schema = type_registry
|
||||||
.export_type_json_schema::<EnumComponent>(&metadata)
|
.export_type_json_schema::<EnumComponent>(&metadata)
|
||||||
.expect("Failed to export schema");
|
.expect("Failed to export schema");
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
!metadata.has_type_data::<ReflectComponent>(&schema.reflect_type_data),
|
!metadata.has_type_data::<ReflectComponent>(&schema.reflect_type_data),
|
||||||
"Should not be a component"
|
"Should not be a component"
|
||||||
@ -597,11 +591,11 @@ mod tests {
|
|||||||
impl bevy_reflect::FromType<SomeType> for ReflectJsonSchema {
|
impl bevy_reflect::FromType<SomeType> for ReflectJsonSchema {
|
||||||
fn from_type() -> Self {
|
fn from_type() -> Self {
|
||||||
JsonSchemaBevyType {
|
JsonSchemaBevyType {
|
||||||
ref_type: Some(
|
ref_type: Some(TypeReferencePath::new_ref(
|
||||||
"https://raw.githubusercontent.com/open-rpc/meta-schema/master/schema.json"
|
ReferenceLocation::Url,
|
||||||
.into(),
|
"raw.githubusercontent.com/open-rpc/meta-schema/master/schema.json",
|
||||||
),
|
)),
|
||||||
description: Some("Custom type for testing purposes.".to_string()),
|
description: Some("Custom type for testing purposes.".into()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
@ -625,7 +619,7 @@ mod tests {
|
|||||||
"Should not be a component"
|
"Should not be a component"
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
schema.ref_type.is_some_and(|t| !t.is_empty()),
|
schema.ref_type.is_some_and(|t| !t.to_string().is_empty()),
|
||||||
"Should have a reference type"
|
"Should have a reference type"
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
|
|||||||
@ -7,7 +7,7 @@ use bevy_ecs::{
|
|||||||
};
|
};
|
||||||
use bevy_platform::collections::HashMap;
|
use bevy_platform::collections::HashMap;
|
||||||
use bevy_reflect::{
|
use bevy_reflect::{
|
||||||
prelude::ReflectDefault, Reflect, ReflectDeserialize, ReflectSerialize, TypeData,
|
prelude::ReflectDefault, FromType, Reflect, ReflectDeserialize, ReflectSerialize, TypeData,
|
||||||
TypeRegistration,
|
TypeRegistration,
|
||||||
};
|
};
|
||||||
use core::any::TypeId;
|
use core::any::TypeId;
|
||||||
@ -27,6 +27,16 @@ pub struct SchemaTypesMetadata {
|
|||||||
pub type_data_map: HashMap<TypeId, Cow<'static, str>>,
|
pub type_data_map: HashMap<TypeId, Cow<'static, str>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reflect-compatible custom JSON Schema for this type
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ReflectJsonSchemaForceAsArray;
|
||||||
|
|
||||||
|
impl<T: Reflect> FromType<T> for ReflectJsonSchemaForceAsArray {
|
||||||
|
fn from_type() -> Self {
|
||||||
|
ReflectJsonSchemaForceAsArray
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Reflect-compatible custom JSON Schema for this type
|
/// Reflect-compatible custom JSON Schema for this type
|
||||||
#[derive(Clone, Deref)]
|
#[derive(Clone, Deref)]
|
||||||
pub struct ReflectJsonSchema(pub JsonSchemaBevyType);
|
pub struct ReflectJsonSchema(pub JsonSchemaBevyType);
|
||||||
|
|||||||
@ -5,7 +5,13 @@ use bevy_reflect::{FromType, Reflect};
|
|||||||
use bevy_utils::default;
|
use bevy_utils::default;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{schemas::ReflectJsonSchema, RemoteMethods};
|
use crate::{
|
||||||
|
schemas::{
|
||||||
|
reflect_info::{ReferenceLocation, TypeReferencePath},
|
||||||
|
ReflectJsonSchema,
|
||||||
|
},
|
||||||
|
RemoteMethods,
|
||||||
|
};
|
||||||
|
|
||||||
use super::json_schema::JsonSchemaBevyType;
|
use super::json_schema::JsonSchemaBevyType;
|
||||||
|
|
||||||
@ -26,12 +32,13 @@ pub struct OpenRpcDocument {
|
|||||||
impl FromType<OpenRpcDocument> for ReflectJsonSchema {
|
impl FromType<OpenRpcDocument> for ReflectJsonSchema {
|
||||||
fn from_type() -> Self {
|
fn from_type() -> Self {
|
||||||
JsonSchemaBevyType {
|
JsonSchemaBevyType {
|
||||||
ref_type: Some(
|
ref_type: Some(TypeReferencePath::new_ref(
|
||||||
"https://raw.githubusercontent.com/open-rpc/meta-schema/master/schema.json".into(),
|
ReferenceLocation::Url,
|
||||||
),
|
"raw.githubusercontent.com/open-rpc/meta-schema/master/schema.json",
|
||||||
|
)),
|
||||||
description: Some(
|
description: Some(
|
||||||
"Represents an `OpenRPC` document as defined by the `OpenRPC` specification."
|
"Represents an `OpenRPC` document as defined by the `OpenRPC` specification."
|
||||||
.to_string(),
|
.into(),
|
||||||
),
|
),
|
||||||
..default()
|
..default()
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user