Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

34
vendor/bevy_macro_utils/src/attrs.rs vendored Normal file
View File

@@ -0,0 +1,34 @@
use syn::{Expr, ExprLit, Lit};
use crate::symbol::Symbol;
/// Get a [literal string](struct@syn::LitStr) from the provided [expression](Expr).
pub fn get_lit_str(attr_name: Symbol, value: &Expr) -> syn::Result<&syn::LitStr> {
if let Expr::Lit(ExprLit {
lit: Lit::Str(lit), ..
}) = &value
{
Ok(lit)
} else {
Err(syn::Error::new_spanned(
value,
format!("expected {attr_name} attribute to be a string: `{attr_name} = \"...\"`"),
))
}
}
/// Get a [literal boolean](struct@syn::LitBool) from the provided [expression](Expr) as a [`bool`].
pub fn get_lit_bool(attr_name: Symbol, value: &Expr) -> syn::Result<bool> {
if let Expr::Lit(ExprLit {
lit: Lit::Bool(lit),
..
}) = &value
{
Ok(lit.value())
} else {
Err(syn::Error::new_spanned(
value,
format!("expected {attr_name} attribute to be a bool value, `true` or `false`: `{attr_name} = ...`"),
))?
}
}

View File

@@ -0,0 +1,133 @@
extern crate proc_macro;
use alloc::collections::BTreeMap;
use parking_lot::{lock_api::RwLockReadGuard, MappedRwLockReadGuard, RwLock, RwLockWriteGuard};
use proc_macro::TokenStream;
use std::{
env,
path::{Path, PathBuf},
time::SystemTime,
};
use toml_edit::{ImDocument, Item};
/// The path to the `Cargo.toml` file for the Bevy project.
#[derive(Debug)]
pub struct BevyManifest {
manifest: ImDocument<Box<str>>,
modified_time: SystemTime,
}
const BEVY: &str = "bevy";
impl BevyManifest {
/// Returns a global shared instance of the [`BevyManifest`] struct.
pub fn shared() -> MappedRwLockReadGuard<'static, BevyManifest> {
static MANIFESTS: RwLock<BTreeMap<PathBuf, BevyManifest>> = RwLock::new(BTreeMap::new());
let manifest_path = Self::get_manifest_path();
let modified_time = Self::get_manifest_modified_time(&manifest_path)
.expect("The Cargo.toml should have a modified time");
if let Ok(manifest) =
RwLockReadGuard::try_map(MANIFESTS.read(), |manifests| manifests.get(&manifest_path))
{
if manifest.modified_time == modified_time {
return manifest;
}
}
let manifest = BevyManifest {
manifest: Self::read_manifest(&manifest_path),
modified_time,
};
let key = manifest_path.clone();
let mut manifests = MANIFESTS.write();
manifests.insert(key, manifest);
RwLockReadGuard::map(RwLockWriteGuard::downgrade(manifests), |manifests| {
manifests.get(&manifest_path).unwrap()
})
}
fn get_manifest_path() -> PathBuf {
env::var_os("CARGO_MANIFEST_DIR")
.map(|path| {
let mut path = PathBuf::from(path);
path.push("Cargo.toml");
assert!(
path.exists(),
"Cargo manifest does not exist at path {}",
path.display()
);
path
})
.expect("CARGO_MANIFEST_DIR is not defined.")
}
fn get_manifest_modified_time(
cargo_manifest_path: &Path,
) -> Result<SystemTime, std::io::Error> {
std::fs::metadata(cargo_manifest_path).and_then(|metadata| metadata.modified())
}
fn read_manifest(path: &Path) -> ImDocument<Box<str>> {
let manifest = std::fs::read_to_string(path)
.unwrap_or_else(|_| panic!("Unable to read cargo manifest: {}", path.display()))
.into_boxed_str();
ImDocument::parse(manifest)
.unwrap_or_else(|_| panic!("Failed to parse cargo manifest: {}", path.display()))
}
/// Attempt to retrieve the [path](syn::Path) of a particular package in
/// the [manifest](BevyManifest) by [name](str).
pub fn maybe_get_path(&self, name: &str) -> Option<syn::Path> {
let find_in_deps = |deps: &Item| -> Option<syn::Path> {
let package = if deps.get(name).is_some() {
return Some(Self::parse_str(name));
} else if deps.get(BEVY).is_some() {
BEVY
} else {
// Note: to support bevy crate aliases, we could do scanning here to find a crate with a "package" name that
// matches our request, but that would then mean we are scanning every dependency (and dev dependency) for every
// macro execution that hits this branch (which includes all built-in bevy crates). Our current stance is that supporting
// remapped crate names in derive macros is not worth that "compile time" price of admission. As a workaround, people aliasing
// bevy crate names can use "use REMAPPED as bevy_X" or "use REMAPPED::x as bevy_x".
return None;
};
let mut path = Self::parse_str::<syn::Path>(package);
if let Some(module) = name.strip_prefix("bevy_") {
path.segments.push(Self::parse_str(module));
}
Some(path)
};
let deps = self.manifest.get("dependencies");
let deps_dev = self.manifest.get("dev-dependencies");
deps.and_then(find_in_deps)
.or_else(|| deps_dev.and_then(find_in_deps))
}
/// Attempt to parse the provided [path](str) as a [syntax tree node](syn::parse::Parse)
pub fn try_parse_str<T: syn::parse::Parse>(path: &str) -> Option<T> {
syn::parse(path.parse::<TokenStream>().ok()?).ok()
}
/// Returns the path for the crate with the given name.
pub fn get_path(&self, name: &str) -> syn::Path {
self.maybe_get_path(name)
.unwrap_or_else(|| Self::parse_str(name))
}
/// Attempt to parse provided [path](str) as a [syntax tree node](syn::parse::Parse).
///
/// # Panics
///
/// Will panic if the path is not able to be parsed. For a non-panicking option, see [`try_parse_str`]
///
/// [`try_parse_str`]: Self::try_parse_str
pub fn parse_str<T: syn::parse::Parse>(path: &str) -> T {
Self::try_parse_str(path).unwrap()
}
}

105
vendor/bevy_macro_utils/src/fq_std.rs vendored Normal file
View File

@@ -0,0 +1,105 @@
//! This module contains unit structs that should be used inside `quote!` and `spanned_quote!`
//! using the variable interpolation syntax in place of their equivalent structs and traits
//! present in `std`.
//!
//! To create hygienic proc macros, all the names must be its fully qualified form. These
//! unit structs help us to not specify the fully qualified name every single time.
//!
//! # Example
//! Instead of writing this:
//! ```
//! # use quote::quote;
//! quote!(
//! fn get_id() -> Option<i32> {
//! Some(0)
//! }
//! );
//! ```
//! Or this:
//! ```
//! # use quote::quote;
//! quote!(
//! fn get_id() -> ::core::option::Option<i32> {
//! ::core::option::Option::Some(0)
//! }
//! );
//! ```
//! We should write this:
//! ```
//! use bevy_macro_utils::fq_std::FQOption;
//! # use quote::quote;
//!
//! quote!(
//! fn get_id() -> #FQOption<i32> {
//! #FQOption::Some(0)
//! }
//! );
//! ```
use proc_macro2::TokenStream;
use quote::{quote, ToTokens};
/// Fully Qualified (FQ) short name for [`std::any::Any`]
pub struct FQAny;
/// Fully Qualified (FQ) short name for [`Box`]
pub struct FQBox;
/// Fully Qualified (FQ) short name for [`Clone`]
pub struct FQClone;
/// Fully Qualified (FQ) short name for [`Default`]
pub struct FQDefault;
/// Fully Qualified (FQ) short name for [`Option`]
pub struct FQOption;
/// Fully Qualified (FQ) short name for [`Result`]
pub struct FQResult;
/// Fully Qualified (FQ) short name for [`Send`]
pub struct FQSend;
/// Fully Qualified (FQ) short name for [`Sync`]
pub struct FQSync;
impl ToTokens for FQAny {
fn to_tokens(&self, tokens: &mut TokenStream) {
quote!(::core::any::Any).to_tokens(tokens);
}
}
impl ToTokens for FQBox {
fn to_tokens(&self, tokens: &mut TokenStream) {
quote!(::std::boxed::Box).to_tokens(tokens);
}
}
impl ToTokens for FQClone {
fn to_tokens(&self, tokens: &mut TokenStream) {
quote!(::core::clone::Clone).to_tokens(tokens);
}
}
impl ToTokens for FQDefault {
fn to_tokens(&self, tokens: &mut TokenStream) {
quote!(::core::default::Default).to_tokens(tokens);
}
}
impl ToTokens for FQOption {
fn to_tokens(&self, tokens: &mut TokenStream) {
quote!(::core::option::Option).to_tokens(tokens);
}
}
impl ToTokens for FQResult {
fn to_tokens(&self, tokens: &mut TokenStream) {
quote!(::core::result::Result).to_tokens(tokens);
}
}
impl ToTokens for FQSend {
fn to_tokens(&self, tokens: &mut TokenStream) {
quote!(::core::marker::Send).to_tokens(tokens);
}
}
impl ToTokens for FQSync {
fn to_tokens(&self, tokens: &mut TokenStream) {
quote!(::core::marker::Sync).to_tokens(tokens);
}
}

106
vendor/bevy_macro_utils/src/label.rs vendored Normal file
View File

@@ -0,0 +1,106 @@
use proc_macro::{TokenStream, TokenTree};
use quote::{quote, quote_spanned};
use std::collections::HashSet;
use syn::{spanned::Spanned, Ident};
/// Finds an identifier that will not conflict with the specified set of tokens.
///
/// If the identifier is present in `haystack`, extra characters will be added
/// to it until it no longer conflicts with anything.
///
/// Note that the returned identifier can still conflict in niche cases,
/// such as if an identifier in `haystack` is hidden behind an un-expanded macro.
pub fn ensure_no_collision(value: Ident, haystack: TokenStream) -> Ident {
// Collect all the identifiers in `haystack` into a set.
let idents = {
// List of token streams that will be visited in future loop iterations.
let mut unvisited = vec![haystack];
// Identifiers we have found while searching tokens.
let mut found = HashSet::new();
while let Some(tokens) = unvisited.pop() {
for t in tokens {
match t {
// Collect any identifiers we encounter.
TokenTree::Ident(ident) => {
found.insert(ident.to_string());
}
// Queue up nested token streams to be visited in a future loop iteration.
TokenTree::Group(g) => unvisited.push(g.stream()),
TokenTree::Punct(_) | TokenTree::Literal(_) => {}
}
}
}
found
};
let span = value.span();
// If there's a collision, add more characters to the identifier
// until it doesn't collide with anything anymore.
let mut value = value.to_string();
while idents.contains(&value) {
value.push('X');
}
Ident::new(&value, span)
}
/// Derive a label trait
///
/// # Args
///
/// - `input`: The [`syn::DeriveInput`] for struct that is deriving the label trait
/// - `trait_name`: Name of the label trait
/// - `trait_path`: The [path](`syn::Path`) to the label trait
/// - `dyn_eq_path`: The [path](`syn::Path`) to the `DynEq` trait
pub fn derive_label(
input: syn::DeriveInput,
trait_name: &str,
trait_path: &syn::Path,
dyn_eq_path: &syn::Path,
) -> TokenStream {
if let syn::Data::Union(_) = &input.data {
let message = format!("Cannot derive {trait_name} for unions.");
return quote_spanned! {
input.span() => compile_error!(#message);
}
.into();
}
let ident = input.ident.clone();
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
let mut where_clause = where_clause.cloned().unwrap_or_else(|| syn::WhereClause {
where_token: Default::default(),
predicates: Default::default(),
});
where_clause.predicates.push(
syn::parse2(quote! {
Self: 'static + Send + Sync + Clone + Eq + ::core::fmt::Debug + ::core::hash::Hash
})
.unwrap(),
);
quote! {
// To ensure alloc is available, but also prevent its name from clashing, we place the implementation inside an anonymous constant
const _: () = {
extern crate alloc;
impl #impl_generics #trait_path for #ident #ty_generics #where_clause {
fn dyn_clone(&self) -> alloc::boxed::Box<dyn #trait_path> {
alloc::boxed::Box::new(::core::clone::Clone::clone(self))
}
fn as_dyn_eq(&self) -> &dyn #dyn_eq_path {
self
}
fn dyn_hash(&self, mut state: &mut dyn ::core::hash::Hasher) {
let ty_id = ::core::any::TypeId::of::<Self>();
::core::hash::Hash::hash(&ty_id, &mut state);
::core::hash::Hash::hash(self, &mut state);
}
}
};
}
.into()
}

24
vendor/bevy_macro_utils/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,24 @@
#![forbid(unsafe_code)]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![doc(
html_logo_url = "https://bevyengine.org/assets/icon.png",
html_favicon_url = "https://bevyengine.org/assets/icon.png"
)]
//! A collection of helper types and functions for working on macros within the Bevy ecosystem.
extern crate alloc;
extern crate proc_macro;
mod attrs;
mod bevy_manifest;
pub mod fq_std;
mod label;
mod shape;
mod symbol;
pub use attrs::*;
pub use bevy_manifest::*;
pub use label::*;
pub use shape::*;
pub use symbol::*;

24
vendor/bevy_macro_utils/src/shape.rs vendored Normal file
View File

@@ -0,0 +1,24 @@
use proc_macro::Span;
use syn::{punctuated::Punctuated, token::Comma, Data, DataStruct, Error, Field, Fields};
/// Get the fields of a data structure if that structure is a struct with named fields;
/// otherwise, return a compile error that points to the site of the macro invocation.
pub fn get_struct_fields(data: &Data) -> syn::Result<&Punctuated<Field, Comma>> {
match data {
Data::Struct(DataStruct {
fields: Fields::Named(fields),
..
}) => Ok(&fields.named),
Data::Struct(DataStruct {
fields: Fields::Unnamed(fields),
..
}) => Ok(&fields.unnamed),
_ => Err(Error::new(
// This deliberately points to the call site rather than the structure
// body; marking the entire body as the source of the error makes it
// impossible to figure out which `derive` has a problem.
Span::call_site().into(),
"Only structs are supported",
)),
}
}

36
vendor/bevy_macro_utils/src/symbol.rs vendored Normal file
View File

@@ -0,0 +1,36 @@
use core::fmt::{self, Display};
use syn::{Ident, Path};
/// A single named value, representable as a [string](str).
#[derive(Copy, Clone)]
pub struct Symbol(pub &'static str);
impl PartialEq<Symbol> for Ident {
fn eq(&self, word: &Symbol) -> bool {
self == word.0
}
}
impl<'a> PartialEq<Symbol> for &'a Ident {
fn eq(&self, word: &Symbol) -> bool {
*self == word.0
}
}
impl PartialEq<Symbol> for Path {
fn eq(&self, word: &Symbol) -> bool {
self.is_ident(word.0)
}
}
impl<'a> PartialEq<Symbol> for &'a Path {
fn eq(&self, word: &Symbol) -> bool {
self.is_ident(word.0)
}
}
impl Display for Symbol {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(self.0)
}
}