Add no_std support to bevy_reflect (#16256)

# Objective

- Contributes to #15460

## Solution

- Added `std` feature (enabled by default)

## Testing

- CI
- `cargo check -p bevy_reflect --no-default-features --target
"x86_64-unknown-none"`
- UEFI demo application runs with this branch of `bevy_reflect`,
allowing `derive(Reflect)`

## Notes

- The [`spin`](https://crates.io/crates/spin) crate has been included to
provide `RwLock` and `Once` (as an alternative to `OnceLock`) when the
`std` feature is not enabled. Another alternative may be more desirable,
please provide feedback if you have a strong opinion here!
- Certain items (`Box`, `String`, `ToString`) provided by `alloc` have
been added to `__macro_exports` as a way to avoid `alloc` vs `std`
namespacing. I'm personally quite annoyed that we can't rely on `alloc`
as a crate name in `std` environments within macros. I'd love an
alternative to my approach here, but I suspect it's the least-bad
option.
- I would've liked to have an `alloc` feature (for allocation-free
`bevy_reflect`), unfortunately, `erased_serde` unconditionally requires
access to `Box`. Maybe one day we could design around this, but for now
it just means `bevy_reflect` requires `alloc`.

---------

Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
This commit is contained in:
Zachary Harrold 2024-12-06 08:15:21 +11:00 committed by GitHub
parent 09b0b5df91
commit bf765e61b5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
68 changed files with 364 additions and 143 deletions

View file

@ -10,14 +10,24 @@ keywords = ["bevy"]
rust-version = "1.81.0"
[features]
default = ["smallvec", "debug", "alloc"]
default = ["std", "smallvec", "debug"]
std = [
"bevy_utils/std",
"erased-serde/std",
"downcast-rs/std",
"serde/std",
"spin/std",
"glam?/std",
"smol_str?/std",
"uuid?/std",
]
# When enabled, provides Bevy-related reflection implementations
bevy = ["smallvec", "smol_str"]
glam = ["dep:glam"]
petgraph = ["dep:petgraph"]
petgraph = ["dep:petgraph", "std"]
smallvec = ["dep:smallvec"]
uuid = ["dep:uuid"]
wgpu-types = ["dep:wgpu-types"]
wgpu-types = ["dep:wgpu-types", "std"]
# Enables features useful for debugging reflection
debug = ["debug_stack"]
# When enabled, keeps track of the current serialization/deserialization context for better error messages
@ -26,31 +36,45 @@ debug_stack = []
documentation = ["bevy_reflect_derive/documentation"]
# Enables function reflection
functions = ["bevy_reflect_derive/functions"]
alloc = []
[dependencies]
# bevy
bevy_reflect_derive = { path = "derive", version = "0.15.0-dev" }
bevy_utils = { path = "../bevy_utils", version = "0.15.0-dev" }
bevy_utils = { path = "../bevy_utils", version = "0.15.0-dev", default-features = false, features = [
"alloc",
] }
bevy_ptr = { path = "../bevy_ptr", version = "0.15.0-dev" }
# other
erased-serde = "0.4"
disqualified = "1.0"
downcast-rs = "1.2"
erased-serde = { version = "0.4", default-features = false, features = [
"alloc",
] }
disqualified = { version = "1.0", default-features = false }
downcast-rs = { version = "1.2", default-features = false }
derive_more = { version = "1", default-features = false, features = [
"error",
"from",
"display",
] }
serde = "1"
smallvec = { version = "1.11", optional = true }
serde = { version = "1", default-features = false, features = ["alloc"] }
spin = { version = "0.9.8", default-features = false, features = [
"once",
"rwlock",
] }
assert_type_match = "0.1.1"
glam = { version = "0.29", features = ["serde"], optional = true }
smallvec = { version = "1.11", default-features = false, optional = true }
glam = { version = "0.29", default-features = false, features = [
"serde",
], optional = true }
petgraph = { version = "0.6", features = ["serde-1"], optional = true }
smol_str = { version = "0.2.0", features = ["serde"], optional = true }
uuid = { version = "1.0", optional = true, features = ["v4", "serde"] }
smol_str = { version = "0.2.0", default-features = false, features = [
"serde",
], optional = true }
uuid = { version = "1.0", default-features = false, optional = true, features = [
"v4",
"serde",
] }
variadics_please = "1.0"
wgpu-types = { version = "23", features = ["serde"], optional = true }

View file

@ -280,9 +280,11 @@ impl<'a> ReflectDerive<'a> {
match &input.data {
Data::Struct(data) => {
let fields = Self::collect_struct_fields(&data.fields)?;
let serialization_data =
SerializationDataDef::new(&fields, &meta.bevy_reflect_path)?;
let reflect_struct = ReflectStruct {
meta,
serialization_data: SerializationDataDef::new(&fields)?,
serialization_data,
fields,
};
@ -1034,6 +1036,7 @@ impl<'a> ReflectTypePath<'a> {
fn reduce_generics(
generics: &Generics,
mut ty_generic_fn: impl FnMut(&TypeParam) -> StringExpr,
bevy_reflect_path: &Path,
) -> StringExpr {
let mut params = generics.params.iter().filter_map(|param| match param {
GenericParam::Type(type_param) => Some(ty_generic_fn(type_param)),
@ -1042,7 +1045,7 @@ impl<'a> ReflectTypePath<'a> {
let ty = &const_param.ty;
Some(StringExpr::Owned(quote! {
<#ty as ::std::string::ToString>::to_string(&#ident)
<#ty as #bevy_reflect_path::__macro_exports::alloc_utils::ToString>::to_string(&#ident)
}))
}
GenericParam::Lifetime(_) => None,
@ -1074,6 +1077,7 @@ impl<'a> ReflectTypePath<'a> {
<#ident as #bevy_reflect_path::TypePath>::type_path()
})
},
bevy_reflect_path,
);
StringExpr::from_iter([
@ -1111,6 +1115,7 @@ impl<'a> ReflectTypePath<'a> {
<#ident as #bevy_reflect_path::TypePath>::short_type_path()
})
},
bevy_reflect_path,
);
StringExpr::from_iter([

View file

@ -32,7 +32,7 @@ pub(crate) fn generate_generics(meta: &ReflectMeta) -> Option<TokenStream> {
Some(quote! {
#bevy_reflect_path::GenericInfo::Type(
#bevy_reflect_path::TypeParamInfo::new::<#ident>(
::std::borrow::Cow::Borrowed(#name),
#bevy_reflect_path::__macro_exports::alloc_utils::Cow::Borrowed(#name),
)
#with_default
)
@ -53,7 +53,7 @@ pub(crate) fn generate_generics(meta: &ReflectMeta) -> Option<TokenStream> {
)]
#bevy_reflect_path::GenericInfo::Const(
#bevy_reflect_path::ConstParamInfo::new::<#ty>(
::std::borrow::Cow::Borrowed(#name),
#bevy_reflect_path::__macro_exports::alloc_utils::Cow::Borrowed(#name),
)
#with_default
)

View file

@ -1,4 +1,4 @@
use bevy_macro_utils::fq_std::{FQAny, FQBox, FQOption, FQResult};
use bevy_macro_utils::fq_std::{FQAny, FQOption, FQResult};
use quote::quote;
@ -17,8 +17,8 @@ pub fn impl_full_reflect(
let any_impls = if meta.is_remote_wrapper() {
quote! {
#[inline]
fn into_any(self: #FQBox<Self>) -> #FQBox<dyn #FQAny> {
#FQBox::new(self.0)
fn into_any(self: #bevy_reflect_path::__macro_exports::alloc_utils::Box<Self>) -> #bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #FQAny> {
#bevy_reflect_path::__macro_exports::alloc_utils::Box::new(self.0)
}
#[inline]
@ -34,7 +34,7 @@ pub fn impl_full_reflect(
} else {
quote! {
#[inline]
fn into_any(self: #FQBox<Self>) -> #FQBox<dyn #FQAny> {
fn into_any(self: #bevy_reflect_path::__macro_exports::alloc_utils::Box<Self>) -> #bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #FQAny> {
self
}
@ -55,7 +55,7 @@ pub fn impl_full_reflect(
#any_impls
#[inline]
fn into_reflect(self: #FQBox<Self>) -> #FQBox<dyn #bevy_reflect_path::Reflect> {
fn into_reflect(self: #bevy_reflect_path::__macro_exports::alloc_utils::Box<Self>) -> #bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #bevy_reflect_path::Reflect> {
self
}
@ -72,8 +72,8 @@ pub fn impl_full_reflect(
#[inline]
fn set(
&mut self,
value: #FQBox<dyn #bevy_reflect_path::Reflect>
) -> #FQResult<(), #FQBox<dyn #bevy_reflect_path::Reflect>> {
value: #bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #bevy_reflect_path::Reflect>
) -> #FQResult<(), #bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #bevy_reflect_path::Reflect>> {
*self = <dyn #bevy_reflect_path::Reflect>::take(value)?;
#FQResult::Ok(())
}
@ -119,8 +119,8 @@ pub fn common_partial_reflect_methods(
quote! {
#[inline]
fn try_into_reflect(
self: #FQBox<Self>
) -> #FQResult<#FQBox<dyn #bevy_reflect_path::Reflect>, #FQBox<dyn #bevy_reflect_path::PartialReflect>> {
self: #bevy_reflect_path::__macro_exports::alloc_utils::Box<Self>
) -> #FQResult<#bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #bevy_reflect_path::Reflect>, #bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #bevy_reflect_path::PartialReflect>> {
#FQResult::Ok(self)
}
@ -135,7 +135,7 @@ pub fn common_partial_reflect_methods(
}
#[inline]
fn into_partial_reflect(self: #FQBox<Self>) -> #FQBox<dyn #bevy_reflect_path::PartialReflect> {
fn into_partial_reflect(self: #bevy_reflect_path::__macro_exports::alloc_utils::Box<Self>) -> #bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #bevy_reflect_path::PartialReflect> {
self
}

View file

@ -3,7 +3,7 @@ use crate::{
enum_utility::{EnumVariantOutputData, TryApplyVariantBuilder, VariantBuilder},
impls::{common_partial_reflect_methods, impl_full_reflect, impl_type_path, impl_typed},
};
use bevy_macro_utils::fq_std::{FQBox, FQOption, FQResult};
use bevy_macro_utils::fq_std::{FQOption, FQResult};
use proc_macro2::{Ident, Span};
use quote::quote;
use syn::{Fields, Path};
@ -186,8 +186,8 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> proc_macro2::TokenStream
}
#[inline]
fn clone_value(&self) -> #FQBox<dyn #bevy_reflect_path::PartialReflect> {
#FQBox::new(#bevy_reflect_path::Enum::clone_dynamic(self))
fn clone_value(&self) -> #bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #bevy_reflect_path::PartialReflect> {
#bevy_reflect_path::__macro_exports::alloc_utils::Box::new(#bevy_reflect_path::Enum::clone_dynamic(self))
}
#[inline]
@ -256,7 +256,7 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> proc_macro2::TokenStream
#bevy_reflect_path::ReflectMut::Enum(self)
}
fn reflect_owned(self: #FQBox<Self>) -> #bevy_reflect_path::ReflectOwned {
fn reflect_owned(self: #bevy_reflect_path::__macro_exports::alloc_utils::Box<Self>) -> #bevy_reflect_path::ReflectOwned {
#bevy_reflect_path::ReflectOwned::Enum(self)
}

View file

@ -3,7 +3,7 @@ use crate::{
where_clause_options::WhereClauseOptions,
ReflectMeta,
};
use bevy_macro_utils::fq_std::{FQBox, FQClone, FQOption, FQResult};
use bevy_macro_utils::fq_std::{FQClone, FQOption, FQResult};
use quote::quote;
/// Implements `GetTypeRegistration` and `Reflect` for the given type data.
@ -77,8 +77,8 @@ pub(crate) fn impl_opaque(meta: &ReflectMeta) -> proc_macro2::TokenStream {
}
#[inline]
fn clone_value(&self) -> #FQBox<dyn #bevy_reflect_path::PartialReflect> {
#FQBox::new(#FQClone::clone(self))
fn clone_value(&self) -> #bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #bevy_reflect_path::PartialReflect> {
#bevy_reflect_path::__macro_exports::alloc_utils::Box::new(#FQClone::clone(self))
}
#[inline]
@ -112,7 +112,7 @@ pub(crate) fn impl_opaque(meta: &ReflectMeta) -> proc_macro2::TokenStream {
}
#[inline]
fn reflect_owned(self: #FQBox<Self>) -> #bevy_reflect_path::ReflectOwned {
fn reflect_owned(self: #bevy_reflect_path::__macro_exports::alloc_utils::Box<Self>) -> #bevy_reflect_path::ReflectOwned {
#bevy_reflect_path::ReflectOwned::Opaque(self)
}

View file

@ -3,7 +3,7 @@ use crate::{
struct_utility::FieldAccessors,
ReflectStruct,
};
use bevy_macro_utils::fq_std::{FQBox, FQDefault, FQOption, FQResult};
use bevy_macro_utils::fq_std::{FQDefault, FQOption, FQResult};
use quote::{quote, ToTokens};
/// Implements `Struct`, `GetTypeRegistration`, and `Reflect` for the given derive data.
@ -134,8 +134,8 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> proc_macro2::TokenS
}
#[inline]
fn clone_value(&self) -> #FQBox<dyn #bevy_reflect_path::PartialReflect> {
#FQBox::new(#bevy_reflect_path::Struct::clone_dynamic(self))
fn clone_value(&self) -> #bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #bevy_reflect_path::PartialReflect> {
#bevy_reflect_path::__macro_exports::alloc_utils::Box::new(#bevy_reflect_path::Struct::clone_dynamic(self))
}
#[inline]
@ -174,7 +174,7 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> proc_macro2::TokenS
#bevy_reflect_path::ReflectMut::Struct(self)
}
#[inline]
fn reflect_owned(self: #FQBox<Self>) -> #bevy_reflect_path::ReflectOwned {
fn reflect_owned(self: #bevy_reflect_path::__macro_exports::alloc_utils::Box<Self>) -> #bevy_reflect_path::ReflectOwned {
#bevy_reflect_path::ReflectOwned::Struct(self)
}

View file

@ -3,7 +3,7 @@ use crate::{
struct_utility::FieldAccessors,
ReflectStruct,
};
use bevy_macro_utils::fq_std::{FQBox, FQDefault, FQOption, FQResult};
use bevy_macro_utils::fq_std::{FQDefault, FQOption, FQResult};
use quote::{quote, ToTokens};
/// Implements `TupleStruct`, `GetTypeRegistration`, and `Reflect` for the given derive data.
@ -100,8 +100,8 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> proc_macro2::
#FQOption::Some(<Self as #bevy_reflect_path::Typed>::type_info())
}
#[inline]
fn clone_value(&self) -> #FQBox<dyn #bevy_reflect_path::PartialReflect> {
#FQBox::new(#bevy_reflect_path::TupleStruct::clone_dynamic(self))
fn clone_value(&self) -> #bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #bevy_reflect_path::PartialReflect> {
#bevy_reflect_path::__macro_exports::alloc_utils::Box::new(#bevy_reflect_path::TupleStruct::clone_dynamic(self))
}
#[inline]
@ -139,7 +139,7 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> proc_macro2::
#bevy_reflect_path::ReflectMut::TupleStruct(self)
}
#[inline]
fn reflect_owned(self: #FQBox<Self>) -> #bevy_reflect_path::ReflectOwned {
fn reflect_owned(self: #bevy_reflect_path::__macro_exports::alloc_utils::Box<Self>) -> #bevy_reflect_path::ReflectOwned {
#bevy_reflect_path::ReflectOwned::TupleStruct(self)
}

View file

@ -106,27 +106,34 @@ pub(crate) fn impl_type_path(meta: &ReflectMeta) -> TokenStream {
quote! {
#primitive_assert
impl #impl_generics #bevy_reflect_path::TypePath for #type_path #ty_generics #where_reflect_clause {
fn type_path() -> &'static str {
#long_type_path
}
// To ensure alloc is available, but also prevent its name from clashing, we place the implementation inside an anonymous constant
const _: () = {
extern crate alloc;
fn short_type_path() -> &'static str {
#short_type_path
}
use alloc::string::ToString;
fn type_ident() -> Option<&'static str> {
#type_ident
}
impl #impl_generics #bevy_reflect_path::TypePath for #type_path #ty_generics #where_reflect_clause {
fn type_path() -> &'static str {
#long_type_path
}
fn crate_name() -> Option<&'static str> {
#crate_name
}
fn short_type_path() -> &'static str {
#short_type_path
}
fn module_path() -> Option<&'static str> {
#module_path
fn type_ident() -> Option<&'static str> {
#type_ident
}
fn crate_name() -> Option<&'static str> {
#crate_name
}
fn module_path() -> Option<&'static str> {
#module_path
}
}
}
};
}
}

View file

@ -2,7 +2,7 @@ use crate::{
derive_data::StructField,
field_attributes::{DefaultBehavior, ReflectIgnoreBehavior},
};
use bevy_macro_utils::fq_std::{FQBox, FQDefault};
use bevy_macro_utils::fq_std::FQDefault;
use quote::quote;
use std::collections::HashMap;
use syn::{spanned::Spanned, Path};
@ -20,7 +20,10 @@ impl SerializationDataDef {
///
/// Returns `Ok(Some(data))` if there are any fields needing to be skipped during serialization.
/// Otherwise, returns `Ok(None)`.
pub fn new(fields: &[StructField<'_>]) -> Result<Option<Self>, syn::Error> {
pub fn new(
fields: &[StructField<'_>],
bevy_reflect_path: &Path,
) -> Result<Option<Self>, syn::Error> {
let mut skipped = HashMap::default();
for field in fields {
@ -33,7 +36,7 @@ impl SerializationDataDef {
"internal error: field is missing a reflection index",
)
})?,
SkippedFieldDef::new(field)?,
SkippedFieldDef::new(field, bevy_reflect_path)?,
);
}
_ => continue,
@ -75,15 +78,15 @@ pub(crate) struct SkippedFieldDef {
}
impl SkippedFieldDef {
pub fn new(field: &StructField<'_>) -> Result<Self, syn::Error> {
pub fn new(field: &StructField<'_>, bevy_reflect_path: &Path) -> Result<Self, syn::Error> {
let ty = &field.data.ty;
let default_fn = match &field.attrs.default {
DefaultBehavior::Func(func) => quote! {
|| { #FQBox::new(#func()) }
|| { #bevy_reflect_path::__macro_exports::alloc_utils::Box::new(#func()) }
},
_ => quote! {
|| { #FQBox::new(<#ty as #FQDefault>::default()) }
|| { #bevy_reflect_path::__macro_exports::alloc_utils::Box::new(<#ty as #FQDefault>::default()) }
},
};

View file

@ -44,9 +44,11 @@ impl StringExpr {
///
/// [already owned]: StringExpr::Owned
pub fn into_owned(self) -> TokenStream {
let bevy_reflect_path = crate::meta::get_bevy_reflect_path();
match self {
Self::Const(tokens) | Self::Borrowed(tokens) => quote! {
::std::string::ToString::to_string(#tokens)
#bevy_reflect_path::__macro_exports::alloc_utils::ToString::to_string(#tokens)
},
Self::Owned(owned) => owned,
}

View file

@ -1,5 +1,5 @@
use bevy_macro_utils::{
fq_std::{FQBox, FQClone, FQOption, FQResult},
fq_std::{FQClone, FQOption, FQResult},
BevyManifest,
};
use proc_macro::TokenStream;
@ -57,7 +57,7 @@ pub(crate) fn reflect_trait(_args: &TokenStream, input: TokenStream) -> TokenStr
#trait_vis struct #reflect_trait_ident {
get_func: fn(&dyn #bevy_reflect_path::Reflect) -> #FQOption<&dyn #trait_ident>,
get_mut_func: fn(&mut dyn #bevy_reflect_path::Reflect) -> #FQOption<&mut dyn #trait_ident>,
get_boxed_func: fn(#FQBox<dyn #bevy_reflect_path::Reflect>) -> #FQResult<#FQBox<dyn #trait_ident>, #FQBox<dyn #bevy_reflect_path::Reflect>>,
get_boxed_func: fn(#bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #bevy_reflect_path::Reflect>) -> #FQResult<#bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #trait_ident>, #bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #bevy_reflect_path::Reflect>>,
}
impl #reflect_trait_ident {
@ -72,7 +72,7 @@ pub(crate) fn reflect_trait(_args: &TokenStream, input: TokenStream) -> TokenStr
}
#[doc = #get_box_doc]
pub fn get_boxed(&self, reflect_value: #FQBox<dyn #bevy_reflect_path::Reflect>) -> #FQResult<#FQBox<dyn #trait_ident>, #FQBox<dyn #bevy_reflect_path::Reflect>> {
pub fn get_boxed(&self, reflect_value: #bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #bevy_reflect_path::Reflect>) -> #FQResult<#bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #trait_ident>, #bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #bevy_reflect_path::Reflect>> {
(self.get_boxed_func)(reflect_value)
}
}
@ -87,7 +87,7 @@ pub(crate) fn reflect_trait(_args: &TokenStream, input: TokenStream) -> TokenStr
<dyn #bevy_reflect_path::Reflect>::downcast_mut::<T>(reflect_value).map(|value| value as &mut dyn #trait_ident)
},
get_boxed_func: |reflect_value| {
<dyn #bevy_reflect_path::Reflect>::downcast::<T>(reflect_value).map(|value| value as #FQBox<dyn #trait_ident>)
<dyn #bevy_reflect_path::Reflect>::downcast::<T>(reflect_value).map(|value| value as #bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #trait_ident>)
}
}
}

View file

@ -4,6 +4,7 @@ use crate::{
Generics, MaybeTyped, PartialReflect, Reflect, ReflectKind, ReflectMut, ReflectOwned,
ReflectRef, Type, TypeInfo, TypePath,
};
use alloc::{boxed::Box, vec::Vec};
use bevy_reflect_derive::impl_type_path;
use core::{
any::Any,

View file

@ -1,4 +1,5 @@
use crate::Reflect;
use alloc::boxed::Box;
use bevy_utils::TypeIdMap;
use core::{
any::TypeId,
@ -16,7 +17,7 @@ use core::{
///
/// ```
/// # use bevy_reflect::{Reflect, Typed, TypeInfo};
/// use std::ops::RangeInclusive;
/// use core::ops::RangeInclusive;
/// #[derive(Reflect)]
/// struct Slider {
/// #[reflect(@RangeInclusive::<f32>::new(0.0, 1.0))]
@ -152,7 +153,7 @@ macro_rules! impl_custom_attribute_methods {
}
#[allow(rustdoc::redundant_explicit_links)]
/// Gets a custom attribute by its [`TypeId`](std::any::TypeId).
/// Gets a custom attribute by its [`TypeId`](core::any::TypeId).
///
/// This is the dynamic equivalent of [`get_attribute`](Self::get_attribute).
pub fn get_attribute_by_id(&$self, id: ::core::any::TypeId) -> Option<&dyn $crate::Reflect> {

View file

@ -6,6 +6,7 @@ use crate::{
Struct, Tuple, TypeInfo, VariantFieldIter, VariantType,
};
use alloc::{boxed::Box, string::String};
use core::fmt::Formatter;
use derive_more::derive::From;

View file

@ -4,7 +4,7 @@ use crate::{
type_info::impl_type_methods,
DynamicEnum, Generics, PartialReflect, Type, TypePath, VariantInfo, VariantType,
};
use alloc::sync::Arc;
use alloc::{boxed::Box, format, string::String, sync::Arc};
use bevy_utils::HashMap;
use core::slice::Iter;

View file

@ -2,10 +2,10 @@ use crate::{
attributes::{impl_custom_attribute_methods, CustomAttributes},
NamedField, UnnamedField,
};
use alloc::boxed::Box;
use alloc::sync::Arc;
use bevy_utils::HashMap;
use core::slice::Iter;
use alloc::sync::Arc;
use derive_more::derive::{Display, Error};
/// Describes the form of an enum variant.

View file

@ -1,4 +1,5 @@
use crate::{FromType, PartialReflect, Reflect};
use alloc::boxed::Box;
/// A trait that enables types to be dynamically constructed from reflected data.
///

View file

@ -2,8 +2,12 @@ use crate::{
func::args::{ArgError, FromArg, Ownership},
PartialReflect, Reflect, TypePath,
};
use alloc::boxed::Box;
use core::ops::Deref;
#[cfg(not(feature = "std"))]
use alloc::{format, vec};
/// Represents an argument that can be passed to a [`DynamicFunction`] or [`DynamicFunctionMut`].
///
/// [`DynamicFunction`]: crate::func::DynamicFunction

View file

@ -4,6 +4,9 @@ use derive_more::derive::{Display, Error};
use crate::func::args::Ownership;
#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, format, vec};
/// An error that occurs when converting an [argument].
///
/// [argument]: crate::func::args::Arg

View file

@ -1,5 +1,8 @@
use crate::func::args::{Arg, ArgError};
#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, format, vec};
/// A trait for types that can be created from an [`Arg`].
///
/// This trait exists so that types can be automatically converted into an [`Arg`]

View file

@ -6,6 +6,9 @@ use crate::{
Type, TypePath,
};
#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, format, vec};
/// Type information for an [`Arg`] used in a [`DynamicFunction`] or [`DynamicFunctionMut`].
///
/// [`Arg`]: crate::func::args::Arg

View file

@ -5,7 +5,10 @@ use crate::{
},
PartialReflect, Reflect, TypePath,
};
use alloc::collections::VecDeque;
use alloc::{boxed::Box, collections::VecDeque};
#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, format, vec};
/// A list of arguments that can be passed to a [`DynamicFunction`] or [`DynamicFunctionMut`].
///

View file

@ -1,5 +1,8 @@
use core::fmt::{Display, Formatter};
#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, format, vec};
/// A trait for getting the ownership of a type.
///
/// This trait exists so that [`TypedFunction`] can automatically generate

View file

@ -9,10 +9,13 @@ use crate::{
ApplyError, MaybeTyped, PartialReflect, Reflect, ReflectKind, ReflectMut, ReflectOwned,
ReflectRef, TypeInfo, TypePath,
};
use alloc::{borrow::Cow, sync::Arc};
use alloc::{borrow::Cow, boxed::Box, sync::Arc};
use bevy_reflect_derive::impl_type_path;
use core::fmt::{Debug, Formatter};
#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, format, vec};
/// A dynamic representation of a function.
///
/// This type can be used to represent any callable that satisfies [`Fn`]
@ -79,7 +82,7 @@ impl<'env> DynamicFunction<'env> {
/// Set the name of the function.
///
/// For [`DynamicFunctions`] created using [`IntoFunction`],
/// the default name will always be the full path to the function as returned by [`std::any::type_name`],
/// the default name will always be the full path to the function as returned by [`core::any::type_name`],
/// unless the function is a closure, anonymous function, or function pointer,
/// in which case the name will be `None`.
///
@ -134,7 +137,7 @@ impl<'env> DynamicFunction<'env> {
/// The [name] of the function.
///
/// For [`DynamicFunctions`] created using [`IntoFunction`],
/// the default name will always be the full path to the function as returned by [`std::any::type_name`],
/// the default name will always be the full path to the function as returned by [`core::any::type_name`],
/// unless the function is a closure, anonymous function, or function pointer,
/// in which case the name will be `None`.
///

View file

@ -1,6 +1,9 @@
use alloc::borrow::Cow;
use alloc::{borrow::Cow, boxed::Box};
use core::fmt::{Debug, Formatter};
#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, format, vec};
use crate::func::{
args::ArgList, info::FunctionInfo, DynamicFunction, FunctionError, FunctionResult,
IntoFunctionMut,
@ -90,7 +93,7 @@ impl<'env> DynamicFunctionMut<'env> {
/// Set the name of the function.
///
/// For [`DynamicFunctionMuts`] created using [`IntoFunctionMut`],
/// the default name will always be the full path to the function as returned by [`std::any::type_name`],
/// the default name will always be the full path to the function as returned by [`core::any::type_name`],
/// unless the function is a closure, anonymous function, or function pointer,
/// in which case the name will be `None`.
///
@ -195,7 +198,7 @@ impl<'env> DynamicFunctionMut<'env> {
/// The [name] of the function.
///
/// For [`DynamicFunctionMuts`] created using [`IntoFunctionMut`],
/// the default name will always be the full path to the function as returned by [`std::any::type_name`],
/// the default name will always be the full path to the function as returned by [`core::any::type_name`],
/// unless the function is a closure, anonymous function, or function pointer,
/// in which case the name will be `None`.
///

View file

@ -2,6 +2,9 @@ use crate::func::{args::ArgError, Return};
use alloc::borrow::Cow;
use derive_more::derive::{Display, Error, From};
#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, format, vec};
/// An error that occurs when calling a [`DynamicFunction`] or [`DynamicFunctionMut`].
///
/// [`DynamicFunction`]: crate::func::DynamicFunction

View file

@ -5,6 +5,9 @@ use crate::{
use alloc::borrow::Cow;
use core::fmt::Debug;
#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, format, vec};
/// A trait used to power [function-like] operations via [reflection].
///
/// This trait allows types to be called like regular functions
@ -36,7 +39,7 @@ pub trait Function: PartialReflect + Debug {
/// The name of the function, if any.
///
/// For [`DynamicFunctions`] created using [`IntoFunction`],
/// the default name will always be the full path to the function as returned by [`std::any::type_name`],
/// the default name will always be the full path to the function as returned by [`core::any::type_name`],
/// unless the function is a closure, anonymous function, or function pointer,
/// in which case the name will be `None`.
///

View file

@ -1,4 +1,7 @@
use alloc::borrow::Cow;
use alloc::{borrow::Cow, vec};
#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, format, vec};
use variadics_please::all_tuples;
@ -109,7 +112,7 @@ impl FunctionInfo {
/// The name of the function.
///
/// For [`DynamicFunctions`] created using [`IntoFunction`] or [`DynamicFunctionMuts`] created using [`IntoFunctionMut`],
/// the default name will always be the full path to the function as returned by [`std::any::type_name`],
/// the default name will always be the full path to the function as returned by [`core::any::type_name`],
/// unless the function is a closure, anonymous function, or function pointer,
/// in which case the name will be `None`.
///
@ -351,7 +354,7 @@ all_tuples!(impl_typed_function, 0, 15, Arg, arg);
/// | Anonymous function | `foo::bar::{{closure}}` | `None` |
/// | Function pointer | `fn() -> String` | `None` |
///
/// [`type_name`]: std::any::type_name
/// [`type_name`]: core::any::type_name
fn create_info<F>() -> FunctionInfo {
let name = core::any::type_name::<F>();

View file

@ -1,5 +1,8 @@
use crate::func::{DynamicFunction, ReflectFn, TypedFunction};
#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, format, vec};
/// A trait for types that can be converted into a [`DynamicFunction`].
///
/// This trait is automatically implemented for any type that implements

View file

@ -1,5 +1,8 @@
use crate::func::{DynamicFunctionMut, ReflectFnMut, TypedFunction};
#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, format, vec};
/// A trait for types that can be converted into a [`DynamicFunctionMut`].
///
/// This trait is automatically implemented for any type that implements

View file

@ -1,3 +1,6 @@
#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, format, vec};
/// Helper macro to implement the necessary traits for function reflection.
///
/// This macro calls the following macros:

View file

@ -1,5 +1,8 @@
use variadics_please::all_tuples;
#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, format, vec};
use crate::{
func::{
args::FromArg, macros::count_tokens, ArgList, FunctionError, FunctionResult, IntoReturn,

View file

@ -1,5 +1,8 @@
use variadics_please::all_tuples;
#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, format, vec};
use crate::{
func::{
args::FromArg, macros::count_tokens, ArgList, FunctionError, FunctionResult, IntoReturn,

View file

@ -2,6 +2,9 @@ use alloc::{borrow::Cow, sync::Arc};
use core::fmt::Debug;
use std::sync::{PoisonError, RwLock, RwLockReadGuard, RwLockWriteGuard};
#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, format, vec};
use bevy_utils::HashMap;
use crate::func::{
@ -167,13 +170,13 @@ impl FunctionRegistry {
/// a + b
/// })?
/// // Registering an existing function with its type name
/// .register_with_name(std::any::type_name_of_val(&mul), mul)?
/// .register_with_name(core::any::type_name_of_val(&mul), mul)?
/// // Registering an existing function with a custom name
/// .register_with_name("my_crate::mul", mul)?;
///
/// // Be careful not to register anonymous functions with their type name.
/// // This code works but registers the function with a non-unique name like `foo::bar::{{closure}}`
/// registry.register_with_name(std::any::type_name_of_val(&div), div)?;
/// registry.register_with_name(core::any::type_name_of_val(&div), div)?;
/// # Ok(())
/// # }
/// ```
@ -195,7 +198,7 @@ impl FunctionRegistry {
/// [name]: DynamicFunction::name
/// [`register`]: Self::register
/// [`overwrite_registration_with_name`]: Self::overwrite_registration_with_name
/// [type name]: std::any::type_name
/// [type name]: core::any::type_name
pub fn register_with_name<F, Marker>(
&mut self,
name: impl Into<Cow<'static, str>>,

View file

@ -1,4 +1,8 @@
use crate::PartialReflect;
use alloc::boxed::Box;
#[cfg(not(feature = "std"))]
use alloc::{format, vec};
/// The return type of a [`DynamicFunction`] or [`DynamicFunctionMut`].
///

View file

@ -1,7 +1,6 @@
use crate::type_info::impl_type_methods;
use crate::{Reflect, Type, TypePath};
use alloc::borrow::Cow;
use alloc::sync::Arc;
use alloc::{borrow::Cow, boxed::Box, sync::Arc};
use core::ops::Deref;
use derive_more::derive::From;

View file

@ -4,6 +4,9 @@ use assert_type_match::assert_type_match;
use bevy_reflect_derive::{impl_reflect, impl_reflect_opaque};
use glam::*;
#[cfg(not(feature = "std"))]
use alloc::format;
/// Reflects the given foreign type as an enum and asserts that the variants/fields match up.
macro_rules! reflect_enum {
($(#[$meta:meta])* enum $ident:ident { $($ty:tt)* } ) => {

View file

@ -1,7 +1,10 @@
use alloc::boxed::Box;
use bevy_reflect_derive::impl_type_path;
use core::any::Any;
use smallvec::{Array as SmallArray, SmallVec};
use core::any::Any;
#[cfg(not(feature = "std"))]
use alloc::{format, vec};
use crate::{
self as bevy_reflect, utility::GenericTypeInfoCell, ApplyError, FromReflect, FromType,

View file

@ -13,13 +13,15 @@ use crate::{
ReflectFromReflect, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, ReflectSerialize, Set,
SetInfo, TypeInfo, TypeParamInfo, TypePath, TypeRegistration, TypeRegistry, Typed,
};
use alloc::{borrow::Cow, collections::VecDeque};
use alloc::{borrow::Cow, borrow::ToOwned, boxed::Box, collections::VecDeque, format, vec::Vec};
use bevy_reflect_derive::{impl_reflect, impl_reflect_opaque};
use core::{
any::Any,
fmt,
hash::{BuildHasher, Hash, Hasher},
};
#[cfg(feature = "std")]
use std::path::Path;
impl_reflect_opaque!(bool(
@ -89,6 +91,7 @@ impl_reflect_opaque!(::alloc::string::String(
Deserialize,
Default
));
#[cfg(feature = "std")]
impl_reflect_opaque!(::std::path::PathBuf(
Debug,
Hash,
@ -114,6 +117,7 @@ impl_reflect_opaque!(::bevy_utils::Duration(
Deserialize,
Default
));
#[cfg(any(target_arch = "wasm32", feature = "std"))]
impl_reflect_opaque!(::bevy_utils::Instant(Debug, Hash, PartialEq));
impl_reflect_opaque!(::core::num::NonZeroI128(
Debug,
@ -205,7 +209,7 @@ impl_reflect_opaque!(::alloc::sync::Arc<T: Send + Sync + ?Sized>);
// `Serialize` and `Deserialize` only for platforms supported by serde:
// https://github.com/serde-rs/serde/blob/3ffb86fc70efd3d329519e2dddfa306cc04f167c/serde/src/de/impls.rs#L1732
#[cfg(any(unix, windows))]
#[cfg(all(any(unix, windows), feature = "std"))]
impl_reflect_opaque!(::std::ffi::OsString(
Debug,
Hash,
@ -213,7 +217,7 @@ impl_reflect_opaque!(::std::ffi::OsString(
Serialize,
Deserialize
));
#[cfg(not(any(unix, windows)))]
#[cfg(all(not(any(unix, windows)), feature = "std"))]
impl_reflect_opaque!(::std::ffi::OsString(Debug, Hash, PartialEq));
impl_reflect_opaque!(::alloc::collections::BinaryHeap<T: Clone>);
@ -235,8 +239,14 @@ macro_rules! impl_reflect_for_atomic {
registration.insert::<ReflectFromPtr>(FromType::<Self>::from_type());
registration.insert::<ReflectFromReflect>(FromType::<Self>::from_type());
registration.insert::<ReflectDefault>(FromType::<Self>::from_type());
registration.insert::<ReflectSerialize>(FromType::<Self>::from_type());
registration.insert::<ReflectDeserialize>(FromType::<Self>::from_type());
// Serde only supports atomic types when the "std" feature is enabled
#[cfg(feature = "std")]
{
registration.insert::<ReflectSerialize>(FromType::<Self>::from_type());
registration.insert::<ReflectDeserialize>(FromType::<Self>::from_type());
}
registration
}
}
@ -820,10 +830,13 @@ macro_rules! impl_reflect_for_hashmap {
};
}
#[cfg(feature = "std")]
impl_reflect_for_hashmap!(::std::collections::HashMap<K, V, S>);
#[cfg(feature = "std")]
impl_type_path!(::std::collections::hash_map::RandomState);
#[cfg(feature = "std")]
impl_type_path!(::std::collections::HashMap<K, V, S>);
#[cfg(feature = "functions")]
#[cfg(all(feature = "functions", feature = "std"))]
crate::func::macros::impl_function_traits!(::std::collections::HashMap<K, V, S>;
<
K: FromReflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Hash,
@ -1049,9 +1062,11 @@ macro_rules! impl_reflect_for_hashset {
impl_type_path!(::bevy_utils::NoOpHash);
impl_type_path!(::bevy_utils::FixedState);
#[cfg(feature = "std")]
impl_reflect_for_hashset!(::std::collections::HashSet<V,S>);
#[cfg(feature = "std")]
impl_type_path!(::std::collections::HashSet<V, S>);
#[cfg(feature = "functions")]
#[cfg(all(feature = "functions", feature = "std"))]
crate::func::macros::impl_function_traits!(::std::collections::HashSet<V, S>;
<
V: Hash + Eq + FromReflect + TypePath + GetTypeRegistration,
@ -1970,6 +1985,7 @@ impl FromReflect for &'static str {
#[cfg(feature = "functions")]
crate::func::macros::impl_function_traits!(&'static str);
#[cfg(feature = "std")]
impl PartialReflect for &'static Path {
fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
Some(<Self as Typed>::type_info())
@ -2048,6 +2064,7 @@ impl PartialReflect for &'static Path {
}
}
#[cfg(feature = "std")]
impl Reflect for &'static Path {
fn into_any(self: Box<Self>) -> Box<dyn Any> {
self
@ -2079,6 +2096,7 @@ impl Reflect for &'static Path {
}
}
#[cfg(feature = "std")]
impl Typed for &'static Path {
fn type_info() -> &'static TypeInfo {
static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new();
@ -2086,6 +2104,7 @@ impl Typed for &'static Path {
}
}
#[cfg(feature = "std")]
impl GetTypeRegistration for &'static Path {
fn get_type_registration() -> TypeRegistration {
let mut registration = TypeRegistration::of::<Self>();
@ -2094,15 +2113,17 @@ impl GetTypeRegistration for &'static Path {
}
}
#[cfg(feature = "std")]
impl FromReflect for &'static Path {
fn from_reflect(reflect: &dyn PartialReflect) -> Option<Self> {
reflect.try_downcast_ref::<Self>().copied()
}
}
#[cfg(feature = "functions")]
#[cfg(all(feature = "functions", feature = "std"))]
crate::func::macros::impl_function_traits!(&'static Path);
#[cfg(feature = "std")]
impl PartialReflect for Cow<'static, Path> {
fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
Some(<Self as Typed>::type_info())
@ -2185,6 +2206,7 @@ impl PartialReflect for Cow<'static, Path> {
}
}
#[cfg(feature = "std")]
impl Reflect for Cow<'static, Path> {
fn into_any(self: Box<Self>) -> Box<dyn Any> {
self
@ -2216,6 +2238,7 @@ impl Reflect for Cow<'static, Path> {
}
}
#[cfg(feature = "std")]
impl Typed for Cow<'static, Path> {
fn type_info() -> &'static TypeInfo {
static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new();
@ -2223,15 +2246,18 @@ impl Typed for Cow<'static, Path> {
}
}
#[cfg(feature = "std")]
impl_type_path!(::std::path::Path);
impl_type_path!(::alloc::borrow::Cow<'a: 'static, T: ToOwned + ?Sized>);
#[cfg(feature = "std")]
impl FromReflect for Cow<'static, Path> {
fn from_reflect(reflect: &dyn PartialReflect) -> Option<Self> {
Some(reflect.try_downcast_ref::<Self>()?.clone())
}
}
#[cfg(feature = "std")]
impl GetTypeRegistration for Cow<'static, Path> {
fn get_type_registration() -> TypeRegistration {
let mut registration = TypeRegistration::of::<Self>();
@ -2243,7 +2269,7 @@ impl GetTypeRegistration for Cow<'static, Path> {
}
}
#[cfg(feature = "functions")]
#[cfg(all(feature = "functions", feature = "std"))]
crate::func::macros::impl_function_traits!(Cow<'static, Path>);
#[cfg(test)]

View file

@ -1,3 +1,4 @@
use alloc::boxed::Box;
use derive_more::derive::{Display, Error};
#[cfg(feature = "functions")]

View file

@ -553,6 +553,8 @@
//! [`ArgList`]: crate::func::ArgList
//! [derive `Reflect`]: derive@crate::Reflect
#![cfg_attr(not(feature = "std"), no_std)]
extern crate alloc;
mod array;
@ -651,6 +653,18 @@ pub mod __macro_exports {
DynamicTupleStruct, GetTypeRegistration, TypeRegistry,
};
/// Re-exports of items from the [`alloc`] crate.
///
/// This is required because in `std` environments (e.g., the `std` feature is enabled)
/// the `alloc` crate may not have been included, making its namespace unreliable.
pub mod alloc_utils {
pub use ::alloc::{
borrow::{Cow, ToOwned},
boxed::Box,
string::ToString,
};
}
/// A wrapper trait around [`GetTypeRegistration`].
///
/// This trait is used by the derive macro to recursively register all type dependencies.

View file

@ -1,3 +1,4 @@
use alloc::{boxed::Box, vec::Vec};
use core::{
any::Any,
fmt::{Debug, Formatter},

View file

@ -9,6 +9,7 @@ use crate::{
PartialReflect, Reflect, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, Type, TypeInfo,
TypePath,
};
use alloc::{boxed::Box, format, vec::Vec};
/// A trait used to power [map-like] operations via [reflection].
///
@ -42,7 +43,7 @@ use crate::{
/// ```
///
/// [`HashMap`]: std::collections::HashMap
/// [`BTreeMap`]: std::collections::BTreeMap
/// [`BTreeMap`]: alloc::collections::BTreeMap
/// [map-like]: https://doc.rust-lang.org/book/ch08-03-hash-maps.html
/// [reflection]: crate
pub trait Map: PartialReflect {

View file

@ -9,6 +9,7 @@ pub use parse::ParseError;
use parse::PathParser;
use crate::{PartialReflect, Reflect};
use alloc::vec::Vec;
use core::fmt;
use derive_more::derive::{Display, From};

View file

@ -3,6 +3,7 @@ use crate::{
tuple_debug, tuple_struct_debug, DynamicTypePath, DynamicTyped, OpaqueInfo, ReflectKind,
ReflectKindMismatchError, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, Typed,
};
use alloc::boxed::Box;
use core::{
any::{Any, TypeId},
fmt::Debug,
@ -319,17 +320,17 @@ where
note = "consider annotating `{Self}` with `#[derive(Reflect)]`"
)]
pub trait Reflect: PartialReflect + DynamicTyped + Any {
/// Returns the value as a [`Box<dyn Any>`][std::any::Any].
/// Returns the value as a [`Box<dyn Any>`][core::any::Any].
///
/// For remote wrapper types, this will return the remote type instead.
fn into_any(self: Box<Self>) -> Box<dyn Any>;
/// Returns the value as a [`&dyn Any`][std::any::Any].
/// Returns the value as a [`&dyn Any`][core::any::Any].
///
/// For remote wrapper types, this will return the remote type instead.
fn as_any(&self) -> &dyn Any;
/// Returns the value as a [`&mut dyn Any`][std::any::Any].
/// Returns the value as a [`&mut dyn Any`][core::any::Any].
///
/// For remote wrapper types, this will return the remote type instead.
fn as_any_mut(&mut self) -> &mut dyn Any;

View file

@ -41,7 +41,7 @@ use crate::Reflect;
/// ```
///
/// [reflectable]: Reflect
/// [`transmute`]: std::mem::transmute
/// [`transmute`]: core::mem::transmute
/// [very unsafe]: https://doc.rust-lang.org/1.71.0/nomicon/transmutes.html
/// [`FromReflect`]: crate::FromReflect
pub trait ReflectRemote: Reflect {

View file

@ -2,6 +2,7 @@ use crate::{
serde::{de::registration_utils::try_get_registration, TypedReflectDeserializer},
ArrayInfo, DynamicArray, TypeRegistry,
};
use alloc::{string::ToString, vec::Vec};
use core::{fmt, fmt::Formatter};
use serde::de::{Error, SeqAccess, Visitor};

View file

@ -1,5 +1,6 @@
use crate::serde::de::error_utils::make_custom_error;
use crate::{FromType, PartialReflect, TypeRegistry};
use alloc::boxed::Box;
use serde::Deserializer;
/// Trait used to provide finer control when deserializing a reflected type with one of

View file

@ -12,6 +12,7 @@ use crate::{
},
PartialReflect, ReflectDeserialize, TypeInfo, TypePath, TypeRegistration, TypeRegistry,
};
use alloc::boxed::Box;
use core::{fmt, fmt::Formatter};
use serde::de::{DeserializeSeed, Error, IgnoredAny, MapAccess, Visitor};
@ -219,7 +220,7 @@ impl<'de, P: ReflectDeserializerProcessor> DeserializeSeed<'de> for ReflectDeser
/// # Example
///
/// ```
/// # use std::any::TypeId;
/// # use core::any::TypeId;
/// # use serde::de::DeserializeSeed;
/// # use bevy_reflect::prelude::*;
/// # use bevy_reflect::{DynamicStruct, TypeRegistry, serde::TypedReflectDeserializer};

View file

@ -1,3 +1,7 @@
use alloc::{
string::{String, ToString},
vec::Vec,
};
use core::{
fmt,
fmt::{Debug, Display, Formatter},

View file

@ -1,4 +1,5 @@
use crate::{PartialReflect, TypeRegistration, TypeRegistry};
use alloc::boxed::Box;
/// Allows overriding the default deserialization behavior of
/// [`ReflectDeserializer`] and [`TypedReflectDeserializer`] for specific

View file

@ -9,6 +9,7 @@ use crate::{
},
DynamicStruct, NamedField, StructInfo, StructVariantInfo, TypeRegistration, TypeRegistry,
};
use alloc::string::ToString;
use core::slice::Iter;
use serde::de::{Error, MapAccess, SeqAccess};

View file

@ -6,6 +6,7 @@ use crate::{
DynamicTuple, TupleInfo, TupleStructInfo, TupleVariantInfo, TypeRegistration, TypeRegistry,
UnnamedField,
};
use alloc::string::ToString;
use serde::de::{Error, SeqAccess};
use super::ReflectDeserializerProcessor;

View file

@ -1,3 +1,4 @@
use alloc::boxed::Box;
use core::ops::Deref;
/// A type-erased serializable value.

View file

@ -1,4 +1,5 @@
use crate::{FromType, Reflect, TypeRegistry};
use alloc::boxed::Box;
use serde::{Serialize, Serializer};
/// Trait used to provide finer control when serializing a reflected type with one of

View file

@ -1,4 +1,5 @@
use crate::Reflect;
use alloc::boxed::Box;
use bevy_utils::{hashbrown::hash_map::Iter, HashMap};
/// Contains data relevant to the automatic reflect powered (de)serialization of a type.
@ -26,7 +27,7 @@ impl SerializationData {
/// # Example
///
/// ```
/// # use std::any::TypeId;
/// # use core::any::TypeId;
/// # use bevy_reflect::{Reflect, Struct, TypeRegistry, serde::SerializationData};
/// #[derive(Reflect)]
/// struct MyStruct {
@ -66,7 +67,7 @@ impl SerializationData {
/// # Example
///
/// ```
/// # use std::any::TypeId;
/// # use core::any::TypeId;
/// # use bevy_reflect::{Reflect, Struct, TypeRegistry, serde::SerializationData};
/// #[derive(Reflect)]
/// struct MyStruct {

View file

@ -1,3 +1,4 @@
use alloc::{boxed::Box, format, vec::Vec};
use core::fmt::{Debug, Formatter};
use bevy_reflect_derive::impl_type_path;
@ -42,7 +43,7 @@ use crate::{
/// ```
///
/// [`HashSet`]: std::collections::HashSet
/// [`BTreeSet`]: std::collections::BTreeSet
/// [`BTreeSet`]: alloc::collections::BTreeSet
/// [set-like]: https://doc.rust-lang.org/stable/std/collections/struct.HashSet.html
/// [reflection]: crate
pub trait Set: PartialReflect {

View file

@ -1,4 +1,5 @@
use crate::{FromType, Reflect};
use alloc::boxed::Box;
/// A struct used to provide the default value of a type.
///

View file

@ -6,7 +6,7 @@ use crate::{
ApplyError, Generics, NamedField, PartialReflect, Reflect, ReflectKind, ReflectMut,
ReflectOwned, ReflectRef, Type, TypeInfo, TypePath,
};
use alloc::{borrow::Cow, sync::Arc};
use alloc::{borrow::Cow, boxed::Box, sync::Arc, vec::Vec};
use bevy_reflect_derive::impl_type_path;
use bevy_utils::HashMap;
use core::{

View file

@ -8,6 +8,7 @@ use crate::{
ReflectMut, ReflectOwned, ReflectRef, Type, TypeInfo, TypePath, TypeRegistration, TypeRegistry,
Typed, UnnamedField,
};
use alloc::{boxed::Box, vec, vec::Vec};
use core::{
any::Any,
fmt::{Debug, Formatter},
@ -376,7 +377,7 @@ impl FromIterator<Box<dyn PartialReflect>> for DynamicTuple {
impl IntoIterator for DynamicTuple {
type Item = Box<dyn PartialReflect>;
type IntoIter = alloc::vec::IntoIter<Self::Item>;
type IntoIter = vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.fields.into_iter()
@ -697,6 +698,7 @@ macro_rules! impl_type_path_tuple {
$(#[$meta])*
impl <$param: TypePath> TypePath for ($param,) {
fn type_path() -> &'static str {
use $crate::__macro_exports::alloc_utils::ToOwned;
static CELL: GenericTypePathCell = GenericTypePathCell::new();
CELL.get_or_insert::<Self, _>(|| {
"(".to_owned() + $param::type_path() + ",)"
@ -704,6 +706,7 @@ macro_rules! impl_type_path_tuple {
}
fn short_type_path() -> &'static str {
use $crate::__macro_exports::alloc_utils::ToOwned;
static CELL: GenericTypePathCell = GenericTypePathCell::new();
CELL.get_or_insert::<Self, _>(|| {
"(".to_owned() + $param::short_type_path() + ",)"
@ -716,6 +719,7 @@ macro_rules! impl_type_path_tuple {
$(#[$meta])*
impl <$($param: TypePath,)* $last: TypePath> TypePath for ($($param,)* $last) {
fn type_path() -> &'static str {
use $crate::__macro_exports::alloc_utils::ToOwned;
static CELL: GenericTypePathCell = GenericTypePathCell::new();
CELL.get_or_insert::<Self, _>(|| {
"(".to_owned() $(+ $param::type_path() + ", ")* + $last::type_path() + ")"
@ -723,6 +727,7 @@ macro_rules! impl_type_path_tuple {
}
fn short_type_path() -> &'static str {
use $crate::__macro_exports::alloc_utils::ToOwned;
static CELL: GenericTypePathCell = GenericTypePathCell::new();
CELL.get_or_insert::<Self, _>(|| {
"(".to_owned() $(+ $param::short_type_path() + ", ")* + $last::short_type_path() + ")"

View file

@ -8,7 +8,7 @@ use crate::{
ApplyError, DynamicTuple, Generics, PartialReflect, Reflect, ReflectKind, ReflectMut,
ReflectOwned, ReflectRef, Tuple, Type, TypeInfo, TypePath, UnnamedField,
};
use alloc::sync::Arc;
use alloc::{boxed::Box, sync::Arc, vec::Vec};
use core::{
fmt::{Debug, Formatter},
slice::Iter,

View file

@ -32,7 +32,7 @@ use derive_more::derive::{Display, Error};
/// # Example
///
/// ```
/// # use std::any::Any;
/// # use core::any::Any;
/// # use bevy_reflect::{DynamicTypePath, NamedField, PartialReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, StructInfo, TypeInfo, TypePath, OpaqueInfo, ApplyError};
/// # use bevy_reflect::utility::NonGenericTypeInfoCell;
/// use bevy_reflect::Typed;
@ -498,7 +498,7 @@ macro_rules! impl_type_methods {
/// The [`TypeId`] of this type.
///
/// [`TypeId`]: std::any::TypeId
/// [`TypeId`]: core::any::TypeId
pub fn type_id(&self) -> ::core::any::TypeId {
self.ty().id()
}
@ -528,7 +528,7 @@ macro_rules! impl_type_methods {
/// and does not verify they share the same [`TypePath`]
/// (though it implies they do).
///
/// [`TypeId`]: std::any::TypeId
/// [`TypeId`]: core::any::TypeId
/// [`TypePath`]: crate::type_path::TypePath
pub fn is<T: ::core::any::Any>(&self) -> bool {
self.ty().is::<T>()

View file

@ -4,6 +4,9 @@ use core::{
slice::Iter,
};
#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, format, vec};
/// Helper struct for managing a stack of [`TypeInfo`] instances.
///
/// This is useful for tracking the type hierarchy when serializing and deserializing types.

View file

@ -2,7 +2,7 @@ use core::fmt;
/// A static accessor to type paths and names.
///
/// The engine uses this trait over [`std::any::type_name`] for stability and flexibility.
/// The engine uses this trait over [`core::any::type_name`] for stability and flexibility.
///
/// This trait is automatically implemented by the `#[derive(Reflect)]` macro
/// and allows type path information to be processed without an instance of that type.
@ -16,7 +16,7 @@ use core::fmt;
/// Certain parts of the engine, e.g. [(de)serialization], rely on type paths as identifiers
/// for matching dynamic values to concrete types.
///
/// Using [`std::any::type_name`], a scene containing `my_crate::foo::MyComponent` would break,
/// Using [`core::any::type_name`], a scene containing `my_crate::foo::MyComponent` would break,
/// failing to deserialize if the component was moved from the `foo` module to the `bar` module,
/// becoming `my_crate::bar::MyComponent`.
/// This trait, through attributes when deriving itself or [`Reflect`], can ensure breaking changes are avoidable.

View file

@ -1,5 +1,6 @@
use crate::{serde::Serializable, FromReflect, Reflect, TypeInfo, TypePath, Typed};
use alloc::sync::Arc;
use alloc::{boxed::Box, string::String};
use bevy_ptr::{Ptr, PtrMut};
use bevy_utils::{HashMap, HashSet, TypeIdMap};
use core::{
@ -9,8 +10,13 @@ use core::{
};
use downcast_rs::{impl_downcast, Downcast};
use serde::Deserialize;
#[cfg(feature = "std")]
use std::sync::{PoisonError, RwLock, RwLockReadGuard, RwLockWriteGuard};
#[cfg(not(feature = "std"))]
use spin::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
/// A registry of [reflected] types.
///
/// This struct is used as the central store for type information.
@ -40,12 +46,12 @@ pub struct TypeRegistryArc {
impl Debug for TypeRegistryArc {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.internal
.read()
.unwrap_or_else(PoisonError::into_inner)
.type_path_to_id
.keys()
.fmt(f)
let read_lock = self.internal.read();
#[cfg(feature = "std")]
let read_lock = read_lock.unwrap_or_else(PoisonError::into_inner);
read_lock.type_path_to_id.keys().fmt(f)
}
}
@ -131,7 +137,7 @@ impl TypeRegistry {
/// # Example
///
/// ```
/// # use std::any::TypeId;
/// # use core::any::TypeId;
/// # use bevy_reflect::{Reflect, TypeRegistry, std_traits::ReflectDefault};
/// #[derive(Reflect, Default)]
/// #[reflect(Default)]
@ -428,14 +434,22 @@ impl TypeRegistry {
impl TypeRegistryArc {
/// Takes a read lock on the underlying [`TypeRegistry`].
pub fn read(&self) -> RwLockReadGuard<'_, TypeRegistry> {
self.internal.read().unwrap_or_else(PoisonError::into_inner)
let read_lock = self.internal.read();
#[cfg(feature = "std")]
let read_lock = read_lock.unwrap_or_else(PoisonError::into_inner);
read_lock
}
/// Takes a write lock on the underlying [`TypeRegistry`].
pub fn write(&self) -> RwLockWriteGuard<'_, TypeRegistry> {
self.internal
.write()
.unwrap_or_else(PoisonError::into_inner)
let write_lock = self.internal.write();
#[cfg(feature = "std")]
let write_lock = write_lock.unwrap_or_else(PoisonError::into_inner);
write_lock
}
}
@ -746,7 +760,7 @@ impl<T: for<'a> Deserialize<'a> + Reflect> FromType<T> for ReflectDeserialize {
/// ```
/// use bevy_reflect::{TypeRegistry, Reflect, ReflectFromPtr};
/// use bevy_ptr::Ptr;
/// use std::ptr::NonNull;
/// use core::ptr::NonNull;
///
/// #[derive(Reflect)]
/// struct Reflected(String);
@ -757,7 +771,7 @@ impl<T: for<'a> Deserialize<'a> + Reflect> FromType<T> for ReflectDeserialize {
/// let mut value = Reflected("Hello world!".to_string());
/// let value = Ptr::from(&value);
///
/// let reflect_data = type_registry.get(std::any::TypeId::of::<Reflected>()).unwrap();
/// let reflect_data = type_registry.get(core::any::TypeId::of::<Reflected>()).unwrap();
/// let reflect_from_ptr = reflect_data.data::<ReflectFromPtr>().unwrap();
/// // SAFE: `value` is of type `Reflected`, which the `ReflectFromPtr` was created for
/// let value = unsafe { reflect_from_ptr.as_reflect(value) };

View file

@ -1,13 +1,19 @@
//! Helpers for working with Bevy reflection.
use crate::TypeInfo;
use alloc::boxed::Box;
use bevy_utils::{FixedState, NoOpHash, TypeIdMap};
use core::{
any::{Any, TypeId},
hash::BuildHasher,
};
#[cfg(feature = "std")]
use std::sync::{OnceLock, PoisonError, RwLock};
#[cfg(not(feature = "std"))]
use spin::{Once as OnceLock, RwLock};
/// A type that can be stored in a ([`Non`])[`GenericTypeCell`].
///
/// [`Non`]: NonGenericTypeCell
@ -22,6 +28,7 @@ pub struct TypePathComponent;
mod sealed {
use super::{TypeInfo, TypePathComponent, TypedProperty};
use alloc::string::String;
pub trait Sealed {}
@ -48,7 +55,7 @@ mod sealed {
/// ## Example
///
/// ```
/// # use std::any::Any;
/// # use core::any::Any;
/// # use bevy_reflect::{DynamicTypePath, NamedField, PartialReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, StructInfo, Typed, TypeInfo, TypePath, ApplyError};
/// use bevy_reflect::utility::NonGenericTypeInfoCell;
///
@ -114,7 +121,11 @@ impl<T: TypedProperty> NonGenericTypeCell<T> {
where
F: FnOnce() -> T::Stored,
{
self.0.get_or_init(f)
#[cfg(feature = "std")]
return self.0.get_or_init(f);
#[cfg(not(feature = "std"))]
return self.0.call_once(f);
}
}
@ -137,7 +148,7 @@ impl<T: TypedProperty> Default for NonGenericTypeCell<T> {
/// Implementing [`TypeInfo`] with generics.
///
/// ```
/// # use std::any::Any;
/// # use core::any::Any;
/// # use bevy_reflect::{DynamicTypePath, PartialReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, TupleStructInfo, Typed, TypeInfo, TypePath, UnnamedField, ApplyError, Generics, TypeParamInfo};
/// use bevy_reflect::utility::GenericTypeInfoCell;
///
@ -186,7 +197,7 @@ impl<T: TypedProperty> Default for NonGenericTypeCell<T> {
/// Implementing [`TypePath`] with generics.
///
/// ```
/// # use std::any::Any;
/// # use core::any::Any;
/// # use bevy_reflect::TypePath;
/// use bevy_reflect::utility::GenericTypePathCell;
///
@ -247,11 +258,12 @@ impl<T: TypedProperty> GenericTypeCell<T> {
///
/// This method will then return the correct [`TypedProperty`] reference for the given type `T`.
fn get_by_type_id(&self, type_id: TypeId) -> Option<&T::Stored> {
self.0
.read()
.unwrap_or_else(PoisonError::into_inner)
.get(&type_id)
.copied()
let read_lock = self.0.read();
#[cfg(feature = "std")]
let read_lock = read_lock.unwrap_or_else(PoisonError::into_inner);
read_lock.get(&type_id).copied()
}
/// Returns a reference to the [`TypedProperty`] stored in the cell.
@ -269,9 +281,14 @@ impl<T: TypedProperty> GenericTypeCell<T> {
}
fn insert_by_type_id(&self, type_id: TypeId, value: T::Stored) -> &T::Stored {
self.0
.write()
.unwrap_or_else(PoisonError::into_inner)
let write_lock = self.0.write();
#[cfg(feature = "std")]
let write_lock = write_lock.unwrap_or_else(PoisonError::into_inner);
let mut write_lock = write_lock;
write_lock
.entry(type_id)
.insert({
// We leak here in order to obtain a `&'static` reference.

View file

@ -62,6 +62,22 @@ impl Prepare for CompileCheckNoStdCommand {
"Please fix compiler errors in output above for bevy_mikktspace no_std compatibility.",
));
commands.push(PreparedCommand::new::<Self>(
cmd!(
sh,
"cargo check -p bevy_mikktspace --no-default-features --features libm --target {target}"
),
"Please fix compiler errors in output above for bevy_mikktspace no_std compatibility.",
));
commands.push(PreparedCommand::new::<Self>(
cmd!(
sh,
"cargo check -p bevy_reflect --no-default-features --target {target}"
),
"Please fix compiler errors in output above for bevy_reflect no_std compatibility.",
));
commands.push(PreparedCommand::new::<Self>(
cmd!(
sh,