Start promoting safe usage
This commit is contained in:
parent
ac59be0a71
commit
0136eb0a0b
8 changed files with 262 additions and 129 deletions
68
ecs/src/commands.rs
Normal file
68
ecs/src/commands.rs
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
use anyhow::Result;
|
||||||
|
use std::any::{Any, TypeId};
|
||||||
|
|
||||||
|
use crate::{world::ComponentChange, *};
|
||||||
|
|
||||||
|
enum CommandsTypes {
|
||||||
|
InsertEntity(EntityObject),
|
||||||
|
RemoveEntity(Entity),
|
||||||
|
UpdateEntity(Entity, ComponentChange),
|
||||||
|
|
||||||
|
Event(TypeId, Box<dyn Any + Send + Sync>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Commands {
|
||||||
|
commands: Vec<CommandsTypes>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Commands {
|
||||||
|
pub fn insert_entity(&mut self, entity_object: EntityObject) -> Entity {
|
||||||
|
let entity = entity_object.as_entity();
|
||||||
|
|
||||||
|
self.commands
|
||||||
|
.push(CommandsTypes::InsertEntity(entity_object));
|
||||||
|
|
||||||
|
entity
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove_entity(&mut self, entity: Entity) {
|
||||||
|
self.commands.push(CommandsTypes::RemoveEntity(entity));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert_component<T: EntityComponent>(&mut self, entity: Entity, component: T) {
|
||||||
|
self.commands.push(CommandsTypes::UpdateEntity(
|
||||||
|
entity,
|
||||||
|
ComponentChange::Added(TypeId::of::<T>(), Box::new(component)),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove_component<T: EntityComponent>(&mut self, entity: Entity) {
|
||||||
|
self.commands.push(CommandsTypes::UpdateEntity(
|
||||||
|
entity,
|
||||||
|
ComponentChange::Removed(TypeId::of::<T>()),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_event<T: Any + Send + Sync>(&mut self, payload: T) {
|
||||||
|
self.commands
|
||||||
|
.push(CommandsTypes::Event(TypeId::of::<T>(), Box::new(payload)));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn apply_deferred(self, world: &mut World) -> Result<()> {
|
||||||
|
for command in self.commands {
|
||||||
|
match command {
|
||||||
|
CommandsTypes::InsertEntity(entity_object) => {
|
||||||
|
world.add_entity(entity_object)?;
|
||||||
|
}
|
||||||
|
CommandsTypes::RemoveEntity(entity) => world.remove_entity(entity),
|
||||||
|
CommandsTypes::UpdateEntity(entity, component_change) => {
|
||||||
|
world.component_change(entity, component_change)
|
||||||
|
}
|
||||||
|
CommandsTypes::Event(type_id, any) => world.events.write_payload(type_id, any),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -72,6 +72,13 @@ impl Events {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn write_payload(&mut self, type_id: TypeId, payload: Box<dyn Any + Send + Sync>) {
|
||||||
|
match self.events.get_mut(&type_id) {
|
||||||
|
Some((payloads, _)) => payloads.push(payload),
|
||||||
|
None => panic!("register event type first!"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn fire_events(&mut self, world: &mut World) -> anyhow::Result<()> {
|
pub(crate) fn fire_events(&mut self, world: &mut World) -> anyhow::Result<()> {
|
||||||
for (payloads, listeners) in self.events.values_mut() {
|
for (payloads, listeners) in self.events.values_mut() {
|
||||||
for payload in payloads.iter_mut() {
|
for payload in payloads.iter_mut() {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
mod commands;
|
||||||
mod entity;
|
mod entity;
|
||||||
mod entity_object_manager;
|
mod entity_object_manager;
|
||||||
mod events;
|
mod events;
|
||||||
|
@ -17,5 +18,6 @@ pub use crate::type_map::{
|
||||||
pub use crate::unsafe_component_store::UnsafeComponentStore;
|
pub use crate::unsafe_component_store::UnsafeComponentStore;
|
||||||
pub use crate::updates::*;
|
pub use crate::updates::*;
|
||||||
pub use crate::world::{World, WorldBuilder};
|
pub use crate::world::{World, WorldBuilder};
|
||||||
|
pub use commands::Commands;
|
||||||
pub use get_disjoint_mut::GetDisjointMut;
|
pub use get_disjoint_mut::GetDisjointMut;
|
||||||
pub use update_macros::Resource;
|
pub use update_macros::Resource;
|
||||||
|
|
|
@ -14,20 +14,20 @@ use indexmap::IndexMap;
|
||||||
use super::super::timings::Timings;
|
use super::super::timings::Timings;
|
||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use update_macros::implement_pair_update;
|
use update_macros::{implement_pair_update, implement_single_update};
|
||||||
|
|
||||||
macro_rules! impl_singleton_update {
|
macro_rules! impl_singleton_update {
|
||||||
( $name: ident, $([$var: ident]$(,)?)+ ) => {
|
( $($var:ident $(,)?)+ ) => {
|
||||||
impl Archetype {
|
impl<Func, Filter, $( $var, )+> CreateArchetype<( $( $var, )+ ), Func, Filter> for Archetype
|
||||||
paste::item! {
|
|
||||||
pub fn [<create_ $name>]<F, Filter, $($var,)+>(f: F, filter: Filter) -> Self
|
|
||||||
where
|
where
|
||||||
F: Fn(&mut World, Entity, $(&mut $var,)+) -> Result<()> + Send + Sync + Clone + 'static,
|
Func: Fn(&mut Commands, Entity, $(&mut $var,)+) -> Result<()> + Send + Sync + Clone + 'static,
|
||||||
Filter: CheckFilter + 'static,
|
Filter: CheckFilter + 'static,
|
||||||
$(
|
$(
|
||||||
$var: EntityComponent + ComponentDebug,
|
$var: EntityComponent + ComponentDebug,
|
||||||
)+
|
)+
|
||||||
{
|
{
|
||||||
|
paste::item! {
|
||||||
|
fn create(f: Func, filter: Filter) -> Self {
|
||||||
$(
|
$(
|
||||||
filter.verify_dedup::<$var>();
|
filter.verify_dedup::<$var>();
|
||||||
)+
|
)+
|
||||||
|
@ -58,8 +58,8 @@ macro_rules! impl_singleton_update {
|
||||||
|
|
||||||
let f = f.clone();
|
let f = f.clone();
|
||||||
|
|
||||||
Ok(Box::new(move |e, scene_contents| {
|
Ok(Box::new(move |e, commands| {
|
||||||
unsafe { f(scene_contents, e, $([< $var:lower >].as_mut(),)+) }
|
unsafe { f(commands, e, $([< $var:lower >].as_mut(),)+) }
|
||||||
}))
|
}))
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
@ -69,12 +69,12 @@ macro_rules! impl_singleton_update {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Func, Filter, $( $var, )+> AddUpdates2<( $( $var, )+ ), Func, Filter> for Updates
|
impl<Func, Filter, $( $var, )+> AddUpdates<( $( $var, )+ ), Func, Filter> for Updates
|
||||||
where
|
where
|
||||||
$(
|
$(
|
||||||
$var: EntityComponent + ComponentDebug,
|
$var: EntityComponent + ComponentDebug,
|
||||||
)+
|
)+
|
||||||
Func: Fn(& mut World, Entity, $(&mut $var,)+) -> Result<()> + Send + Sync + Clone + 'static,
|
Func: Fn(& mut Commands, Entity, $(&mut $var,)+) -> Result<()> + Send + Sync + Clone + 'static,
|
||||||
Filter: CheckFilter + 'static
|
Filter: CheckFilter + 'static
|
||||||
{
|
{
|
||||||
fn add_update(
|
fn add_update(
|
||||||
|
@ -85,7 +85,7 @@ macro_rules! impl_singleton_update {
|
||||||
filter: Filter
|
filter: Filter
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
paste::item! {
|
paste::item! {
|
||||||
self.add(name, priority, Update::Single(Archetype::[<create_ $name>](func, filter)))
|
self.add(name, priority, Update::Single(Archetype::create(func, filter)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ macro_rules! impl_singleton_update {
|
||||||
$(
|
$(
|
||||||
$var: EntityComponent + ComponentDebug,
|
$var: EntityComponent + ComponentDebug,
|
||||||
)+
|
)+
|
||||||
Func: Fn(& mut World, Entity, $(&mut $var,)+) -> Result<()> + Send + Sync + Clone + 'static,
|
Func: Fn(& mut Commands, Entity, $(&mut $var,)+) -> Result<()> + Send + Sync + Clone + 'static,
|
||||||
Filter: CheckFilter + 'static
|
Filter: CheckFilter + 'static
|
||||||
{
|
{
|
||||||
fn add_update(
|
fn add_update(
|
||||||
|
@ -123,7 +123,7 @@ macro_rules! impl_pair_update {
|
||||||
pub fn [<create_lhs_ $lhs_id _rhs_ $rhs_id>] <F, LeftFilter, RightFilter, $($lhs_big,)+ $($rhs_big,)+>
|
pub fn [<create_lhs_ $lhs_id _rhs_ $rhs_id>] <F, LeftFilter, RightFilter, $($lhs_big,)+ $($rhs_big,)+>
|
||||||
(f: F, left_filter: LeftFilter, right_filter: RightFilter) -> Self
|
(f: F, left_filter: LeftFilter, right_filter: RightFilter) -> Self
|
||||||
where
|
where
|
||||||
F: Fn(&mut World, (Entity, $(&mut $lhs_big,)+), (Entity, $(&mut $rhs_big,)+)) -> Result<()> + Send + Sync + Clone + 'static,
|
F: Fn(&mut Commands, (Entity, $(&mut $lhs_big,)+), (Entity, $(&mut $rhs_big,)+)) -> Result<()> + Send + Sync + Clone + 'static,
|
||||||
LeftFilter: CheckFilter + 'static,
|
LeftFilter: CheckFilter + 'static,
|
||||||
RightFilter: CheckFilter + 'static,
|
RightFilter: CheckFilter + 'static,
|
||||||
$(
|
$(
|
||||||
|
@ -188,8 +188,8 @@ macro_rules! impl_pair_update {
|
||||||
|
|
||||||
let f = f.clone();
|
let f = f.clone();
|
||||||
|
|
||||||
Ok(Box::new(move |lhs_e, rhs_e, scene_contents| {
|
Ok(Box::new(move |lhs_e, rhs_e, commands| {
|
||||||
unsafe { f(scene_contents, (lhs_e, $($lhs_little.as_mut(),)+), (rhs_e, $($rhs_little.as_mut(),)+) ) }
|
unsafe { f(commands, (lhs_e, $($lhs_little.as_mut(),)+), (rhs_e, $($rhs_little.as_mut(),)+) ) }
|
||||||
}))
|
}))
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
@ -199,7 +199,7 @@ macro_rules! impl_pair_update {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Func, LhsFilter, RhsFilter, $( $lhs_big, )+ $($rhs_big,)+> AddUpdates2<( ($( $lhs_big, )+), ($($rhs_big,)+) ), Func, (LhsFilter, RhsFilter)> for Updates
|
impl<Func, LhsFilter, RhsFilter, $( $lhs_big, )+ $($rhs_big,)+> AddUpdates<( ($( $lhs_big, )+), ($($rhs_big,)+) ), Func, (LhsFilter, RhsFilter)> for Updates
|
||||||
where
|
where
|
||||||
$(
|
$(
|
||||||
$rhs_big: EntityComponent + ComponentDebug,
|
$rhs_big: EntityComponent + ComponentDebug,
|
||||||
|
@ -207,7 +207,7 @@ macro_rules! impl_pair_update {
|
||||||
$(
|
$(
|
||||||
$lhs_big: EntityComponent + ComponentDebug,
|
$lhs_big: EntityComponent + ComponentDebug,
|
||||||
)+
|
)+
|
||||||
Func: Fn(& mut World, (Entity, $(&mut $lhs_big,)+), (Entity, $(&mut $rhs_big,)+)) -> Result<()> + Send + Sync + Clone + 'static,
|
Func: Fn(&mut Commands, (Entity, $(&mut $lhs_big,)+), (Entity, $(&mut $rhs_big,)+)) -> Result<()> + Send + Sync + Clone + 'static,
|
||||||
LhsFilter: CheckFilter + 'static,
|
LhsFilter: CheckFilter + 'static,
|
||||||
RhsFilter: CheckFilter + 'static
|
RhsFilter: CheckFilter + 'static
|
||||||
{
|
{
|
||||||
|
@ -234,7 +234,7 @@ macro_rules! impl_pair_update {
|
||||||
$(
|
$(
|
||||||
$lhs_big: EntityComponent + ComponentDebug,
|
$lhs_big: EntityComponent + ComponentDebug,
|
||||||
)+
|
)+
|
||||||
Func: Fn(& mut World, (Entity, $(&mut $lhs_big,)+), (Entity, $(&mut $rhs_big,)+)) -> Result<()> + Send + Sync + Clone + 'static,
|
Func: Fn(& mut Commands, (Entity, $(&mut $lhs_big,)+), (Entity, $(&mut $rhs_big,)+)) -> Result<()> + Send + Sync + Clone + 'static,
|
||||||
LhsFilter: CheckFilter + 'static,
|
LhsFilter: CheckFilter + 'static,
|
||||||
RhsFilter: CheckFilter + 'static
|
RhsFilter: CheckFilter + 'static
|
||||||
{
|
{
|
||||||
|
@ -316,8 +316,8 @@ pub trait AddUpdates<T, Func, Filter> {
|
||||||
fn add_update(&mut self, name: &str, priority: u32, func: Func, filter: Filter) -> Result<()>;
|
fn add_update(&mut self, name: &str, priority: u32, func: Func, filter: Filter) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
trait AddUpdates2<T, Func, Filter> {
|
trait CreateArchetype<T, Func, Filter> {
|
||||||
fn add_update(&mut self, name: &str, priority: u32, func: Func, filter: Filter) -> Result<()>;
|
fn create(f: Func, filter: Filter) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait CheckFilter: Send + Sync + Default + Clone {
|
pub trait CheckFilter: Send + Sync + Default + Clone {
|
||||||
|
@ -358,12 +358,15 @@ impl ArchetypeInfo {
|
||||||
pub struct Archetype {
|
pub struct Archetype {
|
||||||
check_entity: Box<dyn Fn(&EntityObject) -> bool + Send + Sync>,
|
check_entity: Box<dyn Fn(&EntityObject) -> bool + Send + Sync>,
|
||||||
create_callback: Box<
|
create_callback: Box<
|
||||||
dyn Fn(&EntityObject) -> Result<Box<dyn Fn(Entity, &mut World) -> Result<()> + Send + Sync>>
|
dyn Fn(
|
||||||
|
&EntityObject,
|
||||||
|
)
|
||||||
|
-> Result<Box<dyn Fn(Entity, &mut Commands) -> Result<()> + Send + Sync>>
|
||||||
+ Send
|
+ Send
|
||||||
+ Sync,
|
+ Sync,
|
||||||
>,
|
>,
|
||||||
|
|
||||||
entities: IndexMap<Entity, Box<dyn Fn(Entity, &mut World) -> Result<()> + Send + Sync>>,
|
entities: IndexMap<Entity, Box<dyn Fn(Entity, &mut Commands) -> Result<()> + Send + Sync>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Archetype {
|
impl Archetype {
|
||||||
|
@ -381,9 +384,11 @@ impl Archetype {
|
||||||
self.entities.swap_remove(&entity);
|
self.entities.swap_remove(&entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute(&self, scene_contents: &mut World) -> Result<()> {
|
pub fn execute(&self, world: &mut World) -> Result<()> {
|
||||||
for (entity, callback) in self.entities.iter() {
|
for (entity, callback) in self.entities.iter() {
|
||||||
callback(*entity, scene_contents)?;
|
let mut commands = Commands::default();
|
||||||
|
callback(*entity, &mut commands)?;
|
||||||
|
commands.apply_deferred(world)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -391,7 +396,7 @@ impl Archetype {
|
||||||
|
|
||||||
pub fn entities(
|
pub fn entities(
|
||||||
&self,
|
&self,
|
||||||
) -> &IndexMap<Entity, Box<dyn Fn(Entity, &mut World) -> Result<()> + Send + Sync>> {
|
) -> &IndexMap<Entity, Box<dyn Fn(Entity, &mut Commands) -> Result<()> + Send + Sync>> {
|
||||||
&self.entities
|
&self.entities
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -405,14 +410,14 @@ pub struct ArchetypePair {
|
||||||
&EntityObject,
|
&EntityObject,
|
||||||
&EntityObject,
|
&EntityObject,
|
||||||
)
|
)
|
||||||
-> Result<Box<dyn Fn(Entity, Entity, &mut World) -> Result<()> + Send + Sync>>
|
-> Result<Box<dyn Fn(Entity, Entity, &mut Commands) -> Result<()> + Send + Sync>>
|
||||||
+ Send
|
+ Send
|
||||||
+ Sync,
|
+ Sync,
|
||||||
>,
|
>,
|
||||||
|
|
||||||
entities: IndexMap<
|
entities: IndexMap<
|
||||||
(Entity, Entity),
|
(Entity, Entity),
|
||||||
Box<dyn Fn(Entity, Entity, &mut World) -> Result<()> + Send + Sync>,
|
Box<dyn Fn(Entity, Entity, &mut Commands) -> Result<()> + Send + Sync>,
|
||||||
>,
|
>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -461,9 +466,11 @@ impl ArchetypePair {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn execute(&self, scene_contents: &mut World) -> Result<()> {
|
pub(crate) fn execute(&self, world: &mut World) -> Result<()> {
|
||||||
for ((left_entity, right_entity), callback) in self.entities.iter() {
|
for ((left_entity, right_entity), callback) in self.entities.iter() {
|
||||||
callback(*left_entity, *right_entity, scene_contents)?;
|
let mut commands = Commands::default();
|
||||||
|
callback(*left_entity, *right_entity, &mut commands)?;
|
||||||
|
commands.apply_deferred(world)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -625,26 +632,8 @@ impl Archetypes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
impl_singleton_update!(single, [R]);
|
|
||||||
#[rustfmt::skip]
|
|
||||||
impl_singleton_update!(double, [R], [S]);
|
|
||||||
#[rustfmt::skip]
|
|
||||||
impl_singleton_update!(triple, [R], [S], [T]);
|
|
||||||
#[rustfmt::skip]
|
|
||||||
impl_singleton_update!(quadruple, [R], [S], [T], [U]);
|
|
||||||
#[rustfmt::skip]
|
|
||||||
impl_singleton_update!(quintuple, [R], [S], [T], [U], [V]);
|
|
||||||
#[rustfmt::skip]
|
|
||||||
impl_singleton_update!(sextuple, [R], [S], [T], [U], [V], [W]);
|
|
||||||
#[rustfmt::skip]
|
|
||||||
impl_singleton_update!(septuple, [R], [S], [T], [U], [V], [W], [X]);
|
|
||||||
#[rustfmt::skip]
|
|
||||||
impl_singleton_update!(octuple, [R], [S], [T], [U], [V], [W], [X], [Y]);
|
|
||||||
#[rustfmt::skip]
|
|
||||||
impl_singleton_update!(ninetuple, [R], [S], [T], [U], [V], [W], [X], [Y], [Z]);
|
|
||||||
|
|
||||||
implement_pair_update!(impl_pair_update, 1, 10);
|
implement_pair_update!(impl_pair_update, 1, 10);
|
||||||
|
implement_single_update!(impl_singleton_update, 1, 10);
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
impl_update_filter!(Monuple, [R, r]);
|
impl_update_filter!(Monuple, [R, r]);
|
||||||
|
|
|
@ -58,7 +58,7 @@ impl WorldBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ComponentChange {
|
pub(crate) enum ComponentChange {
|
||||||
Added(TypeId, Box<dyn EntityComponent>),
|
Added(TypeId, Box<dyn EntityComponent>),
|
||||||
Removed(TypeId),
|
Removed(TypeId),
|
||||||
}
|
}
|
||||||
|
@ -249,6 +249,17 @@ impl World {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn component_change(&mut self, entity: Entity, change: ComponentChange) {
|
||||||
|
match self.entities_updates.get_mut(&entity) {
|
||||||
|
Some(changes) => {
|
||||||
|
changes.push(change);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
self.entities_updates.insert(entity, vec![change]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn remove_entity(&mut self, entity: Entity) {
|
pub fn remove_entity(&mut self, entity: Entity) {
|
||||||
self.entities_to_remove.push(entity);
|
self.entities_to_remove.push(entity);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
|
mod pair_update;
|
||||||
|
mod single_update;
|
||||||
|
|
||||||
|
use pair_update::pair_update;
|
||||||
|
use single_update::single_update;
|
||||||
|
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use proc_macro2::{Span, TokenStream as TokenStream2};
|
use quote::quote;
|
||||||
use quote::{format_ident, quote};
|
|
||||||
use syn::{
|
use syn::{
|
||||||
DeriveInput, Ident, LitInt, Result,
|
DeriveInput, Ident, LitInt, Result,
|
||||||
parse::{Parse, ParseStream},
|
parse::{Parse, ParseStream},
|
||||||
|
@ -39,81 +44,14 @@ struct TupleType {
|
||||||
pub fn implement_pair_update(input: TokenStream) -> TokenStream {
|
pub fn implement_pair_update(input: TokenStream) -> TokenStream {
|
||||||
let input = parse_macro_input!(input as InputInfo);
|
let input = parse_macro_input!(input as InputInfo);
|
||||||
|
|
||||||
let mut generic_count = Vec::new();
|
pair_update(input)
|
||||||
|
|
||||||
for lhs in input.start..=input.end {
|
|
||||||
for rhs in input.start..=input.end {
|
|
||||||
generic_count.push((lhs, rhs));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let generic_tuples: Vec<(Vec<TupleType>, Vec<TupleType>)> = generic_count
|
#[proc_macro]
|
||||||
.iter()
|
pub fn implement_single_update(input: TokenStream) -> TokenStream {
|
||||||
.map(|(lhs_count, rhs_count)| {
|
let input = parse_macro_input!(input as InputInfo);
|
||||||
let lhs = (input.start..(input.start + lhs_count))
|
|
||||||
.map(|i| TupleType {
|
|
||||||
little: format_ident!("l{}", i),
|
|
||||||
big: format_ident!("L{}", i),
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let rhs = (input.start..(input.start + rhs_count))
|
single_update(input)
|
||||||
.map(|i| TupleType {
|
|
||||||
little: format_ident!("r{}", i),
|
|
||||||
big: format_ident!("R{}", i),
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
(lhs, rhs)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let invocations: Vec<TokenStream2> = generic_tuples
|
|
||||||
.iter()
|
|
||||||
.map(|(lhs, rhs)| {
|
|
||||||
let lhs_expr = LitInt::new(&format!("{}", lhs.len()), Span::call_site());
|
|
||||||
let rhs_expr = LitInt::new(&format!("{}", rhs.len()), Span::call_site());
|
|
||||||
|
|
||||||
let lhs_args: Vec<TokenStream2> = lhs
|
|
||||||
.iter()
|
|
||||||
.map(|tuple| {
|
|
||||||
let little = &tuple.little;
|
|
||||||
let big = &tuple.big;
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
[#little: #big],
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let rhs_args: Vec<TokenStream2> = rhs
|
|
||||||
.iter()
|
|
||||||
.map(|tuple| {
|
|
||||||
let little = &tuple.little;
|
|
||||||
let big = &tuple.big;
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
[#little: #big],
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let macro_ident = &input.macro_ident;
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
#macro_ident!(
|
|
||||||
#lhs_expr, (#(#lhs_args)*),
|
|
||||||
#rhs_expr, (#(#rhs_args)*)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
TokenStream::from(quote! {
|
|
||||||
#(
|
|
||||||
#invocations
|
|
||||||
)*
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_derive(Resource)]
|
#[proc_macro_derive(Resource)]
|
||||||
|
|
85
update_macros/src/pair_update.rs
Normal file
85
update_macros/src/pair_update.rs
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
use proc_macro::TokenStream;
|
||||||
|
use proc_macro2::{Span, TokenStream as TokenStream2};
|
||||||
|
use quote::{format_ident, quote};
|
||||||
|
use syn::LitInt;
|
||||||
|
|
||||||
|
use crate::InputInfo;
|
||||||
|
use crate::TupleType;
|
||||||
|
|
||||||
|
pub fn pair_update(input: InputInfo) -> TokenStream {
|
||||||
|
let mut generic_count = Vec::new();
|
||||||
|
|
||||||
|
for lhs in input.start..=input.end {
|
||||||
|
for rhs in input.start..=input.end {
|
||||||
|
generic_count.push((lhs, rhs));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let generic_tuples: Vec<(Vec<TupleType>, Vec<TupleType>)> = generic_count
|
||||||
|
.iter()
|
||||||
|
.map(|(lhs_count, rhs_count)| {
|
||||||
|
let lhs = (input.start..(input.start + lhs_count))
|
||||||
|
.map(|i| TupleType {
|
||||||
|
little: format_ident!("l{}", i),
|
||||||
|
big: format_ident!("L{}", i),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let rhs = (input.start..(input.start + rhs_count))
|
||||||
|
.map(|i| TupleType {
|
||||||
|
little: format_ident!("r{}", i),
|
||||||
|
big: format_ident!("R{}", i),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
(lhs, rhs)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let invocations: Vec<TokenStream2> = generic_tuples
|
||||||
|
.iter()
|
||||||
|
.map(|(lhs, rhs)| {
|
||||||
|
let lhs_expr = LitInt::new(&format!("{}", lhs.len()), Span::call_site());
|
||||||
|
let rhs_expr = LitInt::new(&format!("{}", rhs.len()), Span::call_site());
|
||||||
|
|
||||||
|
let lhs_args: Vec<TokenStream2> = lhs
|
||||||
|
.iter()
|
||||||
|
.map(|tuple| {
|
||||||
|
let little = &tuple.little;
|
||||||
|
let big = &tuple.big;
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
[#little: #big],
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let rhs_args: Vec<TokenStream2> = rhs
|
||||||
|
.iter()
|
||||||
|
.map(|tuple| {
|
||||||
|
let little = &tuple.little;
|
||||||
|
let big = &tuple.big;
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
[#little: #big],
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let macro_ident = &input.macro_ident;
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#macro_ident!(
|
||||||
|
#lhs_expr, (#(#lhs_args)*),
|
||||||
|
#rhs_expr, (#(#rhs_args)*)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
TokenStream::from(quote! {
|
||||||
|
#(
|
||||||
|
#invocations
|
||||||
|
)*
|
||||||
|
})
|
||||||
|
}
|
33
update_macros/src/single_update.rs
Normal file
33
update_macros/src/single_update.rs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
use proc_macro::TokenStream;
|
||||||
|
use proc_macro2::TokenStream as TokenStream2;
|
||||||
|
use quote::{format_ident, quote};
|
||||||
|
use syn::Ident;
|
||||||
|
|
||||||
|
use crate::InputInfo;
|
||||||
|
|
||||||
|
pub fn single_update(input: InputInfo) -> TokenStream {
|
||||||
|
let generate_inputs: Vec<Vec<Ident>> = (input.start..=input.end)
|
||||||
|
.map(|count| {
|
||||||
|
(input.start..(input.start + count))
|
||||||
|
.map(|i| format_ident!("t{}", i))
|
||||||
|
.collect()
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let invocations: Vec<TokenStream2> = generate_inputs
|
||||||
|
.iter()
|
||||||
|
.map(|t| {
|
||||||
|
let macro_ident = &input.macro_ident;
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#macro_ident!(#(#t,)*);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
TokenStream::from(quote! {
|
||||||
|
#(
|
||||||
|
#invocations
|
||||||
|
)*
|
||||||
|
})
|
||||||
|
}
|
Loading…
Reference in a new issue