mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
Simplify design for *Label
s (#4957)
# Objective - Closes #4954 - Reduce the complexity of the `{System, App, *}Label` APIs. ## Solution For the sake of brevity I will only refer to `SystemLabel`, but everything applies to all of the other label types as well. - Add `SystemLabelId`, a lightweight, `copy` struct. - Convert custom types into `SystemLabelId` using the trait `SystemLabel`. ## Changelog - String literals implement `SystemLabel` for now, but this should be changed with #4409 . ## Migration Guide - Any previous use of `Box<dyn SystemLabel>` should be replaced with `SystemLabelId`. - `AsSystemLabel` trait has been modified. - No more output generics. - Method `as_system_label` now returns `SystemLabelId`, removing an unnecessary level of indirection. - If you *need* a label that is determined at runtime, you can use `Box::leak`. Not recommended. ## Questions for later * Should we generate a `Debug` impl along with `#[derive(*Label)]`? * Should we rename `as_str()`? * Should we remove the extra derives (such as `Hash`) from builtin `*Label` types? * Should we automatically derive types like `Clone, Copy, PartialEq, Eq`? * More-ergonomic comparisons between `Label` and `LabelId`. * Move `Dyn{Eq, Hash,Clone}` somewhere else. * Some API to make interning dynamic labels easier. * Optimize string representation * Empty string for unit structs -- no debug info but faster comparisons * Don't show enum types -- same tradeoffs as asbove.
This commit is contained in:
parent
234e5af882
commit
c43295af80
15 changed files with 309 additions and 318 deletions
|
@ -63,11 +63,18 @@ pub fn build_schedule(criterion: &mut Criterion) {
|
||||||
|
|
||||||
// Use multiple different kinds of label to ensure that dynamic dispatch
|
// Use multiple different kinds of label to ensure that dynamic dispatch
|
||||||
// doesn't somehow get optimized away.
|
// doesn't somehow get optimized away.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, SystemLabel)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
struct NumLabel(usize);
|
struct NumLabel(usize);
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, SystemLabel)]
|
#[derive(Debug, Clone, Copy, SystemLabel)]
|
||||||
struct DummyLabel;
|
struct DummyLabel;
|
||||||
|
|
||||||
|
impl SystemLabel for NumLabel {
|
||||||
|
fn as_str(&self) -> &'static str {
|
||||||
|
let s = self.0.to_string();
|
||||||
|
Box::leak(s.into_boxed_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut group = criterion.benchmark_group("build_schedule");
|
let mut group = criterion.benchmark_group("build_schedule");
|
||||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||||
group.measurement_time(std::time::Duration::from_secs(15));
|
group.measurement_time(std::time::Duration::from_secs(15));
|
||||||
|
@ -75,7 +82,10 @@ pub fn build_schedule(criterion: &mut Criterion) {
|
||||||
// Method: generate a set of `graph_size` systems which have a One True Ordering.
|
// Method: generate a set of `graph_size` systems which have a One True Ordering.
|
||||||
// Add system to the stage with full constraints. Hopefully this should be maximimally
|
// Add system to the stage with full constraints. Hopefully this should be maximimally
|
||||||
// difficult for bevy to figure out.
|
// difficult for bevy to figure out.
|
||||||
let labels: Vec<_> = (0..1000).map(NumLabel).collect();
|
// Also, we are performing the `as_label` operation outside of the loop since that
|
||||||
|
// requires an allocation and a leak. This is not something that would be necessary in a
|
||||||
|
// real scenario, just a contrivance for the benchmark.
|
||||||
|
let labels: Vec<_> = (0..1000).map(|i| NumLabel(i).as_label()).collect();
|
||||||
|
|
||||||
// Benchmark graphs of different sizes.
|
// Benchmark graphs of different sizes.
|
||||||
for graph_size in [100, 500, 1000] {
|
for graph_size in [100, 500, 1000] {
|
||||||
|
|
|
@ -56,7 +56,7 @@ pub struct App {
|
||||||
pub runner: Box<dyn Fn(App)>,
|
pub runner: Box<dyn Fn(App)>,
|
||||||
/// A container of [`Stage`]s set to be run in a linear order.
|
/// A container of [`Stage`]s set to be run in a linear order.
|
||||||
pub schedule: Schedule,
|
pub schedule: Schedule,
|
||||||
sub_apps: HashMap<Box<dyn AppLabel>, SubApp>,
|
sub_apps: HashMap<AppLabelId, SubApp>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Each `SubApp` has its own [`Schedule`] and [`World`], enabling a separation of concerns.
|
/// Each `SubApp` has its own [`Schedule`] and [`World`], enabling a separation of concerns.
|
||||||
|
@ -879,7 +879,7 @@ impl App {
|
||||||
sub_app_runner: impl Fn(&mut World, &mut App) + 'static,
|
sub_app_runner: impl Fn(&mut World, &mut App) + 'static,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
self.sub_apps.insert(
|
self.sub_apps.insert(
|
||||||
Box::new(label),
|
label.as_label(),
|
||||||
SubApp {
|
SubApp {
|
||||||
app,
|
app,
|
||||||
runner: Box::new(sub_app_runner),
|
runner: Box::new(sub_app_runner),
|
||||||
|
@ -896,15 +896,16 @@ impl App {
|
||||||
pub fn sub_app_mut(&mut self, label: impl AppLabel) -> &mut App {
|
pub fn sub_app_mut(&mut self, label: impl AppLabel) -> &mut App {
|
||||||
match self.get_sub_app_mut(label) {
|
match self.get_sub_app_mut(label) {
|
||||||
Ok(app) => app,
|
Ok(app) => app,
|
||||||
Err(label) => panic!("Sub-App with label '{:?}' does not exist", label),
|
Err(label) => panic!("Sub-App with label '{:?}' does not exist", label.as_str()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves a `SubApp` inside this [`App`] with the given label, if it exists. Otherwise returns
|
/// Retrieves a `SubApp` inside this [`App`] with the given label, if it exists. Otherwise returns
|
||||||
/// an [`Err`] containing the given label.
|
/// an [`Err`] containing the given label.
|
||||||
pub fn get_sub_app_mut(&mut self, label: impl AppLabel) -> Result<&mut App, impl AppLabel> {
|
pub fn get_sub_app_mut(&mut self, label: impl AppLabel) -> Result<&mut App, AppLabelId> {
|
||||||
|
let label = label.as_label();
|
||||||
self.sub_apps
|
self.sub_apps
|
||||||
.get_mut((&label) as &dyn AppLabel)
|
.get_mut(&label)
|
||||||
.map(|sub_app| &mut sub_app.app)
|
.map(|sub_app| &mut sub_app.app)
|
||||||
.ok_or(label)
|
.ok_or(label)
|
||||||
}
|
}
|
||||||
|
@ -917,7 +918,7 @@ impl App {
|
||||||
pub fn sub_app(&self, label: impl AppLabel) -> &App {
|
pub fn sub_app(&self, label: impl AppLabel) -> &App {
|
||||||
match self.get_sub_app(label) {
|
match self.get_sub_app(label) {
|
||||||
Ok(app) => app,
|
Ok(app) => app,
|
||||||
Err(label) => panic!("Sub-App with label '{:?}' does not exist", label),
|
Err(label) => panic!("Sub-App with label '{:?}' does not exist", label.as_str()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -925,7 +926,7 @@ impl App {
|
||||||
/// an [`Err`] containing the given label.
|
/// an [`Err`] containing the given label.
|
||||||
pub fn get_sub_app(&self, label: impl AppLabel) -> Result<&App, impl AppLabel> {
|
pub fn get_sub_app(&self, label: impl AppLabel) -> Result<&App, impl AppLabel> {
|
||||||
self.sub_apps
|
self.sub_apps
|
||||||
.get((&label) as &dyn AppLabel)
|
.get(&label.as_label())
|
||||||
.map(|sub_app| &sub_app.app)
|
.map(|sub_app| &sub_app.app)
|
||||||
.ok_or(label)
|
.ok_or(label)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,3 @@ define_label!(StageLabel);
|
||||||
define_label!(SystemLabel);
|
define_label!(SystemLabel);
|
||||||
define_label!(AmbiguitySetLabel);
|
define_label!(AmbiguitySetLabel);
|
||||||
define_label!(RunCriteriaLabel);
|
define_label!(RunCriteriaLabel);
|
||||||
|
|
||||||
pub(crate) type BoxedStageLabel = Box<dyn StageLabel>;
|
|
||||||
pub(crate) type BoxedSystemLabel = Box<dyn SystemLabel>;
|
|
||||||
pub(crate) type BoxedAmbiguitySetLabel = Box<dyn AmbiguitySetLabel>;
|
|
||||||
pub(crate) type BoxedRunCriteriaLabel = Box<dyn RunCriteriaLabel>;
|
|
||||||
|
|
|
@ -38,8 +38,8 @@ use bevy_utils::HashMap;
|
||||||
/// runs indefinitely.
|
/// runs indefinitely.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Schedule {
|
pub struct Schedule {
|
||||||
stages: HashMap<BoxedStageLabel, Box<dyn Stage>>,
|
stages: HashMap<StageLabelId, Box<dyn Stage>>,
|
||||||
stage_order: Vec<BoxedStageLabel>,
|
stage_order: Vec<StageLabelId>,
|
||||||
run_criteria: BoxedRunCriteria,
|
run_criteria: BoxedRunCriteria,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,9 +109,9 @@ impl Schedule {
|
||||||
/// schedule.add_stage("my_stage", SystemStage::parallel());
|
/// schedule.add_stage("my_stage", SystemStage::parallel());
|
||||||
/// ```
|
/// ```
|
||||||
pub fn add_stage<S: Stage>(&mut self, label: impl StageLabel, stage: S) -> &mut Self {
|
pub fn add_stage<S: Stage>(&mut self, label: impl StageLabel, stage: S) -> &mut Self {
|
||||||
let label: Box<dyn StageLabel> = Box::new(label);
|
let label = label.as_label();
|
||||||
self.stage_order.push(label.clone());
|
self.stage_order.push(label);
|
||||||
let prev = self.stages.insert(label.clone(), Box::new(stage));
|
let prev = self.stages.insert(label, Box::new(stage));
|
||||||
assert!(prev.is_none(), "Stage already exists: {:?}.", label);
|
assert!(prev.is_none(), "Stage already exists: {:?}.", label);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -133,18 +133,18 @@ impl Schedule {
|
||||||
label: impl StageLabel,
|
label: impl StageLabel,
|
||||||
stage: S,
|
stage: S,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
let label: Box<dyn StageLabel> = Box::new(label);
|
let label = label.as_label();
|
||||||
let target = &target as &dyn StageLabel;
|
let target = target.as_label();
|
||||||
let target_index = self
|
let target_index = self
|
||||||
.stage_order
|
.stage_order
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.find(|(_i, stage_label)| &***stage_label == target)
|
.find(|(_i, stage_label)| **stage_label == target)
|
||||||
.map(|(i, _)| i)
|
.map(|(i, _)| i)
|
||||||
.unwrap_or_else(|| panic!("Target stage does not exist: {:?}.", target));
|
.unwrap_or_else(|| panic!("Target stage does not exist: {:?}.", target));
|
||||||
|
|
||||||
self.stage_order.insert(target_index + 1, label.clone());
|
self.stage_order.insert(target_index + 1, label);
|
||||||
let prev = self.stages.insert(label.clone(), Box::new(stage));
|
let prev = self.stages.insert(label, Box::new(stage));
|
||||||
assert!(prev.is_none(), "Stage already exists: {:?}.", label);
|
assert!(prev.is_none(), "Stage already exists: {:?}.", label);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -167,18 +167,18 @@ impl Schedule {
|
||||||
label: impl StageLabel,
|
label: impl StageLabel,
|
||||||
stage: S,
|
stage: S,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
let label: Box<dyn StageLabel> = Box::new(label);
|
let label = label.as_label();
|
||||||
let target = &target as &dyn StageLabel;
|
let target = target.as_label();
|
||||||
let target_index = self
|
let target_index = self
|
||||||
.stage_order
|
.stage_order
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.find(|(_i, stage_label)| &***stage_label == target)
|
.find(|(_i, stage_label)| **stage_label == target)
|
||||||
.map(|(i, _)| i)
|
.map(|(i, _)| i)
|
||||||
.unwrap_or_else(|| panic!("Target stage does not exist: {:?}.", target));
|
.unwrap_or_else(|| panic!("Target stage does not exist: {:?}.", target));
|
||||||
|
|
||||||
self.stage_order.insert(target_index, label.clone());
|
self.stage_order.insert(target_index, label);
|
||||||
let prev = self.stages.insert(label.clone(), Box::new(stage));
|
let prev = self.stages.insert(label, Box::new(stage));
|
||||||
assert!(prev.is_none(), "Stage already exists: {:?}.", label);
|
assert!(prev.is_none(), "Stage already exists: {:?}.", label);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -213,7 +213,7 @@ impl Schedule {
|
||||||
|
|
||||||
let stage = self
|
let stage = self
|
||||||
.get_stage_mut::<SystemStage>(&stage_label)
|
.get_stage_mut::<SystemStage>(&stage_label)
|
||||||
.unwrap_or_else(move || stage_not_found(&stage_label));
|
.unwrap_or_else(move || stage_not_found(&stage_label.as_label()));
|
||||||
stage.add_system(system);
|
stage.add_system(system);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -282,7 +282,10 @@ impl Schedule {
|
||||||
func: F,
|
func: F,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
let stage = self.get_stage_mut::<T>(&label).unwrap_or_else(move || {
|
let stage = self.get_stage_mut::<T>(&label).unwrap_or_else(move || {
|
||||||
panic!("stage '{:?}' does not exist or is the wrong type", label)
|
panic!(
|
||||||
|
"stage '{:?}' does not exist or is the wrong type",
|
||||||
|
label.as_label()
|
||||||
|
)
|
||||||
});
|
});
|
||||||
func(stage);
|
func(stage);
|
||||||
self
|
self
|
||||||
|
@ -305,7 +308,7 @@ impl Schedule {
|
||||||
/// ```
|
/// ```
|
||||||
pub fn get_stage<T: Stage>(&self, label: &dyn StageLabel) -> Option<&T> {
|
pub fn get_stage<T: Stage>(&self, label: &dyn StageLabel) -> Option<&T> {
|
||||||
self.stages
|
self.stages
|
||||||
.get(label)
|
.get(&label.as_label())
|
||||||
.and_then(|stage| stage.downcast_ref::<T>())
|
.and_then(|stage| stage.downcast_ref::<T>())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,7 +329,7 @@ impl Schedule {
|
||||||
/// ```
|
/// ```
|
||||||
pub fn get_stage_mut<T: Stage>(&mut self, label: &dyn StageLabel) -> Option<&mut T> {
|
pub fn get_stage_mut<T: Stage>(&mut self, label: &dyn StageLabel) -> Option<&mut T> {
|
||||||
self.stages
|
self.stages
|
||||||
.get_mut(label)
|
.get_mut(&label.as_label())
|
||||||
.and_then(|stage| stage.downcast_mut::<T>())
|
.and_then(|stage| stage.downcast_mut::<T>())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,10 +344,10 @@ impl Schedule {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterates over all of schedule's stages and their labels, in execution order.
|
/// Iterates over all of schedule's stages and their labels, in execution order.
|
||||||
pub fn iter_stages(&self) -> impl Iterator<Item = (&dyn StageLabel, &dyn Stage)> {
|
pub fn iter_stages(&self) -> impl Iterator<Item = (StageLabelId, &dyn Stage)> {
|
||||||
self.stage_order
|
self.stage_order
|
||||||
.iter()
|
.iter()
|
||||||
.map(move |label| (&**label, &*self.stages[label]))
|
.map(move |&label| (label, &*self.stages[&label]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
schedule::{BoxedRunCriteriaLabel, GraphNode, RunCriteriaLabel},
|
schedule::{GraphNode, RunCriteriaLabel, RunCriteriaLabelId},
|
||||||
system::{BoxedSystem, IntoSystem, Local},
|
system::{BoxedSystem, IntoSystem, Local},
|
||||||
world::World,
|
world::World,
|
||||||
};
|
};
|
||||||
|
@ -104,9 +104,9 @@ pub(crate) enum RunCriteriaInner {
|
||||||
pub(crate) struct RunCriteriaContainer {
|
pub(crate) struct RunCriteriaContainer {
|
||||||
pub(crate) should_run: ShouldRun,
|
pub(crate) should_run: ShouldRun,
|
||||||
pub(crate) inner: RunCriteriaInner,
|
pub(crate) inner: RunCriteriaInner,
|
||||||
pub(crate) label: Option<BoxedRunCriteriaLabel>,
|
pub(crate) label: Option<RunCriteriaLabelId>,
|
||||||
pub(crate) before: Vec<BoxedRunCriteriaLabel>,
|
pub(crate) before: Vec<RunCriteriaLabelId>,
|
||||||
pub(crate) after: Vec<BoxedRunCriteriaLabel>,
|
pub(crate) after: Vec<RunCriteriaLabelId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RunCriteriaContainer {
|
impl RunCriteriaContainer {
|
||||||
|
@ -139,7 +139,7 @@ impl RunCriteriaContainer {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GraphNode for RunCriteriaContainer {
|
impl GraphNode for RunCriteriaContainer {
|
||||||
type Label = BoxedRunCriteriaLabel;
|
type Label = RunCriteriaLabelId;
|
||||||
|
|
||||||
fn name(&self) -> Cow<'static, str> {
|
fn name(&self) -> Cow<'static, str> {
|
||||||
match &self.inner {
|
match &self.inner {
|
||||||
|
@ -148,7 +148,7 @@ impl GraphNode for RunCriteriaContainer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn labels(&self) -> &[BoxedRunCriteriaLabel] {
|
fn labels(&self) -> &[RunCriteriaLabelId] {
|
||||||
if let Some(ref label) = self.label {
|
if let Some(ref label) = self.label {
|
||||||
std::slice::from_ref(label)
|
std::slice::from_ref(label)
|
||||||
} else {
|
} else {
|
||||||
|
@ -156,18 +156,18 @@ impl GraphNode for RunCriteriaContainer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn before(&self) -> &[BoxedRunCriteriaLabel] {
|
fn before(&self) -> &[RunCriteriaLabelId] {
|
||||||
&self.before
|
&self.before
|
||||||
}
|
}
|
||||||
|
|
||||||
fn after(&self) -> &[BoxedRunCriteriaLabel] {
|
fn after(&self) -> &[RunCriteriaLabelId] {
|
||||||
&self.after
|
&self.after
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum RunCriteriaDescriptorOrLabel {
|
pub enum RunCriteriaDescriptorOrLabel {
|
||||||
Descriptor(RunCriteriaDescriptor),
|
Descriptor(RunCriteriaDescriptor),
|
||||||
Label(BoxedRunCriteriaLabel),
|
Label(RunCriteriaLabelId),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
|
@ -178,10 +178,10 @@ pub(crate) enum DuplicateLabelStrategy {
|
||||||
|
|
||||||
pub struct RunCriteriaDescriptor {
|
pub struct RunCriteriaDescriptor {
|
||||||
pub(crate) system: RunCriteriaSystem,
|
pub(crate) system: RunCriteriaSystem,
|
||||||
pub(crate) label: Option<BoxedRunCriteriaLabel>,
|
pub(crate) label: Option<RunCriteriaLabelId>,
|
||||||
pub(crate) duplicate_label_strategy: DuplicateLabelStrategy,
|
pub(crate) duplicate_label_strategy: DuplicateLabelStrategy,
|
||||||
pub(crate) before: Vec<BoxedRunCriteriaLabel>,
|
pub(crate) before: Vec<RunCriteriaLabelId>,
|
||||||
pub(crate) after: Vec<BoxedRunCriteriaLabel>,
|
pub(crate) after: Vec<RunCriteriaLabelId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) enum RunCriteriaSystem {
|
pub(crate) enum RunCriteriaSystem {
|
||||||
|
@ -222,12 +222,12 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<L> IntoRunCriteria<BoxedRunCriteriaLabel> for L
|
impl<L> IntoRunCriteria<RunCriteriaLabelId> for L
|
||||||
where
|
where
|
||||||
L: RunCriteriaLabel,
|
L: RunCriteriaLabel,
|
||||||
{
|
{
|
||||||
fn into(self) -> RunCriteriaDescriptorOrLabel {
|
fn into(self) -> RunCriteriaDescriptorOrLabel {
|
||||||
RunCriteriaDescriptorOrLabel::Label(Box::new(self))
|
RunCriteriaDescriptorOrLabel::Label(self.as_label())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,24 +254,24 @@ pub trait RunCriteriaDescriptorCoercion<Param> {
|
||||||
|
|
||||||
impl RunCriteriaDescriptorCoercion<()> for RunCriteriaDescriptor {
|
impl RunCriteriaDescriptorCoercion<()> for RunCriteriaDescriptor {
|
||||||
fn label(mut self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor {
|
fn label(mut self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor {
|
||||||
self.label = Some(Box::new(label));
|
self.label = Some(label.as_label());
|
||||||
self.duplicate_label_strategy = DuplicateLabelStrategy::Panic;
|
self.duplicate_label_strategy = DuplicateLabelStrategy::Panic;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn label_discard_if_duplicate(mut self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor {
|
fn label_discard_if_duplicate(mut self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor {
|
||||||
self.label = Some(Box::new(label));
|
self.label = Some(label.as_label());
|
||||||
self.duplicate_label_strategy = DuplicateLabelStrategy::Discard;
|
self.duplicate_label_strategy = DuplicateLabelStrategy::Discard;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn before(mut self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor {
|
fn before(mut self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor {
|
||||||
self.before.push(Box::new(label));
|
self.before.push(label.as_label());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn after(mut self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor {
|
fn after(mut self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor {
|
||||||
self.after.push(Box::new(label));
|
self.after.push(label.as_label());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -327,7 +327,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RunCriteria {
|
pub struct RunCriteria {
|
||||||
label: BoxedRunCriteriaLabel,
|
label: RunCriteriaLabelId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RunCriteria {
|
impl RunCriteria {
|
||||||
|
@ -342,7 +342,7 @@ impl RunCriteria {
|
||||||
label: None,
|
label: None,
|
||||||
duplicate_label_strategy: DuplicateLabelStrategy::Panic,
|
duplicate_label_strategy: DuplicateLabelStrategy::Panic,
|
||||||
before: vec![],
|
before: vec![],
|
||||||
after: vec![Box::new(label)],
|
after: vec![label.as_label()],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,11 +4,11 @@ use crate::{
|
||||||
prelude::IntoSystem,
|
prelude::IntoSystem,
|
||||||
schedule::{
|
schedule::{
|
||||||
graph_utils::{self, DependencyGraphError},
|
graph_utils::{self, DependencyGraphError},
|
||||||
BoxedRunCriteria, BoxedRunCriteriaLabel, BoxedSystemLabel, DuplicateLabelStrategy,
|
BoxedRunCriteria, DuplicateLabelStrategy, ExclusiveSystemContainer, GraphNode,
|
||||||
ExclusiveSystemContainer, GraphNode, InsertionPoint, ParallelExecutor,
|
InsertionPoint, ParallelExecutor, ParallelSystemContainer, ParallelSystemExecutor,
|
||||||
ParallelSystemContainer, ParallelSystemExecutor, RunCriteriaContainer,
|
RunCriteriaContainer, RunCriteriaDescriptor, RunCriteriaDescriptorOrLabel,
|
||||||
RunCriteriaDescriptor, RunCriteriaDescriptorOrLabel, RunCriteriaInner, ShouldRun,
|
RunCriteriaInner, RunCriteriaLabelId, ShouldRun, SingleThreadedExecutor, SystemContainer,
|
||||||
SingleThreadedExecutor, SystemContainer, SystemDescriptor, SystemSet,
|
SystemDescriptor, SystemLabelId, SystemSet,
|
||||||
},
|
},
|
||||||
world::{World, WorldId},
|
world::{World, WorldId},
|
||||||
};
|
};
|
||||||
|
@ -171,7 +171,7 @@ impl SystemStage {
|
||||||
container.run_criteria_label = Some(label);
|
container.run_criteria_label = Some(label);
|
||||||
}
|
}
|
||||||
Some(RunCriteriaDescriptorOrLabel::Descriptor(criteria_descriptor)) => {
|
Some(RunCriteriaDescriptorOrLabel::Descriptor(criteria_descriptor)) => {
|
||||||
container.run_criteria_label = criteria_descriptor.label.clone();
|
container.run_criteria_label = criteria_descriptor.label;
|
||||||
container.run_criteria_index =
|
container.run_criteria_index =
|
||||||
Some(self.add_run_criteria_internal(criteria_descriptor));
|
Some(self.add_run_criteria_internal(criteria_descriptor));
|
||||||
}
|
}
|
||||||
|
@ -205,7 +205,7 @@ impl SystemStage {
|
||||||
container.run_criteria_label = Some(label);
|
container.run_criteria_label = Some(label);
|
||||||
}
|
}
|
||||||
Some(RunCriteriaDescriptorOrLabel::Descriptor(criteria_descriptor)) => {
|
Some(RunCriteriaDescriptorOrLabel::Descriptor(criteria_descriptor)) => {
|
||||||
container.run_criteria_label = criteria_descriptor.label.clone();
|
container.run_criteria_label = criteria_descriptor.label;
|
||||||
container.run_criteria_index =
|
container.run_criteria_index =
|
||||||
Some(self.add_run_criteria_internal(criteria_descriptor));
|
Some(self.add_run_criteria_internal(criteria_descriptor));
|
||||||
}
|
}
|
||||||
|
@ -301,11 +301,11 @@ impl SystemStage {
|
||||||
match system {
|
match system {
|
||||||
SystemDescriptor::Exclusive(descriptor) => {
|
SystemDescriptor::Exclusive(descriptor) => {
|
||||||
descriptor.run_criteria =
|
descriptor.run_criteria =
|
||||||
Some(RunCriteriaDescriptorOrLabel::Label(label.clone()));
|
Some(RunCriteriaDescriptorOrLabel::Label(label));
|
||||||
}
|
}
|
||||||
SystemDescriptor::Parallel(descriptor) => {
|
SystemDescriptor::Parallel(descriptor) => {
|
||||||
descriptor.run_criteria =
|
descriptor.run_criteria =
|
||||||
Some(RunCriteriaDescriptorOrLabel::Label(label.clone()));
|
Some(RunCriteriaDescriptorOrLabel::Label(label));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -372,7 +372,7 @@ impl SystemStage {
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.filter_map(|(index, mut container)| {
|
.filter_map(|(index, mut container)| {
|
||||||
let new_index = index - filtered_criteria;
|
let new_index = index - filtered_criteria;
|
||||||
let label = container.label.clone();
|
let label = container.label;
|
||||||
if let Some(strategy) = uninitialized_criteria.get(&index) {
|
if let Some(strategy) = uninitialized_criteria.get(&index) {
|
||||||
if let Some(ref label) = label {
|
if let Some(ref label) = label {
|
||||||
if let Some(duplicate_index) = criteria_labels.get(label) {
|
if let Some(duplicate_index) = criteria_labels.get(label) {
|
||||||
|
@ -621,10 +621,8 @@ impl SystemStage {
|
||||||
/// Returns a map of run criteria labels to their indices.
|
/// Returns a map of run criteria labels to their indices.
|
||||||
fn process_run_criteria(
|
fn process_run_criteria(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> Result<
|
) -> Result<HashMap<RunCriteriaLabelId, usize>, DependencyGraphError<HashSet<RunCriteriaLabelId>>>
|
||||||
HashMap<BoxedRunCriteriaLabel, usize>,
|
{
|
||||||
DependencyGraphError<HashSet<BoxedRunCriteriaLabel>>,
|
|
||||||
> {
|
|
||||||
let graph = graph_utils::build_dependency_graph(&self.run_criteria);
|
let graph = graph_utils::build_dependency_graph(&self.run_criteria);
|
||||||
let order = graph_utils::topological_order(&graph)?;
|
let order = graph_utils::topological_order(&graph)?;
|
||||||
let mut order_inverted = order.iter().enumerate().collect::<Vec<_>>();
|
let mut order_inverted = order.iter().enumerate().collect::<Vec<_>>();
|
||||||
|
@ -637,7 +635,7 @@ impl SystemStage {
|
||||||
criteria
|
criteria
|
||||||
.label
|
.label
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|label| (label.clone(), order_inverted[index].0))
|
.map(|&label| (label, order_inverted[index].0))
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
for criteria in &mut self.run_criteria {
|
for criteria in &mut self.run_criteria {
|
||||||
|
@ -680,8 +678,8 @@ impl SystemStage {
|
||||||
/// and run criteria.
|
/// and run criteria.
|
||||||
fn process_systems(
|
fn process_systems(
|
||||||
systems: &mut Vec<impl SystemContainer>,
|
systems: &mut Vec<impl SystemContainer>,
|
||||||
run_criteria_labels: &HashMap<BoxedRunCriteriaLabel, usize>,
|
run_criteria_labels: &HashMap<RunCriteriaLabelId, usize>,
|
||||||
) -> Result<(), DependencyGraphError<HashSet<BoxedSystemLabel>>> {
|
) -> Result<(), DependencyGraphError<HashSet<SystemLabelId>>> {
|
||||||
let mut graph = graph_utils::build_dependency_graph(systems);
|
let mut graph = graph_utils::build_dependency_graph(systems);
|
||||||
let order = graph_utils::topological_order(&graph)?;
|
let order = graph_utils::topological_order(&graph)?;
|
||||||
let mut order_inverted = order.iter().enumerate().collect::<Vec<_>>();
|
let mut order_inverted = order.iter().enumerate().collect::<Vec<_>>();
|
||||||
|
@ -974,9 +972,9 @@ impl Stage for SystemStage {
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
schedule::{
|
schedule::{
|
||||||
BoxedSystemLabel, ExclusiveSystemDescriptorCoercion, ParallelSystemDescriptorCoercion,
|
ExclusiveSystemDescriptorCoercion, ParallelSystemDescriptorCoercion, RunCriteria,
|
||||||
RunCriteria, RunCriteriaDescriptorCoercion, ShouldRun, SingleThreadedExecutor, Stage,
|
RunCriteriaDescriptorCoercion, ShouldRun, SingleThreadedExecutor, Stage, SystemLabel,
|
||||||
SystemSet, SystemStage,
|
SystemLabelId, SystemSet, SystemStage,
|
||||||
},
|
},
|
||||||
system::{In, IntoExclusiveSystem, Local, Query, ResMut},
|
system::{In, IntoExclusiveSystem, Local, Query, ResMut},
|
||||||
world::World,
|
world::World,
|
||||||
|
@ -1609,23 +1607,21 @@ mod tests {
|
||||||
|
|
||||||
fn find_ambiguities_first_str_labels(
|
fn find_ambiguities_first_str_labels(
|
||||||
systems: &[impl SystemContainer],
|
systems: &[impl SystemContainer],
|
||||||
) -> Vec<(BoxedSystemLabel, BoxedSystemLabel)> {
|
) -> Vec<(SystemLabelId, SystemLabelId)> {
|
||||||
find_ambiguities(systems)
|
find_ambiguities(systems)
|
||||||
.drain(..)
|
.drain(..)
|
||||||
.map(|(index_a, index_b, _conflicts)| {
|
.map(|(index_a, index_b, _conflicts)| {
|
||||||
(
|
(
|
||||||
systems[index_a]
|
*systems[index_a]
|
||||||
.labels()
|
.labels()
|
||||||
.iter()
|
.iter()
|
||||||
.find(|a| (&***a).type_id() == std::any::TypeId::of::<&str>())
|
.find(|a| a.type_id() == std::any::TypeId::of::<&str>())
|
||||||
.unwrap()
|
.unwrap(),
|
||||||
.clone(),
|
*systems[index_b]
|
||||||
systems[index_b]
|
|
||||||
.labels()
|
.labels()
|
||||||
.iter()
|
.iter()
|
||||||
.find(|a| (&***a).type_id() == std::any::TypeId::of::<&str>())
|
.find(|a| a.type_id() == std::any::TypeId::of::<&str>())
|
||||||
.unwrap()
|
.unwrap(),
|
||||||
.clone(),
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
|
@ -1657,8 +1653,8 @@ mod tests {
|
||||||
stage.rebuild_orders_and_dependencies();
|
stage.rebuild_orders_and_dependencies();
|
||||||
let ambiguities = find_ambiguities_first_str_labels(&stage.parallel);
|
let ambiguities = find_ambiguities_first_str_labels(&stage.parallel);
|
||||||
assert!(
|
assert!(
|
||||||
ambiguities.contains(&(Box::new("1"), Box::new("4")))
|
ambiguities.contains(&("1".as_label(), "4".as_label()))
|
||||||
|| ambiguities.contains(&(Box::new("4"), Box::new("1")))
|
|| ambiguities.contains(&("4".as_label(), "1".as_label()))
|
||||||
);
|
);
|
||||||
assert_eq!(ambiguities.len(), 1);
|
assert_eq!(ambiguities.len(), 1);
|
||||||
|
|
||||||
|
@ -1672,8 +1668,8 @@ mod tests {
|
||||||
stage.rebuild_orders_and_dependencies();
|
stage.rebuild_orders_and_dependencies();
|
||||||
let ambiguities = find_ambiguities_first_str_labels(&stage.parallel);
|
let ambiguities = find_ambiguities_first_str_labels(&stage.parallel);
|
||||||
assert!(
|
assert!(
|
||||||
ambiguities.contains(&(Box::new("1"), Box::new("4")))
|
ambiguities.contains(&("1".as_label(), "4".as_label()))
|
||||||
|| ambiguities.contains(&(Box::new("4"), Box::new("1")))
|
|| ambiguities.contains(&("4".as_label(), "1".as_label()))
|
||||||
);
|
);
|
||||||
assert_eq!(ambiguities.len(), 1);
|
assert_eq!(ambiguities.len(), 1);
|
||||||
|
|
||||||
|
@ -1697,12 +1693,12 @@ mod tests {
|
||||||
stage.rebuild_orders_and_dependencies();
|
stage.rebuild_orders_and_dependencies();
|
||||||
let ambiguities = find_ambiguities_first_str_labels(&stage.parallel);
|
let ambiguities = find_ambiguities_first_str_labels(&stage.parallel);
|
||||||
assert!(
|
assert!(
|
||||||
ambiguities.contains(&(Box::new("0"), Box::new("3")))
|
ambiguities.contains(&("0".as_label(), "3".as_label()))
|
||||||
|| ambiguities.contains(&(Box::new("3"), Box::new("0")))
|
|| ambiguities.contains(&("3".as_label(), "0".as_label()))
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
ambiguities.contains(&(Box::new("1"), Box::new("4")))
|
ambiguities.contains(&("1".as_label(), "4".as_label()))
|
||||||
|| ambiguities.contains(&(Box::new("4"), Box::new("1")))
|
|| ambiguities.contains(&("4".as_label(), "1".as_label()))
|
||||||
);
|
);
|
||||||
assert_eq!(ambiguities.len(), 2);
|
assert_eq!(ambiguities.len(), 2);
|
||||||
|
|
||||||
|
@ -1716,8 +1712,8 @@ mod tests {
|
||||||
stage.rebuild_orders_and_dependencies();
|
stage.rebuild_orders_and_dependencies();
|
||||||
let ambiguities = find_ambiguities_first_str_labels(&stage.parallel);
|
let ambiguities = find_ambiguities_first_str_labels(&stage.parallel);
|
||||||
assert!(
|
assert!(
|
||||||
ambiguities.contains(&(Box::new("0"), Box::new("3")))
|
ambiguities.contains(&("0".as_label(), "3".as_label()))
|
||||||
|| ambiguities.contains(&(Box::new("3"), Box::new("0")))
|
|| ambiguities.contains(&("3".as_label(), "0".as_label()))
|
||||||
);
|
);
|
||||||
assert_eq!(ambiguities.len(), 1);
|
assert_eq!(ambiguities.len(), 1);
|
||||||
|
|
||||||
|
@ -1729,8 +1725,8 @@ mod tests {
|
||||||
stage.rebuild_orders_and_dependencies();
|
stage.rebuild_orders_and_dependencies();
|
||||||
let ambiguities = find_ambiguities_first_str_labels(&stage.parallel);
|
let ambiguities = find_ambiguities_first_str_labels(&stage.parallel);
|
||||||
assert!(
|
assert!(
|
||||||
ambiguities.contains(&(Box::new("0"), Box::new("1")))
|
ambiguities.contains(&("0".as_label(), "1".as_label()))
|
||||||
|| ambiguities.contains(&(Box::new("1"), Box::new("0")))
|
|| ambiguities.contains(&("1".as_label(), "0".as_label()))
|
||||||
);
|
);
|
||||||
assert_eq!(ambiguities.len(), 1);
|
assert_eq!(ambiguities.len(), 1);
|
||||||
|
|
||||||
|
@ -1742,8 +1738,8 @@ mod tests {
|
||||||
stage.rebuild_orders_and_dependencies();
|
stage.rebuild_orders_and_dependencies();
|
||||||
let ambiguities = find_ambiguities_first_str_labels(&stage.parallel);
|
let ambiguities = find_ambiguities_first_str_labels(&stage.parallel);
|
||||||
assert!(
|
assert!(
|
||||||
ambiguities.contains(&(Box::new("1"), Box::new("2")))
|
ambiguities.contains(&("1".as_label(), "2".as_label()))
|
||||||
|| ambiguities.contains(&(Box::new("2"), Box::new("1")))
|
|| ambiguities.contains(&("2".as_label(), "1".as_label()))
|
||||||
);
|
);
|
||||||
assert_eq!(ambiguities.len(), 1);
|
assert_eq!(ambiguities.len(), 1);
|
||||||
|
|
||||||
|
@ -1756,8 +1752,8 @@ mod tests {
|
||||||
stage.rebuild_orders_and_dependencies();
|
stage.rebuild_orders_and_dependencies();
|
||||||
let ambiguities = find_ambiguities_first_str_labels(&stage.parallel);
|
let ambiguities = find_ambiguities_first_str_labels(&stage.parallel);
|
||||||
assert!(
|
assert!(
|
||||||
ambiguities.contains(&(Box::new("1"), Box::new("2")))
|
ambiguities.contains(&("1".as_label(), "2".as_label()))
|
||||||
|| ambiguities.contains(&(Box::new("2"), Box::new("1")))
|
|| ambiguities.contains(&("2".as_label(), "1".as_label()))
|
||||||
);
|
);
|
||||||
assert_eq!(ambiguities.len(), 1);
|
assert_eq!(ambiguities.len(), 1);
|
||||||
|
|
||||||
|
@ -1780,8 +1776,8 @@ mod tests {
|
||||||
stage.rebuild_orders_and_dependencies();
|
stage.rebuild_orders_and_dependencies();
|
||||||
let ambiguities = find_ambiguities_first_str_labels(&stage.parallel);
|
let ambiguities = find_ambiguities_first_str_labels(&stage.parallel);
|
||||||
assert!(
|
assert!(
|
||||||
ambiguities.contains(&(Box::new("1"), Box::new("2")))
|
ambiguities.contains(&("1".as_label(), "2".as_label()))
|
||||||
|| ambiguities.contains(&(Box::new("2"), Box::new("1")))
|
|| ambiguities.contains(&("2".as_label(), "1".as_label()))
|
||||||
);
|
);
|
||||||
assert_eq!(ambiguities.len(), 1);
|
assert_eq!(ambiguities.len(), 1);
|
||||||
|
|
||||||
|
@ -1810,28 +1806,28 @@ mod tests {
|
||||||
stage.rebuild_orders_and_dependencies();
|
stage.rebuild_orders_and_dependencies();
|
||||||
let ambiguities = find_ambiguities_first_str_labels(&stage.parallel);
|
let ambiguities = find_ambiguities_first_str_labels(&stage.parallel);
|
||||||
assert!(
|
assert!(
|
||||||
ambiguities.contains(&(Box::new("1"), Box::new("2")))
|
ambiguities.contains(&("1".as_label(), "2".as_label()))
|
||||||
|| ambiguities.contains(&(Box::new("2"), Box::new("1")))
|
|| ambiguities.contains(&("2".as_label(), "1".as_label()))
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
ambiguities.contains(&(Box::new("1"), Box::new("3")))
|
ambiguities.contains(&("1".as_label(), "3".as_label()))
|
||||||
|| ambiguities.contains(&(Box::new("3"), Box::new("1")))
|
|| ambiguities.contains(&("3".as_label(), "1".as_label()))
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
ambiguities.contains(&(Box::new("1"), Box::new("4")))
|
ambiguities.contains(&("1".as_label(), "4".as_label()))
|
||||||
|| ambiguities.contains(&(Box::new("4"), Box::new("1")))
|
|| ambiguities.contains(&("4".as_label(), "1".as_label()))
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
ambiguities.contains(&(Box::new("2"), Box::new("3")))
|
ambiguities.contains(&("2".as_label(), "3".as_label()))
|
||||||
|| ambiguities.contains(&(Box::new("3"), Box::new("2")))
|
|| ambiguities.contains(&("3".as_label(), "2".as_label()))
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
ambiguities.contains(&(Box::new("2"), Box::new("4")))
|
ambiguities.contains(&("2".as_label(), "4".as_label()))
|
||||||
|| ambiguities.contains(&(Box::new("4"), Box::new("2")))
|
|| ambiguities.contains(&("4".as_label(), "2".as_label()))
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
ambiguities.contains(&(Box::new("3"), Box::new("4")))
|
ambiguities.contains(&("3".as_label(), "4".as_label()))
|
||||||
|| ambiguities.contains(&(Box::new("4"), Box::new("3")))
|
|| ambiguities.contains(&("4".as_label(), "3".as_label()))
|
||||||
);
|
);
|
||||||
assert_eq!(ambiguities.len(), 6);
|
assert_eq!(ambiguities.len(), 6);
|
||||||
|
|
||||||
|
@ -1891,12 +1887,12 @@ mod tests {
|
||||||
stage.rebuild_orders_and_dependencies();
|
stage.rebuild_orders_and_dependencies();
|
||||||
let ambiguities = find_ambiguities_first_str_labels(&stage.parallel);
|
let ambiguities = find_ambiguities_first_str_labels(&stage.parallel);
|
||||||
assert!(
|
assert!(
|
||||||
ambiguities.contains(&(Box::new("1"), Box::new("4")))
|
ambiguities.contains(&("1".as_label(), "4".as_label()))
|
||||||
|| ambiguities.contains(&(Box::new("4"), Box::new("1")))
|
|| ambiguities.contains(&("4".as_label(), "1".as_label()))
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
ambiguities.contains(&(Box::new("2"), Box::new("4")))
|
ambiguities.contains(&("2".as_label(), "4".as_label()))
|
||||||
|| ambiguities.contains(&(Box::new("4"), Box::new("2")))
|
|| ambiguities.contains(&("4".as_label(), "2".as_label()))
|
||||||
);
|
);
|
||||||
assert_eq!(ambiguities.len(), 2);
|
assert_eq!(ambiguities.len(), 2);
|
||||||
|
|
||||||
|
@ -1925,28 +1921,28 @@ mod tests {
|
||||||
stage.rebuild_orders_and_dependencies();
|
stage.rebuild_orders_and_dependencies();
|
||||||
let ambiguities = find_ambiguities_first_str_labels(&stage.exclusive_at_start);
|
let ambiguities = find_ambiguities_first_str_labels(&stage.exclusive_at_start);
|
||||||
assert!(
|
assert!(
|
||||||
ambiguities.contains(&(Box::new("1"), Box::new("3")))
|
ambiguities.contains(&("1".as_label(), "3".as_label()))
|
||||||
|| ambiguities.contains(&(Box::new("3"), Box::new("1")))
|
|| ambiguities.contains(&("3".as_label(), "1".as_label()))
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
ambiguities.contains(&(Box::new("2"), Box::new("3")))
|
ambiguities.contains(&("2".as_label(), "3".as_label()))
|
||||||
|| ambiguities.contains(&(Box::new("3"), Box::new("2")))
|
|| ambiguities.contains(&("3".as_label(), "2".as_label()))
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
ambiguities.contains(&(Box::new("1"), Box::new("4")))
|
ambiguities.contains(&("1".as_label(), "4".as_label()))
|
||||||
|| ambiguities.contains(&(Box::new("4"), Box::new("1")))
|
|| ambiguities.contains(&("4".as_label(), "1".as_label()))
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
ambiguities.contains(&(Box::new("2"), Box::new("4")))
|
ambiguities.contains(&("2".as_label(), "4".as_label()))
|
||||||
|| ambiguities.contains(&(Box::new("4"), Box::new("2")))
|
|| ambiguities.contains(&("4".as_label(), "2".as_label()))
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
ambiguities.contains(&(Box::new("1"), Box::new("5")))
|
ambiguities.contains(&("1".as_label(), "5".as_label()))
|
||||||
|| ambiguities.contains(&(Box::new("5"), Box::new("1")))
|
|| ambiguities.contains(&("5".as_label(), "1".as_label()))
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
ambiguities.contains(&(Box::new("2"), Box::new("5")))
|
ambiguities.contains(&("2".as_label(), "5".as_label()))
|
||||||
|| ambiguities.contains(&(Box::new("5"), Box::new("2")))
|
|| ambiguities.contains(&("5".as_label(), "2".as_label()))
|
||||||
);
|
);
|
||||||
assert_eq!(ambiguities.len(), 6);
|
assert_eq!(ambiguities.len(), 6);
|
||||||
|
|
||||||
|
@ -1962,20 +1958,20 @@ mod tests {
|
||||||
stage.rebuild_orders_and_dependencies();
|
stage.rebuild_orders_and_dependencies();
|
||||||
let ambiguities = find_ambiguities_first_str_labels(&stage.exclusive_at_start);
|
let ambiguities = find_ambiguities_first_str_labels(&stage.exclusive_at_start);
|
||||||
assert!(
|
assert!(
|
||||||
ambiguities.contains(&(Box::new("2"), Box::new("3")))
|
ambiguities.contains(&("2".as_label(), "3".as_label()))
|
||||||
|| ambiguities.contains(&(Box::new("3"), Box::new("2")))
|
|| ambiguities.contains(&("3".as_label(), "2".as_label()))
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
ambiguities.contains(&(Box::new("1"), Box::new("4")))
|
ambiguities.contains(&("1".as_label(), "4".as_label()))
|
||||||
|| ambiguities.contains(&(Box::new("4"), Box::new("1")))
|
|| ambiguities.contains(&("4".as_label(), "1".as_label()))
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
ambiguities.contains(&(Box::new("2"), Box::new("4")))
|
ambiguities.contains(&("2".as_label(), "4".as_label()))
|
||||||
|| ambiguities.contains(&(Box::new("4"), Box::new("2")))
|
|| ambiguities.contains(&("4".as_label(), "2".as_label()))
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
ambiguities.contains(&(Box::new("2"), Box::new("5")))
|
ambiguities.contains(&("2".as_label(), "5".as_label()))
|
||||||
|| ambiguities.contains(&(Box::new("5"), Box::new("2")))
|
|| ambiguities.contains(&("5".as_label(), "2".as_label()))
|
||||||
);
|
);
|
||||||
assert_eq!(ambiguities.len(), 4);
|
assert_eq!(ambiguities.len(), 4);
|
||||||
|
|
||||||
|
|
|
@ -53,47 +53,19 @@ enum ScheduledOperation<T: StateData> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
|
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
|
||||||
enum StateCallback {
|
struct DriverLabel(TypeId, &'static str);
|
||||||
Update,
|
|
||||||
InactiveUpdate,
|
|
||||||
InStackUpdate,
|
|
||||||
Enter,
|
|
||||||
Exit,
|
|
||||||
Pause,
|
|
||||||
Resume,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl StateCallback {
|
|
||||||
fn into_label<T>(self, state: T) -> StateRunCriteriaLabel<T>
|
|
||||||
where
|
|
||||||
T: StateData,
|
|
||||||
{
|
|
||||||
StateRunCriteriaLabel(state, self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
|
|
||||||
struct StateRunCriteriaLabel<T>(T, StateCallback);
|
|
||||||
impl<T> RunCriteriaLabel for StateRunCriteriaLabel<T>
|
|
||||||
where
|
|
||||||
T: StateData,
|
|
||||||
{
|
|
||||||
fn dyn_clone(&self) -> Box<dyn RunCriteriaLabel> {
|
|
||||||
Box::new(self.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
|
|
||||||
struct DriverLabel(TypeId);
|
|
||||||
impl RunCriteriaLabel for DriverLabel {
|
impl RunCriteriaLabel for DriverLabel {
|
||||||
fn dyn_clone(&self) -> Box<dyn RunCriteriaLabel> {
|
fn type_id(&self) -> core::any::TypeId {
|
||||||
Box::new(self.clone())
|
self.0
|
||||||
|
}
|
||||||
|
fn as_str(&self) -> &'static str {
|
||||||
|
self.1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DriverLabel {
|
impl DriverLabel {
|
||||||
fn of<T: 'static>() -> Self {
|
fn of<T: 'static>() -> Self {
|
||||||
Self(TypeId::of::<T>())
|
Self(TypeId::of::<T>(), std::any::type_name::<T>())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,17 +74,14 @@ where
|
||||||
T: StateData,
|
T: StateData,
|
||||||
{
|
{
|
||||||
pub fn on_update(pred: T) -> RunCriteriaDescriptor {
|
pub fn on_update(pred: T) -> RunCriteriaDescriptor {
|
||||||
let pred_clone = pred.clone();
|
|
||||||
(move |state: Res<State<T>>| {
|
(move |state: Res<State<T>>| {
|
||||||
state.stack.last().unwrap() == &pred && state.transition.is_none()
|
state.stack.last().unwrap() == &pred && state.transition.is_none()
|
||||||
})
|
})
|
||||||
.chain(should_run_adapter::<T>)
|
.chain(should_run_adapter::<T>)
|
||||||
.after(DriverLabel::of::<T>())
|
.after(DriverLabel::of::<T>())
|
||||||
.label_discard_if_duplicate(StateCallback::Update.into_label(pred_clone))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_inactive_update(pred: T) -> RunCriteriaDescriptor {
|
pub fn on_inactive_update(pred: T) -> RunCriteriaDescriptor {
|
||||||
let pred_clone = pred.clone();
|
|
||||||
(move |state: Res<State<T>>, mut is_inactive: Local<bool>| match &state.transition {
|
(move |state: Res<State<T>>, mut is_inactive: Local<bool>| match &state.transition {
|
||||||
Some(StateTransition::Pausing(ref relevant, _))
|
Some(StateTransition::Pausing(ref relevant, _))
|
||||||
| Some(StateTransition::Resuming(_, ref relevant)) => {
|
| Some(StateTransition::Resuming(_, ref relevant)) => {
|
||||||
|
@ -126,11 +95,9 @@ where
|
||||||
})
|
})
|
||||||
.chain(should_run_adapter::<T>)
|
.chain(should_run_adapter::<T>)
|
||||||
.after(DriverLabel::of::<T>())
|
.after(DriverLabel::of::<T>())
|
||||||
.label_discard_if_duplicate(StateCallback::InactiveUpdate.into_label(pred_clone))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_in_stack_update(pred: T) -> RunCriteriaDescriptor {
|
pub fn on_in_stack_update(pred: T) -> RunCriteriaDescriptor {
|
||||||
let pred_clone = pred.clone();
|
|
||||||
(move |state: Res<State<T>>, mut is_in_stack: Local<bool>| match &state.transition {
|
(move |state: Res<State<T>>, mut is_in_stack: Local<bool>| match &state.transition {
|
||||||
Some(StateTransition::Entering(ref relevant, _))
|
Some(StateTransition::Entering(ref relevant, _))
|
||||||
| Some(StateTransition::ExitingToResume(_, ref relevant))
|
| Some(StateTransition::ExitingToResume(_, ref relevant))
|
||||||
|
@ -151,11 +118,9 @@ where
|
||||||
})
|
})
|
||||||
.chain(should_run_adapter::<T>)
|
.chain(should_run_adapter::<T>)
|
||||||
.after(DriverLabel::of::<T>())
|
.after(DriverLabel::of::<T>())
|
||||||
.label_discard_if_duplicate(StateCallback::InStackUpdate.into_label(pred_clone))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_enter(pred: T) -> RunCriteriaDescriptor {
|
pub fn on_enter(pred: T) -> RunCriteriaDescriptor {
|
||||||
let pred_clone = pred.clone();
|
|
||||||
(move |state: Res<State<T>>| {
|
(move |state: Res<State<T>>| {
|
||||||
state
|
state
|
||||||
.transition
|
.transition
|
||||||
|
@ -168,11 +133,9 @@ where
|
||||||
})
|
})
|
||||||
.chain(should_run_adapter::<T>)
|
.chain(should_run_adapter::<T>)
|
||||||
.after(DriverLabel::of::<T>())
|
.after(DriverLabel::of::<T>())
|
||||||
.label_discard_if_duplicate(StateCallback::Enter.into_label(pred_clone))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_exit(pred: T) -> RunCriteriaDescriptor {
|
pub fn on_exit(pred: T) -> RunCriteriaDescriptor {
|
||||||
let pred_clone = pred.clone();
|
|
||||||
(move |state: Res<State<T>>| {
|
(move |state: Res<State<T>>| {
|
||||||
state
|
state
|
||||||
.transition
|
.transition
|
||||||
|
@ -185,11 +148,9 @@ where
|
||||||
})
|
})
|
||||||
.chain(should_run_adapter::<T>)
|
.chain(should_run_adapter::<T>)
|
||||||
.after(DriverLabel::of::<T>())
|
.after(DriverLabel::of::<T>())
|
||||||
.label_discard_if_duplicate(StateCallback::Exit.into_label(pred_clone))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_pause(pred: T) -> RunCriteriaDescriptor {
|
pub fn on_pause(pred: T) -> RunCriteriaDescriptor {
|
||||||
let pred_clone = pred.clone();
|
|
||||||
(move |state: Res<State<T>>| {
|
(move |state: Res<State<T>>| {
|
||||||
state
|
state
|
||||||
.transition
|
.transition
|
||||||
|
@ -201,11 +162,9 @@ where
|
||||||
})
|
})
|
||||||
.chain(should_run_adapter::<T>)
|
.chain(should_run_adapter::<T>)
|
||||||
.after(DriverLabel::of::<T>())
|
.after(DriverLabel::of::<T>())
|
||||||
.label_discard_if_duplicate(StateCallback::Pause.into_label(pred_clone))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_resume(pred: T) -> RunCriteriaDescriptor {
|
pub fn on_resume(pred: T) -> RunCriteriaDescriptor {
|
||||||
let pred_clone = pred.clone();
|
|
||||||
(move |state: Res<State<T>>| {
|
(move |state: Res<State<T>>| {
|
||||||
state
|
state
|
||||||
.transition
|
.transition
|
||||||
|
@ -217,7 +176,6 @@ where
|
||||||
})
|
})
|
||||||
.chain(should_run_adapter::<T>)
|
.chain(should_run_adapter::<T>)
|
||||||
.after(DriverLabel::of::<T>())
|
.after(DriverLabel::of::<T>())
|
||||||
.label_discard_if_duplicate(StateCallback::Resume.into_label(pred_clone))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_update_set(s: T) -> SystemSet {
|
pub fn on_update_set(s: T) -> SystemSet {
|
||||||
|
|
|
@ -2,15 +2,15 @@ use crate::{
|
||||||
component::ComponentId,
|
component::ComponentId,
|
||||||
query::Access,
|
query::Access,
|
||||||
schedule::{
|
schedule::{
|
||||||
BoxedAmbiguitySetLabel, BoxedRunCriteriaLabel, BoxedSystemLabel, ExclusiveSystemDescriptor,
|
AmbiguitySetLabelId, ExclusiveSystemDescriptor, GraphNode, ParallelSystemDescriptor,
|
||||||
GraphNode, ParallelSystemDescriptor,
|
RunCriteriaLabelId, SystemLabelId,
|
||||||
},
|
},
|
||||||
system::{ExclusiveSystem, System},
|
system::{ExclusiveSystem, System},
|
||||||
};
|
};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
/// System metadata like its name, labels, order requirements and component access.
|
/// System metadata like its name, labels, order requirements and component access.
|
||||||
pub trait SystemContainer: GraphNode<Label = BoxedSystemLabel> {
|
pub trait SystemContainer: GraphNode<Label = SystemLabelId> {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
fn dependencies(&self) -> &[usize];
|
fn dependencies(&self) -> &[usize];
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
@ -19,20 +19,20 @@ pub trait SystemContainer: GraphNode<Label = BoxedSystemLabel> {
|
||||||
fn run_criteria(&self) -> Option<usize>;
|
fn run_criteria(&self) -> Option<usize>;
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
fn set_run_criteria(&mut self, index: usize);
|
fn set_run_criteria(&mut self, index: usize);
|
||||||
fn run_criteria_label(&self) -> Option<&BoxedRunCriteriaLabel>;
|
fn run_criteria_label(&self) -> Option<&RunCriteriaLabelId>;
|
||||||
fn ambiguity_sets(&self) -> &[BoxedAmbiguitySetLabel];
|
fn ambiguity_sets(&self) -> &[AmbiguitySetLabelId];
|
||||||
fn component_access(&self) -> Option<&Access<ComponentId>>;
|
fn component_access(&self) -> Option<&Access<ComponentId>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) struct ExclusiveSystemContainer {
|
pub(super) struct ExclusiveSystemContainer {
|
||||||
system: Box<dyn ExclusiveSystem>,
|
system: Box<dyn ExclusiveSystem>,
|
||||||
pub(super) run_criteria_index: Option<usize>,
|
pub(super) run_criteria_index: Option<usize>,
|
||||||
pub(super) run_criteria_label: Option<BoxedRunCriteriaLabel>,
|
pub(super) run_criteria_label: Option<RunCriteriaLabelId>,
|
||||||
dependencies: Vec<usize>,
|
dependencies: Vec<usize>,
|
||||||
labels: Vec<BoxedSystemLabel>,
|
labels: Vec<SystemLabelId>,
|
||||||
before: Vec<BoxedSystemLabel>,
|
before: Vec<SystemLabelId>,
|
||||||
after: Vec<BoxedSystemLabel>,
|
after: Vec<SystemLabelId>,
|
||||||
ambiguity_sets: Vec<BoxedAmbiguitySetLabel>,
|
ambiguity_sets: Vec<AmbiguitySetLabelId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExclusiveSystemContainer {
|
impl ExclusiveSystemContainer {
|
||||||
|
@ -55,21 +55,21 @@ impl ExclusiveSystemContainer {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GraphNode for ExclusiveSystemContainer {
|
impl GraphNode for ExclusiveSystemContainer {
|
||||||
type Label = BoxedSystemLabel;
|
type Label = SystemLabelId;
|
||||||
|
|
||||||
fn name(&self) -> Cow<'static, str> {
|
fn name(&self) -> Cow<'static, str> {
|
||||||
self.system.name()
|
self.system.name()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn labels(&self) -> &[BoxedSystemLabel] {
|
fn labels(&self) -> &[SystemLabelId] {
|
||||||
&self.labels
|
&self.labels
|
||||||
}
|
}
|
||||||
|
|
||||||
fn before(&self) -> &[BoxedSystemLabel] {
|
fn before(&self) -> &[SystemLabelId] {
|
||||||
&self.before
|
&self.before
|
||||||
}
|
}
|
||||||
|
|
||||||
fn after(&self) -> &[BoxedSystemLabel] {
|
fn after(&self) -> &[SystemLabelId] {
|
||||||
&self.after
|
&self.after
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,11 +92,11 @@ impl SystemContainer for ExclusiveSystemContainer {
|
||||||
self.run_criteria_index = Some(index);
|
self.run_criteria_index = Some(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_criteria_label(&self) -> Option<&BoxedRunCriteriaLabel> {
|
fn run_criteria_label(&self) -> Option<&RunCriteriaLabelId> {
|
||||||
self.run_criteria_label.as_ref()
|
self.run_criteria_label.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ambiguity_sets(&self) -> &[BoxedAmbiguitySetLabel] {
|
fn ambiguity_sets(&self) -> &[AmbiguitySetLabelId] {
|
||||||
&self.ambiguity_sets
|
&self.ambiguity_sets
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,13 +108,13 @@ impl SystemContainer for ExclusiveSystemContainer {
|
||||||
pub struct ParallelSystemContainer {
|
pub struct ParallelSystemContainer {
|
||||||
system: Box<dyn System<In = (), Out = ()>>,
|
system: Box<dyn System<In = (), Out = ()>>,
|
||||||
pub(crate) run_criteria_index: Option<usize>,
|
pub(crate) run_criteria_index: Option<usize>,
|
||||||
pub(crate) run_criteria_label: Option<BoxedRunCriteriaLabel>,
|
pub(crate) run_criteria_label: Option<RunCriteriaLabelId>,
|
||||||
pub(crate) should_run: bool,
|
pub(crate) should_run: bool,
|
||||||
dependencies: Vec<usize>,
|
dependencies: Vec<usize>,
|
||||||
labels: Vec<BoxedSystemLabel>,
|
labels: Vec<SystemLabelId>,
|
||||||
before: Vec<BoxedSystemLabel>,
|
before: Vec<SystemLabelId>,
|
||||||
after: Vec<BoxedSystemLabel>,
|
after: Vec<SystemLabelId>,
|
||||||
ambiguity_sets: Vec<BoxedAmbiguitySetLabel>,
|
ambiguity_sets: Vec<AmbiguitySetLabelId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParallelSystemContainer {
|
impl ParallelSystemContainer {
|
||||||
|
@ -154,21 +154,21 @@ impl ParallelSystemContainer {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GraphNode for ParallelSystemContainer {
|
impl GraphNode for ParallelSystemContainer {
|
||||||
type Label = BoxedSystemLabel;
|
type Label = SystemLabelId;
|
||||||
|
|
||||||
fn name(&self) -> Cow<'static, str> {
|
fn name(&self) -> Cow<'static, str> {
|
||||||
self.system().name()
|
self.system().name()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn labels(&self) -> &[BoxedSystemLabel] {
|
fn labels(&self) -> &[SystemLabelId] {
|
||||||
&self.labels
|
&self.labels
|
||||||
}
|
}
|
||||||
|
|
||||||
fn before(&self) -> &[BoxedSystemLabel] {
|
fn before(&self) -> &[SystemLabelId] {
|
||||||
&self.before
|
&self.before
|
||||||
}
|
}
|
||||||
|
|
||||||
fn after(&self) -> &[BoxedSystemLabel] {
|
fn after(&self) -> &[SystemLabelId] {
|
||||||
&self.after
|
&self.after
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,11 +191,11 @@ impl SystemContainer for ParallelSystemContainer {
|
||||||
self.run_criteria_index = Some(index);
|
self.run_criteria_index = Some(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_criteria_label(&self) -> Option<&BoxedRunCriteriaLabel> {
|
fn run_criteria_label(&self) -> Option<&RunCriteriaLabelId> {
|
||||||
self.run_criteria_label.as_ref()
|
self.run_criteria_label.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ambiguity_sets(&self) -> &[BoxedAmbiguitySetLabel] {
|
fn ambiguity_sets(&self) -> &[AmbiguitySetLabelId] {
|
||||||
&self.ambiguity_sets
|
&self.ambiguity_sets
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
schedule::{
|
schedule::{
|
||||||
AmbiguitySetLabel, BoxedAmbiguitySetLabel, BoxedSystemLabel, IntoRunCriteria,
|
AmbiguitySetLabel, AmbiguitySetLabelId, IntoRunCriteria, RunCriteriaDescriptorOrLabel,
|
||||||
RunCriteriaDescriptorOrLabel, SystemLabel,
|
SystemLabel, SystemLabelId,
|
||||||
},
|
},
|
||||||
system::{
|
system::{
|
||||||
AsSystemLabel, BoxedSystem, ExclusiveSystem, ExclusiveSystemCoerced, ExclusiveSystemFn,
|
AsSystemLabel, BoxedSystem, ExclusiveSystem, ExclusiveSystemCoerced, ExclusiveSystemFn,
|
||||||
|
@ -98,10 +98,10 @@ impl IntoSystemDescriptor<()> for ExclusiveSystemCoerced {
|
||||||
pub struct ParallelSystemDescriptor {
|
pub struct ParallelSystemDescriptor {
|
||||||
pub(crate) system: BoxedSystem<(), ()>,
|
pub(crate) system: BoxedSystem<(), ()>,
|
||||||
pub(crate) run_criteria: Option<RunCriteriaDescriptorOrLabel>,
|
pub(crate) run_criteria: Option<RunCriteriaDescriptorOrLabel>,
|
||||||
pub(crate) labels: Vec<BoxedSystemLabel>,
|
pub(crate) labels: Vec<SystemLabelId>,
|
||||||
pub(crate) before: Vec<BoxedSystemLabel>,
|
pub(crate) before: Vec<SystemLabelId>,
|
||||||
pub(crate) after: Vec<BoxedSystemLabel>,
|
pub(crate) after: Vec<SystemLabelId>,
|
||||||
pub(crate) ambiguity_sets: Vec<BoxedAmbiguitySetLabel>,
|
pub(crate) ambiguity_sets: Vec<AmbiguitySetLabelId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_parallel_descriptor(system: BoxedSystem<(), ()>) -> ParallelSystemDescriptor {
|
fn new_parallel_descriptor(system: BoxedSystem<(), ()>) -> ParallelSystemDescriptor {
|
||||||
|
@ -147,22 +147,22 @@ impl ParallelSystemDescriptorCoercion<()> for ParallelSystemDescriptor {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn label(mut self, label: impl SystemLabel) -> ParallelSystemDescriptor {
|
fn label(mut self, label: impl SystemLabel) -> ParallelSystemDescriptor {
|
||||||
self.labels.push(Box::new(label));
|
self.labels.push(label.as_label());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn before<Marker>(mut self, label: impl AsSystemLabel<Marker>) -> ParallelSystemDescriptor {
|
fn before<Marker>(mut self, label: impl AsSystemLabel<Marker>) -> ParallelSystemDescriptor {
|
||||||
self.before.push(Box::new(label.as_system_label()));
|
self.before.push(label.as_system_label().as_label());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn after<Marker>(mut self, label: impl AsSystemLabel<Marker>) -> ParallelSystemDescriptor {
|
fn after<Marker>(mut self, label: impl AsSystemLabel<Marker>) -> ParallelSystemDescriptor {
|
||||||
self.after.push(Box::new(label.as_system_label()));
|
self.after.push(label.as_system_label().as_label());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn in_ambiguity_set(mut self, set: impl AmbiguitySetLabel) -> ParallelSystemDescriptor {
|
fn in_ambiguity_set(mut self, set: impl AmbiguitySetLabel) -> ParallelSystemDescriptor {
|
||||||
self.ambiguity_sets.push(Box::new(set));
|
self.ambiguity_sets.push(set.as_label());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -232,10 +232,10 @@ pub(crate) enum InsertionPoint {
|
||||||
pub struct ExclusiveSystemDescriptor {
|
pub struct ExclusiveSystemDescriptor {
|
||||||
pub(crate) system: Box<dyn ExclusiveSystem>,
|
pub(crate) system: Box<dyn ExclusiveSystem>,
|
||||||
pub(crate) run_criteria: Option<RunCriteriaDescriptorOrLabel>,
|
pub(crate) run_criteria: Option<RunCriteriaDescriptorOrLabel>,
|
||||||
pub(crate) labels: Vec<BoxedSystemLabel>,
|
pub(crate) labels: Vec<SystemLabelId>,
|
||||||
pub(crate) before: Vec<BoxedSystemLabel>,
|
pub(crate) before: Vec<SystemLabelId>,
|
||||||
pub(crate) after: Vec<BoxedSystemLabel>,
|
pub(crate) after: Vec<SystemLabelId>,
|
||||||
pub(crate) ambiguity_sets: Vec<BoxedAmbiguitySetLabel>,
|
pub(crate) ambiguity_sets: Vec<AmbiguitySetLabelId>,
|
||||||
pub(crate) insertion_point: InsertionPoint,
|
pub(crate) insertion_point: InsertionPoint,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,22 +293,22 @@ impl ExclusiveSystemDescriptorCoercion for ExclusiveSystemDescriptor {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn label(mut self, label: impl SystemLabel) -> ExclusiveSystemDescriptor {
|
fn label(mut self, label: impl SystemLabel) -> ExclusiveSystemDescriptor {
|
||||||
self.labels.push(Box::new(label));
|
self.labels.push(label.as_label());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn before(mut self, label: impl SystemLabel) -> ExclusiveSystemDescriptor {
|
fn before(mut self, label: impl SystemLabel) -> ExclusiveSystemDescriptor {
|
||||||
self.before.push(Box::new(label));
|
self.before.push(label.as_label());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn after(mut self, label: impl SystemLabel) -> ExclusiveSystemDescriptor {
|
fn after(mut self, label: impl SystemLabel) -> ExclusiveSystemDescriptor {
|
||||||
self.after.push(Box::new(label));
|
self.after.push(label.as_label());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn in_ambiguity_set(mut self, set: impl AmbiguitySetLabel) -> ExclusiveSystemDescriptor {
|
fn in_ambiguity_set(mut self, set: impl AmbiguitySetLabel) -> ExclusiveSystemDescriptor {
|
||||||
self.ambiguity_sets.push(Box::new(set));
|
self.ambiguity_sets.push(set.as_label());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use crate::schedule::{
|
use crate::schedule::{
|
||||||
AmbiguitySetLabel, BoxedAmbiguitySetLabel, BoxedSystemLabel, IntoRunCriteria,
|
AmbiguitySetLabel, AmbiguitySetLabelId, IntoRunCriteria, IntoSystemDescriptor,
|
||||||
IntoSystemDescriptor, RunCriteriaDescriptorOrLabel, State, StateData, SystemDescriptor,
|
RunCriteriaDescriptorOrLabel, State, StateData, SystemDescriptor, SystemLabel, SystemLabelId,
|
||||||
SystemLabel,
|
|
||||||
};
|
};
|
||||||
use crate::system::AsSystemLabel;
|
use crate::system::AsSystemLabel;
|
||||||
|
|
||||||
|
@ -10,10 +9,10 @@ use crate::system::AsSystemLabel;
|
||||||
pub struct SystemSet {
|
pub struct SystemSet {
|
||||||
pub(crate) systems: Vec<SystemDescriptor>,
|
pub(crate) systems: Vec<SystemDescriptor>,
|
||||||
pub(crate) run_criteria: Option<RunCriteriaDescriptorOrLabel>,
|
pub(crate) run_criteria: Option<RunCriteriaDescriptorOrLabel>,
|
||||||
pub(crate) labels: Vec<BoxedSystemLabel>,
|
pub(crate) labels: Vec<SystemLabelId>,
|
||||||
pub(crate) before: Vec<BoxedSystemLabel>,
|
pub(crate) before: Vec<SystemLabelId>,
|
||||||
pub(crate) after: Vec<BoxedSystemLabel>,
|
pub(crate) after: Vec<SystemLabelId>,
|
||||||
pub(crate) ambiguity_sets: Vec<BoxedAmbiguitySetLabel>,
|
pub(crate) ambiguity_sets: Vec<AmbiguitySetLabelId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SystemSet {
|
impl SystemSet {
|
||||||
|
@ -72,7 +71,7 @@ impl SystemSet {
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn in_ambiguity_set(mut self, set: impl AmbiguitySetLabel) -> Self {
|
pub fn in_ambiguity_set(mut self, set: impl AmbiguitySetLabel) -> Self {
|
||||||
self.ambiguity_sets.push(Box::new(set));
|
self.ambiguity_sets.push(set.as_label());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,19 +89,19 @@ impl SystemSet {
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn label(mut self, label: impl SystemLabel) -> Self {
|
pub fn label(mut self, label: impl SystemLabel) -> Self {
|
||||||
self.labels.push(Box::new(label));
|
self.labels.push(label.as_label());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn before<Marker>(mut self, label: impl AsSystemLabel<Marker>) -> Self {
|
pub fn before<Marker>(mut self, label: impl AsSystemLabel<Marker>) -> Self {
|
||||||
self.before.push(Box::new(label.as_system_label()));
|
self.before.push(label.as_system_label().as_label());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn after<Marker>(mut self, label: impl AsSystemLabel<Marker>) -> Self {
|
pub fn after<Marker>(mut self, label: impl AsSystemLabel<Marker>) -> Self {
|
||||||
self.after.push(Box::new(label.as_system_label()));
|
self.after.push(label.as_system_label().as_label());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ use crate::{
|
||||||
component::ComponentId,
|
component::ComponentId,
|
||||||
prelude::FromWorld,
|
prelude::FromWorld,
|
||||||
query::{Access, FilteredAccessSet},
|
query::{Access, FilteredAccessSet},
|
||||||
schedule::SystemLabel,
|
schedule::{SystemLabel, SystemLabelId},
|
||||||
system::{
|
system::{
|
||||||
check_system_change_tick, ReadOnlySystemParamFetch, System, SystemParam, SystemParamFetch,
|
check_system_change_tick, ReadOnlySystemParamFetch, System, SystemParam, SystemParamFetch,
|
||||||
SystemParamItem, SystemParamState,
|
SystemParamItem, SystemParamState,
|
||||||
|
@ -12,7 +12,7 @@ use crate::{
|
||||||
world::{World, WorldId},
|
world::{World, WorldId},
|
||||||
};
|
};
|
||||||
use bevy_ecs_macros::all_tuples;
|
use bevy_ecs_macros::all_tuples;
|
||||||
use std::{borrow::Cow, fmt::Debug, hash::Hash, marker::PhantomData};
|
use std::{borrow::Cow, fmt::Debug, marker::PhantomData};
|
||||||
|
|
||||||
/// The metadata of a [`System`].
|
/// The metadata of a [`System`].
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -444,14 +444,21 @@ where
|
||||||
self.system_meta.name.as_ref(),
|
self.system_meta.name.as_ref(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
fn default_labels(&self) -> Vec<Box<dyn SystemLabel>> {
|
fn default_labels(&self) -> Vec<SystemLabelId> {
|
||||||
vec![Box::new(self.func.as_system_label())]
|
vec![self.func.as_system_label().as_label()]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A [`SystemLabel`] that was automatically generated for a system on the basis of its `TypeId`.
|
/// A [`SystemLabel`] that was automatically generated for a system on the basis of its `TypeId`.
|
||||||
pub struct SystemTypeIdLabel<T: 'static>(PhantomData<fn() -> T>);
|
pub struct SystemTypeIdLabel<T: 'static>(PhantomData<fn() -> T>);
|
||||||
|
|
||||||
|
impl<T: 'static> SystemLabel for SystemTypeIdLabel<T> {
|
||||||
|
#[inline]
|
||||||
|
fn as_str(&self) -> &'static str {
|
||||||
|
std::any::type_name::<T>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> Debug for SystemTypeIdLabel<T> {
|
impl<T> Debug for SystemTypeIdLabel<T> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
f.debug_tuple("SystemTypeIdLabel")
|
f.debug_tuple("SystemTypeIdLabel")
|
||||||
|
@ -459,34 +466,14 @@ impl<T> Debug for SystemTypeIdLabel<T> {
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<T> Hash for SystemTypeIdLabel<T> {
|
|
||||||
fn hash<H: std::hash::Hasher>(&self, _state: &mut H) {
|
|
||||||
// All SystemTypeIds of a given type are the same.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<T> Clone for SystemTypeIdLabel<T> {
|
impl<T> Clone for SystemTypeIdLabel<T> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self(PhantomData)
|
*self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Copy for SystemTypeIdLabel<T> {}
|
impl<T> Copy for SystemTypeIdLabel<T> {}
|
||||||
|
|
||||||
impl<T> PartialEq for SystemTypeIdLabel<T> {
|
|
||||||
#[inline]
|
|
||||||
fn eq(&self, _other: &Self) -> bool {
|
|
||||||
// All labels of a given type are equal, as they will all have the same type id
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<T> Eq for SystemTypeIdLabel<T> {}
|
|
||||||
|
|
||||||
impl<T> SystemLabel for SystemTypeIdLabel<T> {
|
|
||||||
fn dyn_clone(&self) -> Box<dyn SystemLabel> {
|
|
||||||
Box::new(*self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A trait implemented for all functions that can be used as [`System`]s.
|
/// A trait implemented for all functions that can be used as [`System`]s.
|
||||||
///
|
///
|
||||||
/// This trait can be useful for making your own systems which accept other systems,
|
/// This trait can be useful for making your own systems which accept other systems,
|
||||||
|
@ -612,24 +599,21 @@ all_tuples!(impl_system_function, 0, 16, F);
|
||||||
/// Used to implicitly convert systems to their default labels. For example, it will convert
|
/// Used to implicitly convert systems to their default labels. For example, it will convert
|
||||||
/// "system functions" to their [`SystemTypeIdLabel`].
|
/// "system functions" to their [`SystemTypeIdLabel`].
|
||||||
pub trait AsSystemLabel<Marker> {
|
pub trait AsSystemLabel<Marker> {
|
||||||
type SystemLabel: SystemLabel;
|
fn as_system_label(&self) -> SystemLabelId;
|
||||||
fn as_system_label(&self) -> Self::SystemLabel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<In, Out, Param: SystemParam, Marker, T: SystemParamFunction<In, Out, Param, Marker>>
|
impl<In, Out, Param: SystemParam, Marker, T: SystemParamFunction<In, Out, Param, Marker>>
|
||||||
AsSystemLabel<(In, Out, Param, Marker)> for T
|
AsSystemLabel<(In, Out, Param, Marker)> for T
|
||||||
{
|
{
|
||||||
type SystemLabel = SystemTypeIdLabel<Self>;
|
#[inline]
|
||||||
|
fn as_system_label(&self) -> SystemLabelId {
|
||||||
fn as_system_label(&self) -> Self::SystemLabel {
|
SystemTypeIdLabel::<T>(PhantomData).as_label()
|
||||||
SystemTypeIdLabel(PhantomData::<fn() -> Self>)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: SystemLabel + Clone> AsSystemLabel<()> for T {
|
impl<T: SystemLabel> AsSystemLabel<()> for T {
|
||||||
type SystemLabel = T;
|
#[inline]
|
||||||
|
fn as_system_label(&self) -> SystemLabelId {
|
||||||
fn as_system_label(&self) -> Self::SystemLabel {
|
self.as_label()
|
||||||
self.clone()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use bevy_utils::tracing::warn;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
archetype::ArchetypeComponentId, change_detection::MAX_CHANGE_AGE, component::ComponentId,
|
archetype::ArchetypeComponentId, change_detection::MAX_CHANGE_AGE, component::ComponentId,
|
||||||
query::Access, schedule::SystemLabel, world::World,
|
query::Access, schedule::SystemLabelId, world::World,
|
||||||
};
|
};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ pub trait System: Send + Sync + 'static {
|
||||||
fn update_archetype_component_access(&mut self, world: &World);
|
fn update_archetype_component_access(&mut self, world: &World);
|
||||||
fn check_change_tick(&mut self, change_tick: u32);
|
fn check_change_tick(&mut self, change_tick: u32);
|
||||||
/// The default labels for the system
|
/// The default labels for the system
|
||||||
fn default_labels(&self) -> Vec<Box<dyn SystemLabel>> {
|
fn default_labels(&self) -> Vec<SystemLabelId> {
|
||||||
Vec::new()
|
Vec::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,12 +118,41 @@ pub fn derive_label(input: syn::DeriveInput, trait_path: &syn::Path) -> TokenStr
|
||||||
where_token: Default::default(),
|
where_token: Default::default(),
|
||||||
predicates: Default::default(),
|
predicates: Default::default(),
|
||||||
});
|
});
|
||||||
where_clause.predicates.push(syn::parse2(quote! { Self: Eq + ::std::fmt::Debug + ::std::hash::Hash + Clone + Send + Sync + 'static }).unwrap());
|
where_clause
|
||||||
|
.predicates
|
||||||
|
.push(syn::parse2(quote! { Self: 'static }).unwrap());
|
||||||
|
|
||||||
|
let as_str = match input.data {
|
||||||
|
syn::Data::Struct(d) => match d.fields {
|
||||||
|
syn::Fields::Unit => {
|
||||||
|
let lit = ident.to_string();
|
||||||
|
quote! { #lit }
|
||||||
|
}
|
||||||
|
_ => panic!("Labels cannot contain data."),
|
||||||
|
},
|
||||||
|
syn::Data::Enum(d) => {
|
||||||
|
let arms = d.variants.iter().map(|v| match v.fields {
|
||||||
|
syn::Fields::Unit => {
|
||||||
|
let mut path = syn::Path::from(ident.clone());
|
||||||
|
path.segments.push(v.ident.clone().into());
|
||||||
|
let lit = format!("{ident}::{}", v.ident.clone());
|
||||||
|
quote! { #path => #lit }
|
||||||
|
}
|
||||||
|
_ => panic!("Label variants cannot contain data."),
|
||||||
|
});
|
||||||
|
quote! {
|
||||||
|
match self {
|
||||||
|
#(#arms),*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
syn::Data::Union(_) => panic!("Unions cannot be used as labels."),
|
||||||
|
};
|
||||||
|
|
||||||
(quote! {
|
(quote! {
|
||||||
impl #impl_generics #trait_path for #ident #ty_generics #where_clause {
|
impl #impl_generics #trait_path for #ident #ty_generics #where_clause {
|
||||||
fn dyn_clone(&self) -> std::boxed::Box<dyn #trait_path> {
|
fn as_str(&self) -> &'static str {
|
||||||
std::boxed::Box::new(std::clone::Clone::clone(self))
|
#as_str
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -14,6 +14,7 @@ tracing = { version = "0.1", default-features = false, features = ["std"] }
|
||||||
instant = { version = "0.1", features = ["wasm-bindgen"] }
|
instant = { version = "0.1", features = ["wasm-bindgen"] }
|
||||||
uuid = { version = "1.1", features = ["v4", "serde"] }
|
uuid = { version = "1.1", features = ["v4", "serde"] }
|
||||||
hashbrown = { version = "0.12", features = ["serde"] }
|
hashbrown = { version = "0.12", features = ["serde"] }
|
||||||
|
concat-idents = "1"
|
||||||
|
|
||||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||||
getrandom = {version = "0.2.0", features = ["js"]}
|
getrandom = {version = "0.2.0", features = ["js"]}
|
||||||
|
|
|
@ -47,6 +47,9 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub use concat_idents::concat_idents;
|
||||||
|
|
||||||
/// Macro to define a new label trait
|
/// Macro to define a new label trait
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
|
@ -57,45 +60,57 @@ where
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! define_label {
|
macro_rules! define_label {
|
||||||
($label_trait_name:ident) => {
|
($label_name:ident) => {
|
||||||
/// Defines a set of strongly-typed labels for a class of objects
|
$crate::label::concat_idents!(id_name = $label_name, Id {
|
||||||
pub trait $label_trait_name:
|
|
||||||
$crate::label::DynHash + ::std::fmt::Debug + Send + Sync + 'static
|
|
||||||
{
|
|
||||||
#[doc(hidden)]
|
|
||||||
fn dyn_clone(&self) -> Box<dyn $label_trait_name>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialEq for dyn $label_trait_name {
|
/// Stores one of a set of strongly-typed labels for a class of objects.
|
||||||
fn eq(&self, other: &Self) -> bool {
|
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
self.dyn_eq(other.as_dyn_eq())
|
pub struct id_name(::core::any::TypeId, &'static str);
|
||||||
|
|
||||||
|
impl ::core::fmt::Debug for id_name {
|
||||||
|
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
|
||||||
|
write!(f, "{}", self.1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Eq for dyn $label_trait_name {}
|
/// Types that can be converted to a(n) [`id_name`].
|
||||||
|
///
|
||||||
impl ::std::hash::Hash for dyn $label_trait_name {
|
/// Check the docs for [`define_label`](bevy_ecs::define_label) for more info.
|
||||||
fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
|
pub trait $label_name: 'static {
|
||||||
self.dyn_hash(state);
|
/// Converts this type into an opaque, strongly-typed label.
|
||||||
|
fn as_label(&self) -> id_name {
|
||||||
|
let id = self.type_id();
|
||||||
|
let label = self.as_str();
|
||||||
|
id_name(id, label)
|
||||||
|
}
|
||||||
|
/// Returns the [`TypeId`] used to differentiate labels.
|
||||||
|
fn type_id(&self) -> ::core::any::TypeId {
|
||||||
|
::core::any::TypeId::of::<Self>()
|
||||||
|
}
|
||||||
|
/// Returns the representation of this label as a string literal.
|
||||||
|
///
|
||||||
|
/// In cases where you absolutely need a label to be determined at runtime,
|
||||||
|
/// you can use [`Box::leak`] to get a `'static` reference.
|
||||||
|
fn as_str(&self) -> &'static str;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Clone for Box<dyn $label_trait_name> {
|
impl $label_name for id_name {
|
||||||
fn clone(&self) -> Self {
|
fn as_label(&self) -> Self {
|
||||||
self.dyn_clone()
|
*self
|
||||||
|
}
|
||||||
|
fn type_id(&self) -> ::core::any::TypeId {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
fn as_str(&self) -> &'static str {
|
||||||
|
self.1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl $label_trait_name for ::std::borrow::Cow<'static, str> {
|
impl $label_name for &'static str {
|
||||||
fn dyn_clone(&self) -> Box<dyn $label_trait_name> {
|
fn as_str(&self) -> Self {
|
||||||
Box::new(self.clone())
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
impl $label_trait_name for &'static str {
|
|
||||||
fn dyn_clone(&self) -> Box<dyn $label_trait_name> {
|
|
||||||
Box::new(<&str>::clone(self))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue