mirror of
https://github.com/bevyengine/bevy
synced 2024-09-20 06:22:01 +00:00
Allow bevy_utils
in no_std
Contexts (#15279)
# Objective - Adjust `bevy_utils` to make it `no_std` compatible - Partially replaces #6581 - Contributes to #8161 - Contributes to #6370 ## Solution Added `alloc` and `std` features to `bevy_utils` (`std` is enabled by default), allowing the crate's use in `no_std` contexts. ## Testing - CI passed locally. - Used `bevy_utils` in a `no_std` crate as an experiment and compiled successfully. ## Migration Guide If you were importing `bevy_utils` and setting `default_features` to `false`, but relying on elements which are now gated behind the `std` or `alloc` features, include the relevant feature in your `Cargo.toml`. ## Notes - Bevy already includes a single `no_std` crate, `bevy_ptr`, so there is precedent for this change. - As `bevy_utils` is widely used across the rest of Bevy, further work to make Bevy `no_std` compatible would be blocked on this crate, if such work was to be undertaken. - Most of the changes in this PR are just the removal of an unnecessary call to `to_string()` within unit tests.
This commit is contained in:
parent
b1273d48cb
commit
bd489068c6
6 changed files with 50 additions and 35 deletions
|
@ -9,11 +9,16 @@ license = "MIT OR Apache-2.0"
|
||||||
keywords = ["bevy"]
|
keywords = ["bevy"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
default = ["std"]
|
||||||
|
std = ["alloc", "tracing/std", "ahash/std"]
|
||||||
|
alloc = []
|
||||||
detailed_trace = []
|
detailed_trace = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ahash = "0.8.7"
|
ahash = { version = "0.8.7", default-features = false, features = [
|
||||||
tracing = { version = "0.1", default-features = false, features = ["std"] }
|
"runtime-rng",
|
||||||
|
] }
|
||||||
|
tracing = { version = "0.1", default-features = false }
|
||||||
web-time = { version = "1.1" }
|
web-time = { version = "1.1" }
|
||||||
hashbrown = { version = "0.14.2", features = ["serde"] }
|
hashbrown = { version = "0.14.2", features = ["serde"] }
|
||||||
bevy_utils_proc_macros = { version = "0.15.0-dev", path = "macros" }
|
bevy_utils_proc_macros = { version = "0.15.0-dev", path = "macros" }
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//! Utilities for working with [`Future`]s.
|
//! Utilities for working with [`Future`]s.
|
||||||
use std::{
|
use core::{
|
||||||
future::Future,
|
future::Future,
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
|
task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
|
||||||
|
@ -44,7 +44,7 @@ fn noop(_data: *const ()) {}
|
||||||
const NOOP_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(noop_clone, noop, noop, noop);
|
const NOOP_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(noop_clone, noop, noop, noop);
|
||||||
|
|
||||||
fn noop_raw_waker() -> RawWaker {
|
fn noop_raw_waker() -> RawWaker {
|
||||||
RawWaker::new(std::ptr::null(), &NOOP_WAKER_VTABLE)
|
RawWaker::new(core::ptr::null(), &NOOP_WAKER_VTABLE)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn noop_waker() -> Waker {
|
fn noop_waker() -> Waker {
|
||||||
|
|
|
@ -4,12 +4,16 @@
|
||||||
html_logo_url = "https://bevyengine.org/assets/icon.png",
|
html_logo_url = "https://bevyengine.org/assets/icon.png",
|
||||||
html_favicon_url = "https://bevyengine.org/assets/icon.png"
|
html_favicon_url = "https://bevyengine.org/assets/icon.png"
|
||||||
)]
|
)]
|
||||||
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|
||||||
//! General utilities for first-party [Bevy] engine crates.
|
//! General utilities for first-party [Bevy] engine crates.
|
||||||
//!
|
//!
|
||||||
//! [Bevy]: https://bevyengine.org/
|
//! [Bevy]: https://bevyengine.org/
|
||||||
//!
|
//!
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
/// The utilities prelude.
|
/// The utilities prelude.
|
||||||
///
|
///
|
||||||
/// This includes the most common types in this crate, re-exported for your convenience.
|
/// This includes the most common types in this crate, re-exported for your convenience.
|
||||||
|
@ -18,7 +22,9 @@ pub mod prelude {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod futures;
|
pub mod futures;
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
mod short_names;
|
mod short_names;
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
pub use short_names::get_short_name;
|
pub use short_names::get_short_name;
|
||||||
pub mod synccell;
|
pub mod synccell;
|
||||||
pub mod syncunsafecell;
|
pub mod syncunsafecell;
|
||||||
|
@ -37,8 +43,10 @@ pub use parallel_queue::*;
|
||||||
pub use tracing;
|
pub use tracing;
|
||||||
pub use web_time::{Duration, Instant, SystemTime, SystemTimeError, TryFromFloatSecsError};
|
pub use web_time::{Duration, Instant, SystemTime, SystemTimeError, TryFromFloatSecsError};
|
||||||
|
|
||||||
use hashbrown::hash_map::RawEntryMut;
|
#[cfg(feature = "alloc")]
|
||||||
use std::{
|
use alloc::boxed::Box;
|
||||||
|
|
||||||
|
use core::{
|
||||||
any::TypeId,
|
any::TypeId,
|
||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
hash::{BuildHasher, BuildHasherDefault, Hash, Hasher},
|
hash::{BuildHasher, BuildHasherDefault, Hash, Hasher},
|
||||||
|
@ -46,6 +54,7 @@ use std::{
|
||||||
mem::ManuallyDrop,
|
mem::ManuallyDrop,
|
||||||
ops::Deref,
|
ops::Deref,
|
||||||
};
|
};
|
||||||
|
use hashbrown::hash_map::RawEntryMut;
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
mod conditional_send {
|
mod conditional_send {
|
||||||
|
@ -66,11 +75,12 @@ pub use conditional_send::*;
|
||||||
|
|
||||||
/// Use [`ConditionalSendFuture`] for a future with an optional Send trait bound, as on certain platforms (eg. Wasm),
|
/// Use [`ConditionalSendFuture`] for a future with an optional Send trait bound, as on certain platforms (eg. Wasm),
|
||||||
/// futures aren't Send.
|
/// futures aren't Send.
|
||||||
pub trait ConditionalSendFuture: std::future::Future + ConditionalSend {}
|
pub trait ConditionalSendFuture: core::future::Future + ConditionalSend {}
|
||||||
impl<T: std::future::Future + ConditionalSend> ConditionalSendFuture for T {}
|
impl<T: core::future::Future + ConditionalSend> ConditionalSendFuture for T {}
|
||||||
|
|
||||||
/// An owned and dynamically typed Future used when you can't statically type your result or need to add some indirection.
|
/// An owned and dynamically typed Future used when you can't statically type your result or need to add some indirection.
|
||||||
pub type BoxedFuture<'a, T> = std::pin::Pin<Box<dyn ConditionalSendFuture<Output = T> + 'a>>;
|
#[cfg(feature = "alloc")]
|
||||||
|
pub type BoxedFuture<'a, T> = core::pin::Pin<Box<dyn ConditionalSendFuture<Output = T> + 'a>>;
|
||||||
|
|
||||||
/// A shortcut alias for [`hashbrown::hash_map::Entry`].
|
/// A shortcut alias for [`hashbrown::hash_map::Entry`].
|
||||||
pub type Entry<'a, K, V, S = BuildHasherDefault<AHasher>> = hashbrown::hash_map::Entry<'a, K, V, S>;
|
pub type Entry<'a, K, V, S = BuildHasherDefault<AHasher>> = hashbrown::hash_map::Entry<'a, K, V, S>;
|
||||||
|
@ -192,7 +202,7 @@ impl<V: PartialEq, H> PartialEq for Hashed<V, H> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: Debug, H> Debug for Hashed<V, H> {
|
impl<V: Debug, H> Debug for Hashed<V, H> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
f.debug_struct("Hashed")
|
f.debug_struct("Hashed")
|
||||||
.field("hash", &self.hash)
|
.field("hash", &self.hash)
|
||||||
.field("value", &self.value)
|
.field("value", &self.value)
|
||||||
|
@ -417,7 +427,7 @@ mod tests {
|
||||||
fn fast_typeid_hash() {
|
fn fast_typeid_hash() {
|
||||||
struct Hasher;
|
struct Hasher;
|
||||||
|
|
||||||
impl std::hash::Hasher for Hasher {
|
impl core::hash::Hasher for Hasher {
|
||||||
fn finish(&self) -> u64 {
|
fn finish(&self) -> u64 {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
@ -430,8 +440,11 @@ mod tests {
|
||||||
Hash::hash(&TypeId::of::<()>(), &mut Hasher);
|
Hash::hash(&TypeId::of::<()>(), &mut Hasher);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
#[test]
|
#[test]
|
||||||
fn stable_hash_within_same_program_execution() {
|
fn stable_hash_within_same_program_execution() {
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
let mut map_1 = HashMap::new();
|
let mut map_1 = HashMap::new();
|
||||||
let mut map_2 = HashMap::new();
|
let mut map_2 = HashMap::new();
|
||||||
for i in 1..10 {
|
for i in 1..10 {
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
use std::{cell::RefCell, ops::DerefMut};
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
|
use core::{cell::RefCell, ops::DerefMut};
|
||||||
use thread_local::ThreadLocal;
|
use thread_local::ThreadLocal;
|
||||||
|
|
||||||
/// A cohesive set of thread-local values of a given type.
|
/// A cohesive set of thread-local values of a given type.
|
||||||
|
@ -56,6 +59,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
impl<T: Send> Parallel<Vec<T>> {
|
impl<T: Send> Parallel<Vec<T>> {
|
||||||
/// Collect all enqueued items from all threads and appends them to the end of a
|
/// Collect all enqueued items from all threads and appends them to the end of a
|
||||||
/// single Vec.
|
/// single Vec.
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use alloc::string::String;
|
||||||
|
|
||||||
/// Shortens a type name to remove all module paths.
|
/// Shortens a type name to remove all module paths.
|
||||||
///
|
///
|
||||||
/// The short name of a type is its full name as returned by
|
/// The short name of a type is its full name as returned by
|
||||||
|
@ -88,43 +90,37 @@ mod name_formatting_tests {
|
||||||
fn path_separated() {
|
fn path_separated() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
get_short_name("bevy_prelude::make_fun_game"),
|
get_short_name("bevy_prelude::make_fun_game"),
|
||||||
"make_fun_game".to_string()
|
"make_fun_game"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn tuple_type() {
|
fn tuple_type() {
|
||||||
assert_eq!(
|
assert_eq!(get_short_name("(String, String)"), "(String, String)");
|
||||||
get_short_name("(String, String)"),
|
|
||||||
"(String, String)".to_string()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn array_type() {
|
fn array_type() {
|
||||||
assert_eq!(get_short_name("[i32; 3]"), "[i32; 3]".to_string());
|
assert_eq!(get_short_name("[i32; 3]"), "[i32; 3]");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn trivial_generics() {
|
fn trivial_generics() {
|
||||||
assert_eq!(get_short_name("a<B>"), "a<B>".to_string());
|
assert_eq!(get_short_name("a<B>"), "a<B>");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn multiple_type_parameters() {
|
fn multiple_type_parameters() {
|
||||||
assert_eq!(get_short_name("a<B, C>"), "a<B, C>".to_string());
|
assert_eq!(get_short_name("a<B, C>"), "a<B, C>");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn enums() {
|
fn enums() {
|
||||||
assert_eq!(get_short_name("Option::None"), "Option::None".to_string());
|
assert_eq!(get_short_name("Option::None"), "Option::None");
|
||||||
assert_eq!(
|
assert_eq!(get_short_name("Option::Some(2)"), "Option::Some(2)");
|
||||||
get_short_name("Option::Some(2)"),
|
|
||||||
"Option::Some(2)".to_string()
|
|
||||||
);
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
get_short_name("bevy_render::RenderSet::Prepare"),
|
get_short_name("bevy_render::RenderSet::Prepare"),
|
||||||
"RenderSet::Prepare".to_string()
|
"RenderSet::Prepare"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,7 +128,7 @@ mod name_formatting_tests {
|
||||||
fn generics() {
|
fn generics() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
get_short_name("bevy_render::camera::camera::extract_cameras<bevy_render::camera::bundle::Camera3d>"),
|
get_short_name("bevy_render::camera::camera::extract_cameras<bevy_render::camera::bundle::Camera3d>"),
|
||||||
"extract_cameras<Camera3d>".to_string()
|
"extract_cameras<Camera3d>"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +136,7 @@ mod name_formatting_tests {
|
||||||
fn nested_generics() {
|
fn nested_generics() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
get_short_name("bevy::mad_science::do_mad_science<mad_science::Test<mad_science::Tube>, bavy::TypeSystemAbuse>"),
|
get_short_name("bevy::mad_science::do_mad_science<mad_science::Test<mad_science::Tube>, bavy::TypeSystemAbuse>"),
|
||||||
"do_mad_science<Test<Tube>, TypeSystemAbuse>".to_string()
|
"do_mad_science<Test<Tube>, TypeSystemAbuse>"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,15 +144,12 @@ mod name_formatting_tests {
|
||||||
fn sub_path_after_closing_bracket() {
|
fn sub_path_after_closing_bracket() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
get_short_name("bevy_asset::assets::Assets<bevy_scene::dynamic_scene::DynamicScene>::asset_event_system"),
|
get_short_name("bevy_asset::assets::Assets<bevy_scene::dynamic_scene::DynamicScene>::asset_event_system"),
|
||||||
"Assets<DynamicScene>::asset_event_system".to_string()
|
"Assets<DynamicScene>::asset_event_system"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
get_short_name("(String, String)::default"),
|
get_short_name("(String, String)::default"),
|
||||||
"(String, String)::default".to_string()
|
"(String, String)::default"
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
get_short_name("[i32; 16]::default"),
|
|
||||||
"[i32; 16]::default".to_string()
|
|
||||||
);
|
);
|
||||||
|
assert_eq!(get_short_name("[i32; 16]::default"), "[i32; 16]::default");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
//!
|
//!
|
||||||
//! [`std::sync::Exclusive`]: https://doc.rust-lang.org/nightly/std/sync/struct.Exclusive.html
|
//! [`std::sync::Exclusive`]: https://doc.rust-lang.org/nightly/std/sync/struct.Exclusive.html
|
||||||
|
|
||||||
use std::ptr;
|
use core::ptr;
|
||||||
|
|
||||||
/// See [`Exclusive`](https://github.com/rust-lang/rust/issues/98407) for stdlib's upcoming implementation,
|
/// See [`Exclusive`](https://github.com/rust-lang/rust/issues/98407) for stdlib's upcoming implementation,
|
||||||
/// which should replace this one entirely.
|
/// which should replace this one entirely.
|
||||||
|
|
Loading…
Reference in a new issue