#![feature(allocator_api)]
#![feature(const_maybe_uninit_as_mut_ptr)]
#![feature(const_mut_refs)]
#![feature(const_ptr_offset_from)]
#![feature(const_ptr_write)]
#![feature(const_refs_to_cell)]
#![feature(const_trait_impl)]
#![feature(const_type_id)]
#![feature(explicit_generic_args_with_impl_trait)]
#![feature(never_type)]
#![feature(ptr_metadata)]
#![feature(raw_ref_op)]
#![feature(unchecked_math)]
#![feature(unsize)]
#![deny(warnings)]
#![doc(test(attr(deny(warnings))))]
#![doc(test(attr(allow(dead_code))))]
#![doc(test(attr(allow(unused_variables))))]
#![allow(clippy::collapsible_else_if)]
#![allow(clippy::option_map_unit_fn)]
#![allow(clippy::type_complexity)]
#![no_std]
extern crate alloc;
mod base;
pub use base::*;
pub mod binding;
#[cfg(docsrs)]
pub mod example {
use crate::{DetachedDepObjId, impl_dep_obj, dep_type, with_builder};
use components_arena::{Arena, Component, ComponentStop, Id, NewtypeComponentId, with_arena_in_state_part};
use dyn_context::{SelfState, State, StateExt, Stop};
dep_type! {
#[derive(Debug)]
pub struct MyDepType = MyDepTypeId[MyDepType] {
prop_1: bool = false,
prop_2: i32 = 10,
}
}
#[derive(Debug)]
struct MyDepTypePrivateData {
dep_data: MyDepType,
}
Component!((stop=MyDepTypeStop) struct MyDepTypePrivateData { .. });
impl ComponentStop for MyDepTypeStop {
with_arena_in_state_part!(MyApp { .my_dep_types });
fn stop(&self, state: &mut dyn State, id: Id<MyDepTypePrivateData>) {
MyDepTypeId(id).drop_bindings_priv(state);
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct MyDepTypeId(Id<MyDepTypePrivateData>);
NewtypeComponentId!(() pub struct MyDepTypeId(Id<MyDepTypePrivateData>););
impl DetachedDepObjId for MyDepTypeId { }
#[derive(Debug, Stop)]
pub struct MyApp {
my_dep_types: Arena<MyDepTypePrivateData>,
}
impl SelfState for MyApp { }
impl MyDepTypeId {
pub fn new(state: &mut dyn State) -> MyDepTypeId {
let app: &mut MyApp = state.get_mut();
app.my_dep_types.insert(|id| (MyDepTypePrivateData {
dep_data: MyDepType::new_priv()
}, MyDepTypeId(id)))
}
pub fn drop_self(self, state: &mut dyn State) {
self.drop_bindings_priv(state);
let app: &mut MyApp = state.get_mut();
app.my_dep_types.remove(self.0);
}
with_builder!(MyDepType);
}
impl_dep_obj!(MyDepTypeId {
fn<MyDepType>() -> (MyDepType) { MyApp { .my_dep_types } | .dep_data }
});
}
#[doc(hidden)]
pub use alloc::vec::Vec as std_vec_Vec;
#[doc(hidden)]
pub use alloc::boxed::Box as std_boxed_Box;
#[doc(hidden)]
pub use components_arena::ComponentId as components_arena_ComponentId;
#[doc(hidden)]
pub use components_arena::RawId as components_arena_RawId;
#[doc(hidden)]
pub use composable_allocators;
#[doc(hidden)]
pub use core::alloc::Allocator as std_alloc_Allocator;
#[doc(hidden)]
pub use core::any::Any as std_any_Any;
#[doc(hidden)]
pub use core::any::TypeId as std_any_TypeId;
#[doc(hidden)]
pub use core::compile_error as std_compile_error;
#[doc(hidden)]
pub use core::concat as std_concat;
#[doc(hidden)]
pub use core::convert::From as std_convert_From;
#[doc(hidden)]
pub use core::default::Default as std_default_Default;
#[doc(hidden)]
pub use core::fmt::Debug as std_fmt_Debug;
#[doc(hidden)]
pub use core::mem::take as std_mem_take;
#[doc(hidden)]
pub use core::option::Option as std_option_Option;
#[doc(hidden)]
pub use core::stringify as std_stringify;
#[doc(hidden)]
pub use dyn_context::State as dyn_context_State;
#[doc(hidden)]
pub use dyn_context::StateExt as dyn_context_StateExt;
#[doc(hidden)]
pub use generics::concat as generics_concat;
#[doc(hidden)]
pub use generics::parse as generics_parse;
#[doc(hidden)]
pub use indoc::indoc as indoc_indoc;
#[doc(hidden)]
pub use memoffset::offset_of as memoffset_offset_of;
#[doc(hidden)]
pub use paste::paste as paste_paste;
use crate::binding::*;
use alloc::boxed::Box;
use alloc::collections::VecDeque;
use alloc::vec::Vec;
use arrayvec::ArrayVec;
use components_arena::{Arena, ArenaItemsIntoValues, Component, ComponentId, Id, RawId};
use composable_allocators::Global;
use composable_allocators::fallbacked::Fallbacked;
use composable_allocators::stacked::{self};
use core::alloc::Allocator;
use core::any::{Any, TypeId};
use core::fmt::Debug;
use core::iter::once;
use core::mem::{replace, take};
use core::ops::{Deref, DerefMut};
use dyn_context::State;
use educe::Educe;
use macro_attr_2018::macro_attr;
use phantom_type::PhantomType;
macro_attr! {
#[derive(Educe, Component!(class=ItemHandlerComponent))]
#[educe(Debug)]
struct ItemHandler<ItemType: Convenient> {
handler: Box<dyn Handler<ItemChange<ItemType>>>,
update: Option<BindingBase<()>>,
}
}
macro_attr! {
#[derive(Educe, Component!(class=HandlerComponent))]
#[educe(Debug, Clone)]
struct BoxedHandler<T>(Box<dyn Handler<T>>);
}
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub struct Change<PropType: Convenient> {
pub old: PropType,
pub new: PropType,
}
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub enum ItemChangeAction<ItemType: Convenient> {
Insert { prev: Option<ItemType> },
Remove,
UpdateInsert { prev: Option<ItemType> },
UpdateRemove,
MoveInsert { prev: Option<ItemType> },
MoveRemove,
}
impl<ItemType: Convenient> ItemChangeAction<ItemType> {
pub fn is_insert(&self) -> bool {
matches!(self, ItemChangeAction::Insert { .. })
}
pub fn is_remove(&self) -> bool { self == &ItemChangeAction::Remove }
pub fn is_update_insert(&self) -> bool {
matches!(self, ItemChangeAction::UpdateInsert { .. })
}
pub fn is_update_remove(&self) -> bool { self == &ItemChangeAction::UpdateRemove }
pub fn is_move_insert(&self) -> bool {
matches!(self, ItemChangeAction::MoveInsert { .. })
}
pub fn is_move_remove(&self) -> bool { self == &ItemChangeAction::MoveRemove }
pub fn as_insert_prev(&self) -> Option<&Option<ItemType>> {
if let ItemChangeAction::Insert { prev } = self { Some(prev) } else { None }
}
pub fn as_update_insert_prev(&self) -> Option<&Option<ItemType>> {
if let ItemChangeAction::UpdateInsert { prev } = self { Some(prev) } else { None }
}
pub fn as_insert_or_update_insert_prev(&self) -> Option<&Option<ItemType>> {
match self {
ItemChangeAction::Insert { prev } => Some(prev),
ItemChangeAction::UpdateInsert { prev } => Some(prev),
_ => None
}
}
pub fn as_move_insert_prev(&self) -> Option<&Option<ItemType>> {
if let ItemChangeAction::MoveInsert { prev } = self { Some(prev) } else { None }
}
}
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub struct ItemChange<ItemType: Convenient> {
pub item: ItemType,
pub action: ItemChangeAction<ItemType>,
}
impl<ItemType: Convenient> ItemChange<ItemType> {
pub fn is_insert(&self) -> bool { self.action.is_insert() }
pub fn is_remove(&self) -> bool { self.action.is_remove() }
pub fn is_update_insert(&self) -> bool { self.action.is_update_insert() }
pub fn is_update_remove(&self) -> bool { self.action.is_update_remove() }
pub fn is_move_insert(&self) -> bool { self.action.is_move_insert() }
pub fn is_move_remove(&self) -> bool { self.action.is_move_remove() }
pub fn as_insert_prev(&self) -> Option<&Option<ItemType>> { self.action.as_insert_prev() }
pub fn as_update_insert_prev(&self) -> Option<&Option<ItemType>> { self.action.as_update_insert_prev() }
pub fn as_insert_or_update_insert_prev(&self) -> Option<&Option<ItemType>> {
self.action.as_insert_or_update_insert_prev()
}
pub fn as_move_insert_prev(&self) -> Option<&Option<ItemType>> { self.action.as_move_insert_prev() }
}
#[derive(Debug)]
struct DepPropHandlers<PropType: Convenient> {
children_has_handlers: Option<bool>,
value_handlers: Arena<BoxedHandler<PropType>>,
change_handlers: Arena<BoxedHandler<Change<PropType>>>,
change_initial_handler: Option<Box<dyn Handler<Change<PropType>>>>,
change_final_handler: Option<Box<dyn Handler<Change<PropType>>>>,
}
#[derive(Debug)]
struct DepPropHandlersCopy<PropType: Convenient> {
notify_children: bool,
value_handlers: ArenaItemsIntoValues<BoxedHandler<PropType>>,
change_handlers: ArenaItemsIntoValues<BoxedHandler<Change<PropType>>>,
change_initial_handler: Option<Box<dyn Handler<Change<PropType>>>>,
change_final_handler: Option<Box<dyn Handler<Change<PropType>>>>,
}
impl<PropType: Convenient> DepPropHandlers<PropType> {
const fn new(inherits: bool) -> Self {
DepPropHandlers {
children_has_handlers: if inherits { Some(false) } else { None },
value_handlers: Arena::new(),
change_handlers: Arena::new(),
change_initial_handler: None,
change_final_handler: None,
}
}
fn is_empty(&self) -> bool {
self.children_has_handlers != Some(true) &&
self.value_handlers.items().is_empty() &&
self.change_handlers.items().is_empty() &&
self.change_initial_handler.is_none() &&
self.change_final_handler.is_none()
}
fn take_all<A: Allocator>(&mut self, handlers: &mut Vec<Box<dyn AnyHandler>, A>) {
handlers.extend(take(&mut self.value_handlers).into_items().into_values().map(|x| x.0.into_any()));
handlers.extend(take(&mut self.change_handlers).into_items().into_values().map(|x| x.0.into_any()));
self.change_initial_handler.take().map(|x| handlers.push(x.into_any()));
self.change_final_handler.take().map(|x| handlers.push(x.into_any()));
}
fn clone(&self) -> DepPropHandlersCopy<PropType> {
DepPropHandlersCopy {
notify_children: self.children_has_handlers == Some(true),
value_handlers: Clone::clone(self.value_handlers.items()).into_values(),
change_handlers: Clone::clone(self.change_handlers.items()).into_values(),
change_initial_handler: self.change_initial_handler.clone(),
change_final_handler: self.change_final_handler.clone(),
}
}
}
impl<PropType: Convenient> DepPropHandlersCopy<PropType> {
fn execute<Owner: DepType>(
self,
state: &mut dyn State,
change: &Change<PropType>,
id: Owner::Id,
prop: DepProp<Owner, PropType>
) where Owner::Id: DepObj<Owner::DepObjKey, Owner> {
if let Some(change_initial_handler) = self.change_initial_handler {
change_initial_handler.execute(state, change.clone());
}
for handler in self.value_handlers {
handler.0.execute(state, change.new.clone());
}
for handler in self.change_handlers {
handler.0.execute(state, change.clone());
}
if let Some(change_final_handler) = self.change_final_handler {
change_final_handler.execute(state, change.clone());
}
if self.notify_children {
prop.notify_children(state, id, change);
}
}
}
mod one_stack {
use alloc::collections::VecDeque;
use either::{Either, Left, Right};
pub trait Cont: Default {
type Item;
fn with_capacity(capacity: usize) -> Self;
fn push_back(&mut self, value: Self::Item);
}
pub trait Deque: Cont {
fn pop_front(&mut self) -> Option<Self::Item>;
}
impl<T> Cont for VecDeque<T> {
type Item = T;
fn with_capacity(capacity: usize) -> Self {
VecDeque::with_capacity(capacity)
}
fn push_back(&mut self, value: Self::Item) {
self.push_back(value);
}
}
impl<T> Deque for VecDeque<T> {
fn pop_front(&mut self) -> Option<Self::Item> {
self.pop_front()
}
}
#[derive(Debug)]
pub struct OneStack<C: Cont>(Option<Either<C::Item, C>>);
impl<C: Cont> OneStack<C> {
pub const fn new() -> Self {
OneStack(None)
}
}
impl<C: Cont> const Default for OneStack<C> {
fn default() -> Self { OneStack::new() }
}
impl<C: Cont> Cont for OneStack<C> {
type Item = C::Item;
fn with_capacity(capacity: usize) -> Self {
OneStack(match capacity {
0 ..= 1 => None,
capacity => Some(Right(C::with_capacity(capacity)))
})
}
fn push_back(&mut self, value: Self::Item) {
let this = if let Some(this) = self.0.take() {
match this {
Left(one_item) => {
let mut cont = C::with_capacity(2);
cont.push_back(one_item);
cont.push_back(value);
Some(Right(cont))
},
Right(mut cont) => {
cont.push_back(value);
Some(Right(cont))
}
}
} else {
Some(Left(value))
};
self.0 = this;
}
}
impl<C: Deque> Deque for OneStack<C> {
fn pop_front(&mut self) -> Option<Self::Item> {
let (this, res) = if let Some(this) = self.0.take() {
match this {
Left(one_item) => (None, Some(one_item)),
Right(mut cont) => {
let res = cont.pop_front();
(Some(Right(cont)), res)
}
}
} else {
(None, None)
};
self.0 = this;
res
}
}
}
use one_stack::*;
#[derive(Debug)]
pub struct DepPropEntry<PropType: Convenient> {
default: &'static PropType,
style: Option<PropType>,
local: Option<PropType>,
handlers: DepPropHandlers<PropType>,
binding: Option<BindingBase<PropType>>,
queue: OneStack<VecDeque<Option<PropType>>>,
enqueue: bool,
}
impl<PropType: Convenient> DepPropEntry<PropType> {
pub const fn new(default: &'static PropType, inherits: bool) -> Self {
DepPropEntry {
default,
handlers: DepPropHandlers::new(inherits),
style: None,
local: None,
binding: None,
queue: OneStack::new(),
enqueue: false,
}
}
fn inherits(&self) -> bool { self.handlers.children_has_handlers.is_some() }
#[doc(hidden)]
pub fn take_all_handlers<A: Allocator>(&mut self, handlers: &mut Vec<Box<dyn AnyHandler>, A>) {
self.handlers.take_all(handlers);
}
#[doc(hidden)]
pub fn binding(&self) -> Option<BindingBase<PropType>> {
self.binding
}
}
#[derive(Debug)]
pub struct DepEventEntry<ArgsType: DepEventArgs> {
bubble: bool,
handlers: Arena<BoxedHandler<ArgsType>>,
}
impl<ArgsType: DepEventArgs> DepEventEntry<ArgsType> {
pub const fn new(bubble: bool) -> Self {
DepEventEntry {
bubble,
handlers: Arena::new(),
}
}
#[doc(hidden)]
pub fn take_all_handlers<A: Allocator>(&mut self, handlers: &mut Vec<Box<dyn AnyHandler>, A>) {
handlers.extend(take(&mut self.handlers).into_items().into_values().map(|x| x.0.into_any()));
}
}
#[derive(Debug)]
struct DepVecHandlers<ItemType: Convenient> {
changed_handlers: Arena<BoxedHandler<()>>,
item_handlers: Arena<ItemHandler<ItemType>>,
item_initial_final_handler: Option<ItemHandler<ItemType>>,
}
impl<ItemType: Convenient> DepVecHandlers<ItemType> {
const fn new() -> Self {
DepVecHandlers {
changed_handlers: Arena::new(),
item_handlers: Arena::new(),
item_initial_final_handler: None,
}
}
fn take_all<A: Allocator>(&mut self, handlers: &mut Vec<Box<dyn AnyHandler>, A>) {
handlers.extend(take(&mut self.changed_handlers).into_items().into_values().map(|x| x.0.into_any()));
handlers.extend(take(&mut self.item_handlers).into_items().into_values().map(|x| x.handler.into_any()));
self.item_initial_final_handler.take().map(|x| handlers.push(x.handler.into_any()));
}
fn clone(&self) -> DepVecHandlersCopy<ItemType> {
DepVecHandlersCopy {
changed_handlers: self.changed_handlers.items().clone().into_values(),
item_handlers: self.item_handlers.items().values().map(|x| x.handler.clone()).collect(),
item_initial_final_handler: self.item_initial_final_handler.as_ref().map(|x| x.handler.clone()),
}
}
}
#[derive(Debug)]
struct DepVecHandlersCopy<ItemType: Convenient> {
changed_handlers: ArenaItemsIntoValues<BoxedHandler<()>>,
item_handlers: Vec<Box<dyn Handler<ItemChange<ItemType>>>>,
item_initial_final_handler: Option<Box<dyn Handler<ItemChange<ItemType>>>>,
}
impl<ItemType: Convenient> DepVecHandlersCopy<ItemType> {
fn execute_insert(self, state: &mut dyn State, prev: Option<ItemType>, items: &[ItemType]) {
for handler in self.item_initial_final_handler.into_iter().chain(self.item_handlers) {
for (item, prev) in items.iter().zip(once(prev.as_ref()).chain(items.iter().map(Some))) {
handler.execute(state, ItemChange {
action: ItemChangeAction::Insert { prev: prev.cloned() },
item: item.clone()
});
}
}
for handler in self.changed_handlers {
handler.0.execute(state, ());
}
}
fn execute_remove(self, state: &mut dyn State, items: &[ItemType]) {
for handler in self.item_handlers.into_iter().chain(self.item_initial_final_handler.into_iter()) {
for item in items {
handler.execute(state, ItemChange { action: ItemChangeAction::Remove, item: item.clone() });
}
}
for handler in self.changed_handlers {
handler.0.execute(state, ());
}
}
fn execute_move(self, state: &mut dyn State, prev: Option<ItemType>, item: ItemType) {
for handler in self.item_handlers.iter().chain(self.item_initial_final_handler.iter()) {
handler.execute(state, ItemChange { action: ItemChangeAction::MoveRemove, item: item.clone() });
}
for handler in self.item_initial_final_handler.into_iter().chain(self.item_handlers) {
handler.execute(state, ItemChange {
action: ItemChangeAction::MoveInsert { prev: prev.clone() },
item: item.clone()
});
}
for handler in self.changed_handlers {
handler.0.execute(state, ());
}
}
}
#[derive(Debug)]
pub struct DepVecEntry<ItemType: Convenient> {
items: Vec<ItemType>,
handlers: DepVecHandlers<ItemType>,
queue: OneStack<VecDeque<DepVecModification<ItemType>>>,
enqueue: bool,
}
impl<ItemType: Convenient> DepVecEntry<ItemType> {
pub const fn new() -> Self {
DepVecEntry {
items: Vec::new(),
handlers: DepVecHandlers::new(),
queue: OneStack::new(),
enqueue: false,
}
}
#[doc(hidden)]
pub fn take_all_handlers<A: Allocator>(&mut self, handlers: &mut Vec<Box<dyn AnyHandler>, A>) {
self.handlers.take_all(handlers);
}
#[doc(hidden)]
pub fn collect_all_bindings<A: Allocator>(&self, bindings: &mut Vec<AnyBindingBase, A>) {
bindings.extend(
self.handlers.item_handlers.items().values().filter_map(|x| x.update).map(|x| {
let x: AnyBindingBase = x.into();
x
})
);
if let Some(binding) = self.handlers.item_initial_final_handler.as_ref().and_then(|x| x.update) {
bindings.push(binding.into());
}
}
}
#[derive(Debug)]
pub struct BaseDepObjCore<Owner: DepType + 'static> {
style: Option<Style<Owner>>,
added_bindings: Arena<AnyBindingBase>,
}
impl<Owner: DepType> BaseDepObjCore<Owner> {
pub const fn new() -> Self {
BaseDepObjCore {
style: None,
added_bindings: Arena::new(),
}
}
#[doc(hidden)]
pub fn collect_bindings<A: Allocator>(&self, bindings: &mut Vec<AnyBindingBase, A>) {
bindings.extend(self.added_bindings.items().values().copied());
}
}
pub trait DepObjId: ComponentId {
fn parent(self, state: &dyn State) -> Option<Self>;
fn next(self, state: &dyn State) -> Self;
fn first_child(self, state: &dyn State) -> Option<Self>;
fn add_binding_raw<Owner: DepType<Id=Self>, T: Convenient>(
self, state: &mut dyn State, binding: BindingBase<T>
) where Owner: 'static, Owner::Id: DepObj<Owner::DepObjKey, Owner> {
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, self.into_raw());
let binding_id = obj.core_base_priv_mut().added_bindings.insert(|id| (binding.into(), id));
binding.set_holder(state, Box::new(AddedBindingHolder::<Owner> { id: self, binding_id }));
}
fn add_binding<Owner: DepType<Id=Self>, T: Convenient>(
self, state: &mut dyn State, binding: impl Into<BindingBase<T>>
) where Owner: 'static, Owner::Id: DepObj<Owner::DepObjKey, Owner> {
self.add_binding_raw::<Owner, _>(state, binding.into())
}
fn apply_style<Owner: DepType<Id=Self>>(
self,
state: &mut dyn State,
style: Option<Style<Owner>>,
) -> Option<Style<Owner>> where Owner::Id: DepObj<Owner::DepObjKey, Owner> {
stacked::with_size::<256, _>(|alloc| {
let mut on_changed = Vec::new_in(Fallbacked(alloc, Global));
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, self.into_raw());
let old = obj.core_base_priv_mut().style.take();
if let Some(old) = old.as_ref() {
old.setters
.iter()
.filter(|setter| style.as_ref().map_or(
true,
|new| new.setters.binary_search_by_key(
&setter.prop_offset(),
|x| x.prop_offset()
).is_err()
))
.filter_map(|setter| setter.un_apply(state, self, true))
.for_each(|x| on_changed.push(x))
;
}
if let Some(new) = style.as_ref() {
new.setters
.iter()
.filter_map(|setter| setter.un_apply(state, self, false))
.for_each(|x| on_changed.push(x))
;
}
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, self.into_raw());
obj.core_base_priv_mut().style = style;
for on_changed in on_changed {
on_changed(state);
}
old
})
}
}
pub trait DetachedDepObjId: ComponentId { }
impl<T: DetachedDepObjId> DepObjId for T {
fn parent(self, _state: &dyn State) -> Option<Self> { None }
fn next(self, _state: &dyn State) -> Self { self }
fn first_child(self, _state: &dyn State) -> Option<Self> { None }
}
pub trait DepType: Debug {
type Id: DepObjId;
type DepObjKey: ?Sized;
#[doc(hidden)]
fn core_base_priv(&self) -> &BaseDepObjCore<Self> where Self: Sized;
#[doc(hidden)]
fn core_base_priv_mut(&mut self) -> &mut BaseDepObjCore<Self> where Self: Sized;
#[doc(hidden)]
fn take_all_handlers(&mut self, handlers: &mut Vec<Box<dyn AnyHandler>, &dyn Allocator>);
#[doc(hidden)]
fn collect_all_bindings(&self, bindings: &mut Vec<AnyBindingBase, &dyn Allocator>);
#[doc(hidden)]
fn update_parent_children_has_handlers(&self) -> fn(state: &mut dyn State, id: RawId);
}
pub trait DepEventArgs: Convenient {
fn handled(&self) -> bool;
}
#[derive(Educe)]
#[educe(Debug, Clone, Copy)]
pub struct DepEvent<Owner: DepType, ArgsType: DepEventArgs> {
offset: usize,
_phantom: PhantomType<(Owner, ArgsType)>
}
impl<Owner: DepType, ArgsType: DepEventArgs> DepEvent<Owner, ArgsType> {
pub const unsafe fn new(offset: usize) -> Self {
DepEvent { offset, _phantom: PhantomType::new() }
}
pub fn offset(self) -> usize { self.offset }
fn entry(self, owner: &Owner) -> &DepEventEntry<ArgsType> {
unsafe {
let entry = (owner as *const _ as usize).unchecked_add(self.offset);
let entry = entry as *const DepEventEntry<ArgsType>;
&*entry
}
}
fn entry_mut(self, owner: &mut Owner) -> &mut DepEventEntry<ArgsType> {
unsafe {
let entry = (owner as *mut _ as usize).unchecked_add(self.offset);
let entry = entry as *mut DepEventEntry<ArgsType>;
&mut *entry
}
}
fn raise_raw(
self, state: &mut dyn State, id: Owner::Id, args: &ArgsType
) -> bool where Owner::Id: DepObj<Owner::DepObjKey, Owner> {
let obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get(state, id.into_raw());
let entry = self.entry(&obj);
let bubble = entry.bubble;
let handlers = entry.handlers.items().clone().into_values();
for handler in handlers {
handler.0.execute(state, args.clone());
}
bubble
}
pub fn raise<X: Convenient>(
self, state: &mut dyn State, mut id: Owner::Id, args: ArgsType
) -> Re<X> where Owner::Id: DepObj<Owner::DepObjKey, Owner> {
let bubble = self.raise_raw(state, id, &args);
if !bubble || args.handled() { return Re::Continue; }
while let Some(parent) = id.parent(state) {
id = parent;
let bubble = self.raise_raw(state, id, &args);
debug_assert!(bubble);
if args.handled() { return Re::Continue; }
}
Re::Continue
}
pub fn source(self, id: Owner::Id) -> DepEventSource<Owner, ArgsType> where
Owner::Id: DepObj<Owner::DepObjKey, Owner> {
DepEventSource { id, event: self }
}
}
#[derive(Educe)]
#[educe(Debug, Clone, Copy)]
pub struct DepProp<Owner: DepType, PropType: Convenient> {
offset: usize,
_phantom: PhantomType<(Owner, PropType)>
}
impl<Owner: DepType, PropType: Convenient> DepProp<Owner, PropType> {
pub const unsafe fn new(offset: usize) -> Self {
DepProp { offset, _phantom: PhantomType::new() }
}
pub fn offset(self) -> usize { self.offset }
fn entry(self, owner: &Owner) -> &DepPropEntry<PropType> {
unsafe {
let entry = (owner as *const _ as usize).unchecked_add(self.offset);
let entry = entry as *const DepPropEntry<PropType>;
&*entry
}
}
fn entry_mut(self, owner: &mut Owner) -> &mut DepPropEntry<PropType> {
unsafe {
let entry = (owner as *mut _ as usize).unchecked_add(self.offset);
let entry = entry as *mut DepPropEntry<PropType>;
&mut *entry
}
}
fn unstyled_non_local_value<T>(
self, state: &dyn State, id: Owner::Id, f: impl FnOnce(&PropType) -> T
) -> T where Owner::Id: DepObj<Owner::DepObjKey, Owner> {
let obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get(state, id.into_raw());
let entry = self.entry(&obj);
if entry.inherits() {
if let Some(parent) = id.parent(state) {
self.current_value(state, parent, f)
} else {
f(entry.default)
}
} else {
f(entry.default)
}
}
fn non_local_value<T>(
self, state: &dyn State, id: Owner::Id, f: impl FnOnce(&PropType) -> T
) -> T where Owner::Id: DepObj<Owner::DepObjKey, Owner> {
let obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get(state, id.into_raw());
let entry = self.entry(&obj);
if let Some(value) = entry.style.as_ref() {
f(value)
} else {
self.unstyled_non_local_value(state, id, f)
}
}
fn current_value<T>(
self, state: &dyn State, id: Owner::Id, f: impl FnOnce(&PropType) -> T
) -> T where Owner::Id: DepObj<Owner::DepObjKey, Owner> {
let obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get(state, id.into_raw());
let entry = self.entry(&obj);
if let Some(value) = entry.local.as_ref() {
f(value)
} else {
self.non_local_value(state, id, f)
}
}
#[doc(hidden)]
pub fn update_parent_children_has_handlers(
self, state: &mut dyn State, id: RawId
) where Owner::Id: DepObj<Owner::DepObjKey, Owner> {
let mut id = Owner::Id::from_raw(id);
while let Some(parent) = id.parent(state) {
id = parent;
let children_has_handlers = if let Some(first_child) = id.first_child(state) {
let mut child = first_child;
loop {
let obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get(state, child.into_raw());
let entry = self.entry(&obj);
debug_assert!(entry.inherits());
if !entry.handlers.is_empty() { break true; }
child = child.next(state);
if child == first_child { break false; }
}
} else {
false
};
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, id.into_raw());
let entry_mut = self.entry_mut(&mut obj);
if children_has_handlers == entry_mut.handlers.children_has_handlers.unwrap() { return; }
entry_mut.handlers.children_has_handlers = Some(children_has_handlers);
}
}
fn notify_children(
self,
state: &mut dyn State,
id: Owner::Id,
change: &Change<PropType>,
) where Owner::Id: DepObj<Owner::DepObjKey, Owner> {
if let Some(first_child) = id.first_child(state) {
let mut child = first_child;
loop {
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, child.into_raw());
let entry_mut = self.entry_mut(&mut obj);
debug_assert!(entry_mut.inherits());
if entry_mut.local.is_none() && entry_mut.style.is_none() {
let handlers = entry_mut.handlers.clone();
handlers.execute(state, change, child, self);
}
child = child.next(state);
if child == first_child { break; }
}
}
}
fn un_set_core(
self, state: &mut dyn State, id: Owner::Id, value: Option<PropType>
) where Owner::Id: DepObj<Owner::DepObjKey, Owner> {
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, id.into_raw());
let entry_mut = self.entry_mut(&mut obj);
let old = replace(&mut entry_mut.local, value.clone());
if old == value { return; }
let handlers = entry_mut.handlers.clone();
let change = if old.is_some() && value.is_some() {
unsafe { Change { old: old.unwrap_unchecked(), new: value.unwrap_unchecked() } }
} else {
if let Some(change) = self.non_local_value(state, id, |non_local| {
let old_ref = old.as_ref().unwrap_or(non_local);
let value_ref = value.as_ref().unwrap_or(non_local);
if old_ref == value_ref {
None
} else {
let old = old.unwrap_or_else(|| non_local.clone());
let new = value.unwrap_or_else(|| non_local.clone());
Some(Change { old, new })
}
}) {
change
} else {
return;
}
};
handlers.execute(state, &change, id, self);
}
fn un_set(
self, state: &mut dyn State, id: Owner::Id, mut value: Option<PropType>
) where Owner::Id: DepObj<Owner::DepObjKey, Owner> {
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, id.into_raw());
let entry_mut = self.entry_mut(&mut obj);
if replace(&mut entry_mut.enqueue, true) {
entry_mut.queue.push_back(value);
return;
}
loop {
self.un_set_core(state, id, value);
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, id.into_raw());
let entry_mut = self.entry_mut(&mut obj);
if let Some(queue_head) = entry_mut.queue.pop_front() { value = queue_head; } else { break; }
}
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, id.into_raw());
let entry_mut = self.entry_mut(&mut obj);
entry_mut.enqueue = false;
}
pub fn set<X: Convenient>(
self, state: &mut dyn State, id: Owner::Id, value: PropType
) -> Re<X> where Owner::Id: DepObj<Owner::DepObjKey, Owner> {
self.un_set(state, id, Some(value));
Re::Continue
}
pub fn unset<X: Convenient>(
self, state: &mut dyn State, id: Owner::Id
) -> Re<X> where Owner::Id: DepObj<Owner::DepObjKey, Owner> {
self.un_set(state, id, None);
Re::Continue
}
fn bind_raw(
self,
state: &mut dyn State,
id: Owner::Id,
binding: BindingBase<PropType>
) where Owner: 'static, Owner::Id: DepObj<Owner::DepObjKey, Owner> {
self.unbind(state, id);
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, id.into_raw());
let entry_mut = self.entry_mut(&mut obj);
entry_mut.binding = Some(binding);
binding.set_target(state, Box::new(DepPropSet { prop: self, id }));
binding.set_holder(state, Box::new(DepPropSet { prop: self, id }));
}
pub fn bind(
self,
state: &mut dyn State,
id: Owner::Id,
binding: impl Into<BindingBase<PropType>>
) where Owner: 'static, Owner::Id: DepObj<Owner::DepObjKey, Owner> {
self.bind_raw(state, id, binding.into());
}
pub fn unbind(
self, state: &mut dyn State, id: Owner::Id
) where Owner::Id: DepObj<Owner::DepObjKey, Owner> {
if let Some(binding) = {
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, id.into_raw());
let entry_mut = self.entry_mut(&mut obj);
entry_mut.binding
} {
binding.drop_self(state);
}
}
fn clear_binding(self, state: &mut dyn State, id: Owner::Id) where Owner::Id: DepObj<Owner::DepObjKey, Owner> {
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, id.into_raw());
let entry_mut = self.entry_mut(&mut obj);
let ok = entry_mut.binding.take().is_some();
debug_assert!(ok);
}
pub fn value_source(self, id: Owner::Id) -> DepPropValueSource<Owner, PropType> {
DepPropValueSource { id, prop: self }
}
pub fn change_source(self, id: Owner::Id) -> DepPropChangeSource<Owner, PropType> {
DepPropChangeSource { id, prop: self }
}
pub fn change_initial_source(self, id: Owner::Id) -> DepPropChangeInitialSource<Owner, PropType> {
DepPropChangeInitialSource { id, prop: self }
}
pub fn change_final_source(self, id: Owner::Id) -> DepPropChangeFinalSource<Owner, PropType> {
DepPropChangeFinalSource { id, prop: self }
}
}
#[derive(Educe)]
#[educe(Debug, Clone)]
struct DepPropSet<Owner: DepType, PropType: Convenient> where
Owner::Id: DepObj<Owner::DepObjKey, Owner> {
id: Owner::Id,
prop: DepProp<Owner, PropType>,
}
impl<Owner: DepType, PropType: Convenient> Target<PropType> for DepPropSet<Owner, PropType> where
Owner::Id: DepObj<Owner::DepObjKey, Owner> {
fn execute(&self, state: &mut dyn State, value: PropType) {
self.prop.set(state, self.id, value).immediate();
}
}
impl<Owner: DepType, PropType: Convenient> Holder for DepPropSet<Owner, PropType> where
Owner::Id: DepObj<Owner::DepObjKey, Owner> {
fn release(&self, state: &mut dyn State) {
self.prop.clear_binding(state, self.id);
}
}
#[derive(Debug)]
enum DepVecModification<ItemType: Convenient> {
Clear,
Insert(DepVecInsertPos<ItemType>, ItemType),
Remove(DepVecItemPos<ItemType>),
Move(DepVecItemPos<ItemType>, DepVecInsertPos<ItemType>),
ExtendFrom(Vec<ItemType>),
Update(Option<Id<ItemHandler<ItemType>>>),
}
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, Hash)]
pub enum DepVecItemPos<ItemType: Convenient> {
FirstItem,
LastItem,
Item(ItemType),
}
impl<ItemType: Convenient> DepVecItemPos<ItemType> {
fn find(&self, items: &[ItemType]) -> usize {
match self {
DepVecItemPos::FirstItem => {
assert!(!items.is_empty(), "item position not found");
0
},
DepVecItemPos::LastItem => {
assert!(!items.is_empty(), "item position not found");
items.len() - 1
}
DepVecItemPos::Item(item) => {
items.iter().enumerate()
.find_map(|(i, x)| if x == item { Some(i) } else { None })
.expect("item position not found")
}
}
}
}
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, Hash)]
pub enum DepVecInsertPos<ItemType: Convenient> {
BeforeFirstItem,
AfterLastItem,
Before(ItemType),
After(ItemType)
}
impl<ItemType: Convenient> DepVecInsertPos<ItemType> {
fn find(&self, items: &[ItemType]) -> usize {
match self {
DepVecInsertPos::BeforeFirstItem => 0,
DepVecInsertPos::AfterLastItem => items.len(),
DepVecInsertPos::Before(item) => {
items.iter().enumerate()
.find_map(|(i, x)| if x == item { Some(i) } else { None })
.expect("insert position not found")
},
DepVecInsertPos::After(item) => {
1 + items.iter().enumerate()
.find_map(|(i, x)| if x == item { Some(i) } else { None })
.expect("insert position not found")
},
}
}
}
#[derive(Educe)]
#[educe(Debug, Clone, Copy)]
pub struct DepVec<Owner: DepType, ItemType: Convenient> {
offset: usize,
_phantom: PhantomType<(Owner, ItemType)>
}
impl<Owner: DepType, ItemType: Convenient> DepVec<Owner, ItemType> {
pub const unsafe fn new(offset: usize) -> Self {
DepVec { offset, _phantom: PhantomType::new() }
}
pub fn offset(self) -> usize { self.offset }
fn entry(self, owner: &Owner) -> &DepVecEntry<ItemType> {
unsafe {
let entry = (owner as *const _ as usize).unchecked_add(self.offset);
let entry = entry as *const DepVecEntry<ItemType>;
&*entry
}
}
fn entry_mut(self, owner: &mut Owner) -> &mut DepVecEntry<ItemType> {
unsafe {
let entry = (owner as *mut _ as usize).unchecked_add(self.offset);
let entry = entry as *mut DepVecEntry<ItemType>;
&mut *entry
}
}
fn modify(
self,
state: &mut dyn State,
id: Owner::Id,
mut modification: DepVecModification<ItemType>,
) where Owner::Id: DepObj<Owner::DepObjKey, Owner> {
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, id.into_raw());
let entry_mut = self.entry_mut(&mut obj);
if replace(&mut entry_mut.enqueue, true) {
entry_mut.queue.push_back(modification);
return;
}
loop {
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, id.into_raw());
let entry_mut = self.entry_mut(&mut obj);
match modification {
DepVecModification::Clear => {
let items = take(&mut entry_mut.items);
let handlers = entry_mut.handlers.clone();
handlers.execute_remove(state, &items);
},
DepVecModification::Insert(pos, item) => {
let index = pos.find(&entry_mut.items);
let prev = if index == 0 { None } else { Some(entry_mut.items[index - 1].clone()) };
entry_mut.items.insert(index, item.clone());
let handlers = entry_mut.handlers.clone();
handlers.execute_insert(state, prev, &[item]);
},
DepVecModification::Remove(pos) => {
let index = pos.find(&entry_mut.items);
let item = entry_mut.items.remove(index);
let handlers = entry_mut.handlers.clone();
handlers.execute_remove(state, &[item]);
},
DepVecModification::Move(old_pos, new_pos) => {
let old_index = old_pos.find(&entry_mut.items);
let item = entry_mut.items.remove(old_index);
let new_index = new_pos.find(&entry_mut.items);
let prev = if new_index == 0 { None } else { Some(entry_mut.items[new_index - 1].clone()) };
entry_mut.items.insert(new_index, item.clone());
let handlers = entry_mut.handlers.clone();
handlers.execute_move(state, prev, item);
},
DepVecModification::ExtendFrom(vec) => {
let prev = entry_mut.items.last().cloned();
entry_mut.items.extend_from_slice(&vec);
let handlers = entry_mut.handlers.clone();
handlers.execute_insert(state, prev, &vec);
},
DepVecModification::Update(handler_id) => {
let items = entry_mut.items.clone();
let handler = handler_id.map_or_else(
|| entry_mut.handlers.item_initial_final_handler.as_ref().unwrap().handler.clone(),
|handler_id| entry_mut.handlers.item_handlers[handler_id].handler.clone()
);
for item in &items {
handler.execute(state, ItemChange { action: ItemChangeAction::UpdateRemove, item: item.clone() });
}
for (item, prev) in items.iter().zip(once(None).chain(items.iter().map(Some))) {
handler.execute(state, ItemChange {
action: ItemChangeAction::UpdateInsert { prev: prev.cloned() },
item: item.clone()
});
}
},
};
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, id.into_raw());
let entry_mut = self.entry_mut(&mut obj);
if let Some(queue_head) = entry_mut.queue.pop_front() { modification = queue_head; } else { break; }
}
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, id.into_raw());
let entry_mut = self.entry_mut(&mut obj);
entry_mut.enqueue = false;
}
pub fn clear<X: Convenient>(
self, state: &mut dyn State, id: Owner::Id
) -> Re<X> where Owner::Id: DepObj<Owner::DepObjKey, Owner> {
self.modify(state, id, DepVecModification::Clear);
Re::Continue
}
pub fn push<X: Convenient>(
self, state: &mut dyn State, id: Owner::Id, item: ItemType
) -> Re<X> where Owner::Id: DepObj<Owner::DepObjKey, Owner> {
self.insert(state, id, DepVecInsertPos::AfterLastItem, item)
}
pub fn insert<X: Convenient>(
self,
state: &mut dyn State,
id: Owner::Id,
pos: DepVecInsertPos<ItemType>,
item: ItemType
) -> Re<X> where Owner::Id: DepObj<Owner::DepObjKey, Owner> {
self.modify(state, id, DepVecModification::Insert(pos, item));
Re::Continue
}
pub fn move_<X: Convenient>(
self,
state: &mut dyn State,
id: Owner::Id,
old_pos: DepVecItemPos<ItemType>,
new_pos: DepVecInsertPos<ItemType>
) -> Re<X> where Owner::Id: DepObj<Owner::DepObjKey, Owner> {
self.modify(state, id, DepVecModification::Move(old_pos, new_pos));
Re::Continue
}
pub fn remove<X: Convenient>(
self,
state: &mut dyn State,
id: Owner::Id,
pos: DepVecItemPos<ItemType>
) -> Re<X> where Owner::Id: DepObj<Owner::DepObjKey, Owner> {
self.modify(state, id, DepVecModification::Remove(pos));
Re::Continue
}
pub fn extend_from<X: Convenient>(
self, state: &mut dyn State, id: Owner::Id, other: Vec<ItemType>
) -> Re<X> where Owner::Id: DepObj<Owner::DepObjKey, Owner> {
self.modify(state, id, DepVecModification::ExtendFrom(other));
Re::Continue
}
pub fn changed_source(
self, id: Owner::Id
) -> DepVecChangedSource<Owner, ItemType> where Owner::Id: DepObj<Owner::DepObjKey, Owner> {
DepVecChangedSource { id, vec: self }
}
pub fn item_source(
self, id: Owner::Id
) -> DepVecItemSource<Owner, ItemType> where Owner::Id: DepObj<Owner::DepObjKey, Owner> {
DepVecItemSource { id, vec: self, update: None }
}
pub fn item_source_with_update(
self, update: impl Into<BindingBase<()>>, id: Owner::Id
) -> DepVecItemSource<Owner, ItemType> where Owner::Id: DepObj<Owner::DepObjKey, Owner> {
DepVecItemSource { id, vec: self, update: Some(update.into()) }
}
pub fn item_initial_final_source(
self, id: Owner::Id
) -> DepVecItemInitialFinalSource<Owner, ItemType> where Owner::Id: DepObj<Owner::DepObjKey, Owner> {
DepVecItemInitialFinalSource { id, vec: self, update: None }
}
pub fn item_initial_final_source_with_update(
self, update: impl Into<BindingBase<()>>, id: Owner::Id
) -> DepVecItemInitialFinalSource<Owner, ItemType> where Owner::Id: DepObj<Owner::DepObjKey, Owner> {
DepVecItemInitialFinalSource { id, vec: self, update: Some(update.into()) }
}
}
struct AddedBindingHolder<Owner: DepType> {
id: Owner::Id,
binding_id: Id<AnyBindingBase>,
}
impl<Owner: DepType + 'static> Holder for AddedBindingHolder<Owner> where
Owner::Id: DepObj<Owner::DepObjKey, Owner> {
fn release(&self, state: &mut dyn State) {
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, self.id.into_raw());
obj.core_base_priv_mut().added_bindings.remove(self.binding_id);
}
}
mod arraybox {
use core::alloc::{self };
use core::borrow::{Borrow, BorrowMut};
use core::fmt::{self, Debug, Display, Formatter};
use core::marker::Unsize;
use core::mem::{MaybeUninit, align_of, size_of};
use core::ops::{Deref, DerefMut};
use core::ptr::{self, Pointee, null};
pub unsafe trait Buf: Default {
fn as_ptr(&self) -> *const u8;
fn as_mut_ptr(&mut self) -> *mut u8;
fn align() -> usize;
fn len() -> usize;
}
macro_rules! align_n {
(
$n:literal
) => {
$crate::paste_paste! {
#[repr(C, align($n))]
pub struct [< Align $n >] <const LEN: usize>([MaybeUninit<u8>; LEN]);
impl<const LEN: usize> const Default for [< Align $n >] <LEN> {
fn default() -> Self { Self(unsafe { MaybeUninit::uninit().assume_init() }) }
}
unsafe impl<const LEN: usize> const Buf for [< Align $n >] <LEN> {
fn align() -> usize { align_of::<Self>() }
fn len() -> usize { LEN }
fn as_ptr(&self) -> *const u8 {
&raw const self.0 as *const u8
}
fn as_mut_ptr(&mut self) -> *mut u8 {
&raw mut self.0 as *mut u8
}
}
}
};
}
align_n!(1);
align_n!(2);
align_n!(4);
align_n!(8);
align_n!(16);
pub struct ArrayBox<T: ?Sized + 'static, B: Buf> {
buf: B,
metadata: <T as Pointee>::Metadata,
}
impl<T: ?Sized + 'static, B: Buf> Drop for ArrayBox<T, B> {
fn drop(&mut self) {
unsafe { ptr::drop_in_place(self.as_mut_ptr()) };
}
}
impl<T: ?Sized + 'static, B: Buf> ArrayBox<T, B> {
pub const fn new<S: Unsize<T>>(source: S) -> Self where B: ~const Buf + ~const Default {
assert!(B::align() >= align_of::<S>());
assert!(B::len() >= size_of::<S>());
let source_null_ptr: *const T = null::<S>();
let metadata = source_null_ptr.to_raw_parts().1;
let mut res = ArrayBox { buf: B::default(), metadata };
unsafe { ptr::write(res.buf.as_mut_ptr() as *mut S, source) };
res
}
pub fn as_ptr(&self) -> *const T {
let metadata = self.metadata;
ptr::from_raw_parts(self.buf.as_ptr() as *const (), metadata)
}
pub fn as_mut_ptr(&mut self) -> *mut T {
let metadata = self.metadata;
ptr::from_raw_parts_mut(self.buf.as_mut_ptr() as *mut (), metadata)
}
}
impl<T: ?Sized + 'static, B: Buf> AsRef<T> for ArrayBox<T, B> {
fn as_ref(&self) -> &T {
unsafe { &*self.as_ptr() }
}
}
impl<T: ?Sized + 'static, B: Buf> AsMut<T> for ArrayBox<T, B> {
fn as_mut(&mut self) -> &mut T {
unsafe { &mut *self.as_mut_ptr() }
}
}
impl<T: ?Sized + 'static, B: Buf> Borrow<T> for ArrayBox<T, B> {
fn borrow(&self) -> &T { self.as_ref() }
}
impl<T: ?Sized + 'static, B: Buf> BorrowMut<T> for ArrayBox<T, B> {
fn borrow_mut(&mut self) -> &mut T { self.as_mut() }
}
pub unsafe trait DynClone {
unsafe fn dyn_clone_write(&self, target: *mut u8);
unsafe fn dyn_clone_replace_drop(&self, target: *mut u8);
fn layout(&self) -> alloc::Layout;
}
impl<T: ?Sized + 'static, B: Buf> Deref for ArrayBox<T, B> {
type Target = T;
fn deref(&self) -> &T { self.as_ref() }
}
impl<T: ?Sized + 'static, B: Buf> DerefMut for ArrayBox<T, B> {
fn deref_mut(&mut self) -> &mut T { self.as_mut() }
}
unsafe impl<T: Clone> DynClone for T {
unsafe fn dyn_clone_write(&self, target: *mut u8) {
ptr::write(target as *mut T, self.clone())
}
unsafe fn dyn_clone_replace_drop(&self, target: *mut u8) {
(*(target as *mut T)).clone_from(self)
}
fn layout(&self) -> alloc::Layout {
unsafe { alloc::Layout::from_size_align_unchecked(size_of::<Self>(), align_of::<Self>()) }
}
}
impl<T: DynClone + ?Sized + 'static, B: Buf> Clone for ArrayBox<T, B> {
fn clone(&self) -> Self {
let mut res = ArrayBox { buf: B::default(), metadata: self.metadata };
unsafe { self.as_ref().dyn_clone_write(res.buf.as_mut_ptr()) };
res
}
fn clone_from(&mut self, source: &Self) {
unsafe { source.as_ref().dyn_clone_replace_drop(self.buf.as_mut_ptr()) };
}
}
impl<T: Debug + ?Sized + 'static, B: Buf> Debug for ArrayBox<T, B> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
self.as_ref().fmt(f)
}
}
impl<T: Display + ?Sized + 'static, B: Buf> Display for ArrayBox<T, B> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
self.as_ref().fmt(f)
}
}
}
use arraybox::*;
#[derive(Educe)]
#[educe(Debug, Clone)]
struct Setter<Owner: DepType, PropType: Convenient> {
prop: DepProp<Owner, PropType>,
value: PropType,
}
trait AnySetter<Owner: DepType>: Debug + DynClone {
fn prop_offset(&self) -> usize;
fn un_apply(
&self,
state: &mut dyn State,
id: Owner::Id,
unapply: bool
) -> Option<Box<dyn for<'a> FnOnce(&'a mut dyn State)>>;
}
impl<Owner: DepType + 'static, PropType: Convenient> AnySetter<Owner> for Setter<Owner, PropType> where
Owner::Id: 'static, Owner::Id: DepObj<Owner::DepObjKey, Owner> {
fn prop_offset(&self) -> usize { self.prop.offset }
fn un_apply(
&self,
state: &mut dyn State,
id: Owner::Id,
unapply: bool
) -> Option<Box<dyn for<'a> FnOnce(&'a mut dyn State)>> where {
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, id.into_raw());
let entry_mut = self.prop.entry_mut(&mut obj);
let value = if unapply { None } else { Some(self.value.clone()) };
let old = replace(&mut entry_mut.style, value.clone());
if entry_mut.local.is_some() || old == value { return None; }
let handlers = entry_mut.handlers.clone();
let change = if old.is_some() && value.is_some() {
unsafe { Change { old: old.unwrap_unchecked(), new: value.unwrap_unchecked() } }
} else {
self.prop.unstyled_non_local_value(state, id, |unstyled_non_local_value| {
let old_ref = old.as_ref().unwrap_or(unstyled_non_local_value);
let value_ref = value.as_ref().unwrap_or(unstyled_non_local_value);
if old_ref == value_ref {
None
} else {
let old = old.unwrap_or_else(|| unstyled_non_local_value.clone());
let new = value.unwrap_or_else(|| unstyled_non_local_value.clone());
Some(Change { old, new })
}
})?
};
let prop = self.prop;
Some(Box::new(move |state: &'_ mut dyn State| handlers.execute(state, &change, id, prop)))
}
}
#[cfg(target_pointer_width="32")]
type AnySetterBuf = Align4<64>;
#[cfg(target_pointer_width="64")]
type AnySetterBuf = Align8<128>;
#[derive(Educe)]
#[educe(Debug, Clone)]
pub struct Style<Owner: DepType + 'static> {
setters: ArrayVec<ArrayBox<dyn AnySetter<Owner>, AnySetterBuf>, 16>,
}
impl<Owner: DepType> const Default for Style<Owner> {
fn default() -> Self { Style::new() }
}
impl<Owner: DepType> Style<Owner> {
pub const fn new() -> Self { Style { setters: ArrayVec::new_const() } }
pub const fn capacity(&self) -> usize { self.setters.capacity() }
pub fn clear(&mut self) { self.setters.clear(); }
pub fn contains_prop<PropType: Convenient>(&self, prop: DepProp<Owner, PropType>) -> bool {
self.setters.binary_search_by_key(&prop.offset, |x| x.prop_offset()).is_ok()
}
pub fn insert<PropType: Convenient>(
&mut self,
prop: DepProp<Owner, PropType>,
value: PropType
) -> bool where Owner: 'static, Owner::Id: DepObj<Owner::DepObjKey, Owner> {
let setter = ArrayBox::new(Setter { prop, value });
match self.setters.binary_search_by_key(&prop.offset, |x| x.prop_offset()) {
Ok(index) => { self.setters[index] = setter; true }
Err(index) => { self.setters.insert(index, setter); false }
}
}
pub fn is_empty(&self) -> bool { self.setters.is_empty() }
pub fn len(&self) -> usize { self.setters.len() }
pub fn remove<PropType: Convenient>(&mut self, prop: DepProp<Owner, PropType>) -> bool {
match self.setters.binary_search_by_key(&prop.offset, |x| x.prop_offset()) {
Ok(index) => { self.setters.remove(index); true }
Err(_) => false
}
}
}
pub trait DepObjBuilder {
type Id: ComponentId;
fn state(&self) -> &dyn State;
fn state_mut(&mut self) -> &mut dyn State;
fn id(&self) -> Self::Id;
}
#[derive(Educe)]
#[educe(Debug)]
struct DepEventHandledSource<Owner: DepType, ArgsType: DepEventArgs> {
id: Owner::Id,
handler_id: Id<BoxedHandler<ArgsType>>,
event: DepEvent<Owner, ArgsType>,
}
impl<Owner: DepType, ArgsType: DepEventArgs> HandlerId for DepEventHandledSource<Owner, ArgsType> where
Owner::Id: DepObj<Owner::DepObjKey, Owner> {
fn unhandle(&self, state: &mut dyn State, _dropping_binding: AnyBindingBase) {
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, self.id.into_raw());
let entry_mut = self.event.entry_mut(&mut obj);
entry_mut.handlers.remove(self.handler_id);
}
}
#[derive(Educe)]
#[educe(Debug)]
pub struct DepEventSource<Owner: DepType, ArgsType: DepEventArgs> {
id: Owner::Id,
event: DepEvent<Owner, ArgsType>,
}
impl<Owner: DepType + 'static, ArgsType: DepEventArgs + 'static> Source for DepEventSource<Owner, ArgsType> where
Owner::Id: DepObj<Owner::DepObjKey, Owner> {
type Value = ArgsType;
type Cache = NoCache;
fn handle(
&self,
state: &mut dyn State,
handler: Box<dyn Handler<ArgsType>>,
) -> HandledSource {
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, self.id.into_raw());
let entry = self.event.entry_mut(&mut obj);
let handler_id = entry.handlers.insert(|handler_id| (BoxedHandler(handler), handler_id));
HandledSource {
handler_id: Box::new(DepEventHandledSource { handler_id, id: self.id, event: self.event }),
init: None }
}
}
#[derive(Educe)]
#[educe(Debug)]
struct DepPropHandledValueSource<Owner: DepType, PropType: Convenient> {
id: Owner::Id,
handler_id: Id<BoxedHandler<PropType>>,
prop: DepProp<Owner, PropType>,
}
impl<Owner: DepType, PropType: Convenient> HandlerId for DepPropHandledValueSource<Owner, PropType> where
Owner::Id: DepObj<Owner::DepObjKey, Owner> {
fn unhandle(&self, state: &mut dyn State, _dropping_binding: AnyBindingBase) {
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, self.id.into_raw());
let entry_mut = self.prop.entry_mut(&mut obj);
entry_mut.handlers.value_handlers.remove(self.handler_id);
if entry_mut.inherits() && entry_mut.handlers.is_empty() {
self.prop.update_parent_children_has_handlers(state, self.id.into_raw());
}
}
}
#[derive(Educe)]
#[educe(Debug)]
struct DepPropHandledChangeInitialSource<Owner: DepType, PropType: Convenient> {
id: Owner::Id,
prop: DepProp<Owner, PropType>,
}
impl<Owner: DepType, PropType: Convenient> HandlerId for DepPropHandledChangeInitialSource<Owner, PropType> where
Owner::Id: DepObj<Owner::DepObjKey, Owner> {
fn unhandle(&self, state: &mut dyn State, _dropping_binding: AnyBindingBase) {
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, self.id.into_raw());
let entry_mut = self.prop.entry_mut(&mut obj);
let handler = entry_mut.handlers.change_initial_handler.take();
debug_assert!(handler.is_some());
if entry_mut.inherits() && entry_mut.handlers.is_empty() {
self.prop.update_parent_children_has_handlers(state, self.id.into_raw());
}
}
}
#[derive(Educe)]
#[educe(Debug)]
struct DepPropHandledChangeFinalSource<Owner: DepType, PropType: Convenient> {
id: Owner::Id,
prop: DepProp<Owner, PropType>,
}
impl<Owner: DepType, PropType: Convenient> HandlerId for DepPropHandledChangeFinalSource<Owner, PropType> where
Owner::Id: DepObj<Owner::DepObjKey, Owner> {
fn unhandle(&self, state: &mut dyn State, _dropping_binding: AnyBindingBase) {
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, self.id.into_raw());
let entry_mut = self.prop.entry_mut(&mut obj);
let handler = entry_mut.handlers.change_final_handler.take();
debug_assert!(handler.is_some());
if entry_mut.inherits() && entry_mut.handlers.is_empty() {
self.prop.update_parent_children_has_handlers(state, self.id.into_raw());
}
}
}
#[derive(Educe)]
#[educe(Debug)]
struct DepPropHandledChangeSource<Owner: DepType, PropType: Convenient> {
id: Owner::Id,
handler_id: Id<BoxedHandler<Change<PropType>>>,
prop: DepProp<Owner, PropType>,
}
impl<Owner: DepType, PropType: Convenient> HandlerId for DepPropHandledChangeSource<Owner, PropType> where
Owner::Id: DepObj<Owner::DepObjKey, Owner> {
fn unhandle(&self, state: &mut dyn State, _dropping_binding: AnyBindingBase) {
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, self.id.into_raw());
let entry_mut = self.prop.entry_mut(&mut obj);
entry_mut.handlers.change_handlers.remove(self.handler_id);
if entry_mut.inherits() && entry_mut.handlers.is_empty() {
self.prop.update_parent_children_has_handlers(state, self.id.into_raw());
}
}
}
#[derive(Educe)]
#[educe(Debug)]
pub struct DepPropValueSource<Owner: DepType, PropType: Convenient> {
id: Owner::Id,
prop: DepProp<Owner, PropType>,
}
impl<Owner: DepType + 'static, PropType: Convenient> Source for DepPropValueSource<Owner, PropType> where
Owner::Id: DepObj<Owner::DepObjKey, Owner> {
type Value = PropType;
type Cache = ValueCache<PropType>;
fn handle(&self, state: &mut dyn State, handler: Box<dyn Handler<PropType>>) -> HandledSource {
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, self.id.into_raw());
let entry = self.prop.entry_mut(&mut obj);
let update_parent_children_has_handlers = entry.inherits() && entry.handlers.is_empty();
let handler_id = entry.handlers.value_handlers.insert(|handler_id| (BoxedHandler(handler), handler_id));
if update_parent_children_has_handlers {
self.prop.update_parent_children_has_handlers(state, self.id.into_raw());
}
let value = self.prop.current_value(state, self.id, |x| x.clone());
let prop = self.prop;
let id = self.id;
let init = Box::new(move |state: &mut dyn State| {
let obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get(state, id.into_raw());
let entry = prop.entry(&obj);
let handler = entry.handlers.value_handlers[handler_id].0.clone();
handler.execute(state, value);
});
HandledSource {
handler_id: Box::new(DepPropHandledValueSource { handler_id, id: self.id, prop: self.prop }),
init: Some(init)
}
}
}
#[derive(Educe)]
#[educe(Debug)]
pub struct DepPropChangeSource<Owner: DepType, PropType: Convenient> {
id: Owner::Id,
prop: DepProp<Owner, PropType>,
}
impl<Owner: DepType + 'static, PropType: Convenient> Source for DepPropChangeSource<Owner, PropType> where
Owner::Id: DepObj<Owner::DepObjKey, Owner> {
type Value = Change<PropType>;
type Cache = NoCache;
fn handle(
&self,
state: &mut dyn State,
handler: Box<dyn Handler<Change<PropType>>>,
) -> HandledSource {
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, self.id.into_raw());
let entry = self.prop.entry_mut(&mut obj);
let default_value = entry.default;
let update_parent_children_has_handlers = entry.inherits() && entry.handlers.is_empty();
let handler_id = entry.handlers.change_handlers.insert(|handler_id| (BoxedHandler(handler), handler_id));
if update_parent_children_has_handlers {
self.prop.update_parent_children_has_handlers(state, self.id.into_raw());
}
let change = self.prop.current_value(state, self.id, |value| {
if value == default_value {
None
} else {
Some(Change { old: default_value.clone(), new: value.clone() })
}
});
let init = change.map(|change| {
let prop = self.prop;
let id = self.id;
Box::new(move |state: &mut dyn State| {
let obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get(state, id.into_raw());
let entry = prop.entry(&obj);
let handler = entry.handlers.change_handlers[handler_id].0.clone();
handler.execute(state, change);
}) as _
});
HandledSource {
handler_id: Box::new(DepPropHandledChangeSource { handler_id, id: self.id, prop: self.prop }),
init
}
}
}
#[derive(Educe)]
#[educe(Debug)]
pub struct DepPropChangeInitialSource<Owner: DepType, PropType: Convenient> {
id: Owner::Id,
prop: DepProp<Owner, PropType>,
}
impl<Owner: DepType + 'static, PropType: Convenient> Source for DepPropChangeInitialSource<Owner, PropType> where
Owner::Id: DepObj<Owner::DepObjKey, Owner> {
type Value = Change<PropType>;
type Cache = NoCache;
fn handle(
&self,
state: &mut dyn State,
handler: Box<dyn Handler<Change<PropType>>>,
) -> HandledSource {
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, self.id.into_raw());
let entry = self.prop.entry_mut(&mut obj);
let default_value = entry.default;
let update_parent_children_has_handlers = entry.inherits() && entry.handlers.is_empty();
let handler = entry.handlers.change_initial_handler.replace(handler);
assert!(handler.is_none(), "duplicate initial handler");
if update_parent_children_has_handlers {
self.prop.update_parent_children_has_handlers(state, self.id.into_raw());
}
let change = self.prop.current_value(state, self.id, |value| {
if value == default_value {
None
} else {
Some(Change { old: default_value.clone(), new: value.clone() })
}
});
let init = change.map(|change| {
let prop = self.prop;
let id = self.id;
Box::new(move |state: &mut dyn State| {
let obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get(state, id.into_raw());
let entry = prop.entry(&obj);
let handler = entry.handlers.change_initial_handler.clone().unwrap();
handler.execute(state, change);
}) as _
});
HandledSource {
handler_id: Box::new(DepPropHandledChangeInitialSource { id: self.id, prop: self.prop }),
init
}
}
}
#[derive(Educe)]
#[educe(Debug)]
pub struct DepPropChangeFinalSource<Owner: DepType, PropType: Convenient> {
id: Owner::Id,
prop: DepProp<Owner, PropType>,
}
impl<Owner: DepType + 'static, PropType: Convenient> Source for DepPropChangeFinalSource<Owner, PropType> where
Owner::Id: DepObj<Owner::DepObjKey, Owner> {
type Value = Change<PropType>;
type Cache = NoCache;
fn handle(
&self,
state: &mut dyn State,
handler: Box<dyn Handler<Change<PropType>>>,
) -> HandledSource {
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, self.id.into_raw());
let entry = self.prop.entry_mut(&mut obj);
let default_value = entry.default;
let update_parent_children_has_handlers = entry.inherits() && entry.handlers.is_empty();
let handler = entry.handlers.change_final_handler.replace(handler);
assert!(handler.is_none(), "duplicate final handler");
if update_parent_children_has_handlers {
self.prop.update_parent_children_has_handlers(state, self.id.into_raw());
}
let change = self.prop.current_value(state, self.id, |value| {
if value == default_value {
None
} else {
Some(Change { old: default_value.clone(), new: value.clone() })
}
});
let init = change.map(|change| {
let prop = self.prop;
let id = self.id;
Box::new(move |state: &mut dyn State| {
let obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get(state, id.into_raw());
let entry = prop.entry(&obj);
let handler = entry.handlers.change_final_handler.clone().unwrap();
handler.execute(state, change);
}) as _
});
HandledSource {
handler_id: Box::new(DepPropHandledChangeFinalSource { id: self.id, prop: self.prop }),
init
}
}
}
#[derive(Educe)]
#[educe(Debug)]
struct DepVecChangedHandledSource<Owner: DepType, ItemType: Convenient> {
id: Owner::Id,
handler_id: Id<BoxedHandler<()>>,
vec: DepVec<Owner, ItemType>,
}
impl<Owner: DepType, ItemType: Convenient> HandlerId for DepVecChangedHandledSource<Owner, ItemType> where
Owner::Id: DepObj<Owner::DepObjKey, Owner> {
fn unhandle(&self, state: &mut dyn State, _dropping_binding: AnyBindingBase) {
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, self.id.into_raw());
let entry_mut = self.vec.entry_mut(&mut obj);
entry_mut.handlers.changed_handlers.remove(self.handler_id);
}
}
#[derive(Educe)]
#[educe(Debug)]
struct DepVecItemHandledInitialFinalSource<Owner: DepType, ItemType: Convenient> {
id: Owner::Id,
vec: DepVec<Owner, ItemType>,
}
impl<Owner: DepType, ItemType: Convenient> HandlerId for DepVecItemHandledInitialFinalSource<Owner, ItemType> where
Owner::Id: DepObj<Owner::DepObjKey, Owner> {
fn unhandle(&self, state: &mut dyn State, dropping_binding: AnyBindingBase) {
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, self.id.into_raw());
let entry_mut = self.vec.entry_mut(&mut obj);
let handler = entry_mut.handlers.item_initial_final_handler.take().unwrap();
handler.update.filter(|&x| {
let x: AnyBindingBase = x.into();
x != dropping_binding
}).map(|binding| binding.drop_self(state));
}
}
#[derive(Educe)]
#[educe(Debug)]
struct DepVecItemHandledSource<Owner: DepType, ItemType: Convenient> {
id: Owner::Id,
handler_id: Id<ItemHandler<ItemType>>,
vec: DepVec<Owner, ItemType>,
}
impl<Owner: DepType, ItemType: Convenient> HandlerId for DepVecItemHandledSource<Owner, ItemType> where
Owner::Id: DepObj<Owner::DepObjKey, Owner> {
fn unhandle(&self, state: &mut dyn State, dropping_binding: AnyBindingBase) {
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, self.id.into_raw());
let entry_mut = self.vec.entry_mut(&mut obj);
let handler = entry_mut.handlers.item_handlers.remove(self.handler_id);
handler.update.filter(|&x| {
let x: AnyBindingBase = x.into();
x != dropping_binding
}).map(|binding| binding.drop_self(state));
}
}
#[derive(Educe)]
#[educe(Debug)]
pub struct DepVecChangedSource<Owner: DepType, ItemType: Convenient> {
id: Owner::Id,
vec: DepVec<Owner, ItemType>,
}
impl<Owner: DepType + 'static, ItemType: Convenient> Source for DepVecChangedSource<Owner, ItemType> where
Owner::Id: DepObj<Owner::DepObjKey, Owner> {
type Value = ();
type Cache = NoCache;
fn handle(
&self,
state: &mut dyn State,
handler: Box<dyn Handler<()>>,
) -> HandledSource {
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, self.id.into_raw());
let entry = self.vec.entry_mut(&mut obj);
let changed = !entry.items.is_empty();
let handler_id = entry.handlers.changed_handlers.insert(|handler_id| (BoxedHandler(handler), handler_id));
let init = if changed {
let vec = self.vec;
let id = self.id;
Some(Box::new(move |state: &mut dyn State| {
let obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get(state, id.into_raw());
let entry = vec.entry(&obj);
let handler = entry.handlers.changed_handlers[handler_id].0.clone();
handler.execute(state, ());
}) as _)
} else {
None
};
HandledSource {
handler_id: Box::new(DepVecChangedHandledSource { handler_id, id: self.id, vec: self.vec }),
init
}
}
}
#[derive(Educe)]
#[educe(Debug, Clone)]
struct DepVecItemInitialFinalSourceUpdate<Owner: DepType, ItemType: Convenient> {
id: Owner::Id,
vec: DepVec<Owner, ItemType>,
}
impl<Owner: DepType, ItemType: Convenient> Target<()> for DepVecItemInitialFinalSourceUpdate<Owner, ItemType> where
Owner::Id: DepObj<Owner::DepObjKey, Owner> {
fn execute(&self, state: &mut dyn State, (): ()) {
self.vec.modify(state, self.id, DepVecModification::Update(None));
}
}
impl<Owner: DepType, ItemType: Convenient> Holder for DepVecItemInitialFinalSourceUpdate<Owner, ItemType> where
Owner::Id: DepObj<Owner::DepObjKey, Owner> {
fn release(&self, state: &mut dyn State) {
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, self.id.into_raw());
let entry = self.vec.entry_mut(&mut obj);
let ok = entry.handlers.item_initial_final_handler.as_mut().unwrap().update.take().is_some();
debug_assert!(ok);
}
}
#[derive(Educe)]
#[educe(Debug, Clone)]
struct DepVecItemSourceUpdate<Owner: DepType, ItemType: Convenient> {
id: Owner::Id,
vec: DepVec<Owner, ItemType>,
handler_id: Id<ItemHandler<ItemType>>,
}
impl<Owner: DepType, ItemType: Convenient> Target<()> for DepVecItemSourceUpdate<Owner, ItemType> where
Owner::Id: DepObj<Owner::DepObjKey, Owner> {
fn execute(&self, state: &mut dyn State, (): ()) {
self.vec.modify(state, self.id, DepVecModification::Update(Some(self.handler_id)));
}
}
impl<Owner: DepType, ItemType: Convenient> Holder for DepVecItemSourceUpdate<Owner, ItemType> where
Owner::Id: DepObj<Owner::DepObjKey, Owner> {
fn release(&self, state: &mut dyn State) {
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, self.id.into_raw());
let entry = self.vec.entry_mut(&mut obj);
let ok = entry.handlers.item_handlers[self.handler_id].update.take().is_some();
debug_assert!(ok);
}
}
#[derive(Educe)]
#[educe(Debug)]
pub struct DepVecItemSource<Owner: DepType, ItemType: Convenient> {
id: Owner::Id,
vec: DepVec<Owner, ItemType>,
update: Option<BindingBase<()>>,
}
impl<Owner: DepType + 'static, ItemType: Convenient> Source for DepVecItemSource<Owner, ItemType> where
Owner::Id: DepObj<Owner::DepObjKey, Owner> {
type Value = ItemChange<ItemType>;
type Cache = NoCache;
fn handle(
&self,
state: &mut dyn State,
handler: Box<dyn Handler<ItemChange<ItemType>>>,
) -> HandledSource {
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, self.id.into_raw());
let entry = self.vec.entry_mut(&mut obj);
let items = entry.items.clone();
let handler_id = entry.handlers.item_handlers.insert(
|handler_id| (ItemHandler { handler, update: self.update }, handler_id)
);
if let Some(update) = self.update {
update.set_target(state, Box::new(DepVecItemSourceUpdate { id: self.id, vec: self.vec, handler_id }));
update.set_holder(state, Box::new(DepVecItemSourceUpdate { id: self.id, vec: self.vec, handler_id }));
}
let init = if items.is_empty() {
None
} else {
let vec = self.vec;
let id = self.id;
Some(Box::new(move |state: &mut dyn State| {
let obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get(state, id.into_raw());
let entry = vec.entry(&obj);
let handler = entry.handlers.item_handlers[handler_id].handler.clone();
for (item, prev) in items.iter().zip(once(None).chain(items.iter().map(Some))) {
handler.execute(state, ItemChange {
action: ItemChangeAction::Insert { prev: prev.cloned() },
item: item.clone()
});
}
}) as _)
};
HandledSource {
handler_id: Box::new(DepVecItemHandledSource { handler_id, id: self.id, vec: self.vec }),
init
}
}
}
#[derive(Educe)]
#[educe(Debug)]
pub struct DepVecItemInitialFinalSource<Owner: DepType, ItemType: Convenient> {
id: Owner::Id,
vec: DepVec<Owner, ItemType>,
update: Option<BindingBase<()>>,
}
impl<Owner: DepType + 'static, ItemType: Convenient> Source for DepVecItemInitialFinalSource<Owner, ItemType> where
Owner::Id: DepObj<Owner::DepObjKey, Owner> {
type Value = ItemChange<ItemType>;
type Cache = NoCache;
fn handle(
&self,
state: &mut dyn State,
handler: Box<dyn Handler<ItemChange<ItemType>>>,
) -> HandledSource {
let mut obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get_mut(state, self.id.into_raw());
let entry = self.vec.entry_mut(&mut obj);
let items = entry.items.clone();
let handler = ItemHandler { handler, update: self.update };
assert!(entry.handlers.item_initial_final_handler.replace(handler).is_none(), "duplicate initial handler");
if let Some(update) = self.update {
update.set_target(state, Box::new(DepVecItemInitialFinalSourceUpdate { id: self.id, vec: self.vec }));
update.set_holder(state, Box::new(DepVecItemInitialFinalSourceUpdate { id: self.id, vec: self.vec }));
}
let init = if items.is_empty() {
None
} else {
let vec = self.vec;
let id = self.id;
Some(Box::new(move |state: &mut dyn State| {
let obj = <Owner::Id as DepObj<Owner::DepObjKey, Owner>>::get(state, id.into_raw());
let entry = vec.entry(&obj);
let handler = entry.handlers.item_initial_final_handler.as_ref().unwrap().handler.clone();
for (item, prev) in items.iter().zip(once(None).chain(items.iter().map(Some))) {
handler.execute(state, ItemChange {
action: ItemChangeAction::Insert { prev: prev.cloned() },
item: item.clone()
});
}
}) as _)
};
HandledSource {
handler_id: Box::new(DepVecItemHandledInitialFinalSource { id: self.id, vec: self.vec }),
init
}
}
}
pub struct DepObjRef<'a, Obj> {
state_part: &'a dyn Any,
id: RawId,
get_raw: fn(state_part: &dyn Any, id: RawId) -> &Obj,
}
impl<'a, Obj> Deref for DepObjRef<'a, Obj> {
type Target = Obj;
fn deref(&self) -> &Obj {
(self.get_raw)(self.state_part, self.id)
}
}
pub struct DepObjMut<'a, Obj> {
state_part: &'a mut dyn Any,
id: RawId,
get_raw: fn(state_part: &dyn Any, id: RawId) -> &Obj,
get_raw_mut: fn(state_part: &mut dyn Any, id: RawId) -> &mut Obj,
}
impl<'a, Obj> Deref for DepObjMut<'a, Obj> {
type Target = Obj;
fn deref(&self) -> &Obj {
(self.get_raw)(self.state_part, self.id)
}
}
impl<'a, Obj> DerefMut for DepObjMut<'a, Obj> {
fn deref_mut(&mut self) -> &mut Obj {
(self.get_raw_mut)(self.state_part, self.id)
}
}
pub trait DepObj<Key: ?Sized, Type: DepType> {
const STATE_PART: TypeId;
fn get_raw(state_part: &dyn Any, id: RawId) -> &Type;
fn get_raw_mut(state_part: &mut dyn Any, id: RawId) -> &mut Type;
fn get(state: &dyn State, id: RawId) -> DepObjRef<Type> {
DepObjRef {
id,
state_part: state.get_raw(Self::STATE_PART).unwrap_or_else(|| panic!("{:?} required", Self::STATE_PART)),
get_raw: Self::get_raw,
}
}
fn get_mut(state: &mut dyn State, id: RawId) -> DepObjMut<Type> {
DepObjMut {
id,
state_part: state.get_mut_raw(Self::STATE_PART).unwrap_or_else(|| panic!("{:?} required", Self::STATE_PART)),
get_raw: Self::get_raw,
get_raw_mut: Self::get_raw_mut,
}
}
}
pub struct Builder<'a, T: ComponentId> {
pub id: T,
pub state: &'a mut dyn State,
}
impl<'a, T: ComponentId> DepObjBuilder for Builder<'a, T> {
type Id = T;
fn id(&self) -> T { self.id }
fn state(&self) -> &dyn State { self.state }
fn state_mut(&mut self) -> &mut dyn State { self.state }
}
#[doc(hidden)]
#[macro_export]
macro_rules! unexpected_token {
() => { };
}
#[macro_export]
macro_rules! ext_builder {
(
$($token:tt)+
) => {
$crate::generics_parse! {
$crate::ext_builder_impl {
@generics
}
$($token)+
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! ext_builder_impl {
(
@generics
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
$base_builder:ty as $ext:ident [$Id:ty] {
fn $fn_name:ident (
$state:ident $(: $State:ty)?,
$id:ident $(: $Id_:ty)?
) -> ($builder:ident $(in $($builder_path:tt)+)?) {
$($e:tt)*
}
}
) => {
$crate::generics_concat! {
$crate::ext_builder_impl {
@impl
[$($g)*] [$($r)*] [$($w)*]
[$base_builder] [$ext] [$Id] [$fn_name]
[$builder] [$($($builder_path)+)?]
[$state $($State)?] [$id $($Id_)?] [$($e)*]
}
[$($g)*] [$($r)*] [$($w)*],
[] [] [where Self: Sized]
}
};
(
@generics
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
$base_builder:ty as $ext:ident [$Id:ty] {
fn $fn_name:ident () -> ($builder:ident $(in $($builder_path:tt)+)?);
}
) => {
$crate::generics_concat! {
$crate::ext_builder_impl {
@impl
[$($g)*] [$($r)*] [$($w)*]
[$base_builder] [$ext] [$Id] [$fn_name]
[$builder] [$($($builder_path)+)?]
[_state] [_id] []
}
[$($g)*] [$($r)*] [$($w)*],
[] [] [where Self: Sized]
}
};
(
@generics
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
$($token:tt)*
) => {
$crate::std_compile_error!("invalid builder extension");
};
(
@impl
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
[$base_builder:ty] [$ext:ident] [$Id:ty] [$fn_name:ident]
[$builder:ident] [$($($builder_path:tt)+)?]
[$state:ident $($State:ty)?] [$id:ident $($Id_:ty)?] [$($e:tt)*]
[$($tr_g:tt)*] [$($tr_r:tt)*] [$($tr_w:tt)*]
) => {
$crate::paste_paste! {
pub trait $ext $($tr_g)* : $crate::DepObjBuilder<Id=$Id> $($tr_w)* {
fn $fn_name (
self,
f: impl FnOnce(
$($($builder_path)+ ::)? [< $builder Builder >] < Self >
) -> $($($builder_path)+ ::)? [< $builder Builder >] < Self >
) -> Self;
}
impl $($g)* $ext $($r)* for $base_builder $($w)* {
fn $fn_name (
mut self,
f: impl FnOnce(
$($($builder_path)+ ::)? [< $builder Builder >] < Self >
) -> $($($builder_path)+ ::)? [< $builder Builder >] < Self >
) -> Self {
{
let $id $(: $Id_)? = <Self as $crate::DepObjBuilder>::id(&self);
let $state $(: $State)? = <Self as $crate::DepObjBuilder>::state_mut(&mut self);
$($e)*
}
f($($($builder_path)+ ::)? [< $builder Builder >] ::<Self> (self)).0
}
}
}
};
}
#[macro_export]
macro_rules! with_builder {
(
) => {
pub fn build(
self,
state: &mut dyn $crate::dyn_context_State,
f: impl for<'builder_lt> FnOnce(
$crate::Builder<'builder_lt, Self>
) -> $crate::Builder<'builder_lt, Self>
) -> Self {
f($crate::Builder { state, id: self });
self
}
};
(
$builder:ident $(in $($builder_path:tt)+)?
) => {
$crate::paste_paste! {
pub fn build(
self,
state: &mut dyn $crate::dyn_context_State,
f: impl for<'builder_lt> FnOnce(
$($($builder_path)+ ::)? [< $builder Builder >] < $crate::Builder <'builder_lt, Self> >
) -> $($($builder_path)+ ::)? [< $builder Builder >] < $crate::Builder <'builder_lt, Self> >
) -> Self {
let base_builder = $crate::Builder { state, id: self };
f(
$($($builder_path)+ ::)? [< $builder Builder >] ::< $crate::Builder <'_, Self> >
(base_builder)
);
self
}
}
};
}
#[macro_export]
macro_rules! dep_type {
(
$($token:tt)*
) => {
$crate::dep_type_impl! { $($token)* }
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! dep_type_impl {
(
$(#[$attr:meta])* $vis:vis struct $name:ident $($body:tt)*
) => {
$crate::generics_parse! {
$crate::dep_type_impl {
@struct
[Base]
[$([$attr])*] [$vis] [$name]
}
$($body)*
}
};
(
@struct
[$BaseBuilder:ident]
[$([$attr:meta])*] [$vis:vis] [$name:ident]
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
= $Id:ty [$DepObjKey:ty]
{
$($($(#[$inherits:tt])* $field:ident $delim:tt $($field_ty:ty $(= $field_val:expr)?)?),+ $(,)?)?
}
) => {
$crate::dep_type_impl! {
@concat_generics
[$([$attr])*] [$vis] [$name] [id] [$Id] [$DepObjKey]
[$($g)*] [$($r)*] [$($w)*]
[$BaseBuilder]
[$($([[$($inherits)*] $field $delim $($field_ty $(= $field_val)?)?])+)?]
}
};
(
@struct
[$BaseBuilder:ident]
[$([$attr:meta])*] [$vis:vis] [$name:ident]
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
= $Id:ty [$DepObjKey:ty]
{
$($($(#[$inherits:tt])* $field:ident $delim:tt $($field_ty:ty $(= $field_val:expr)?)?),+ $(,)?)?
}
$token:tt $($tail:tt)*
) => {
$crate::unexpected_token!($token);
$crate::std_compile_error!("unexpected extra tokens after dep type definition");
};
(
@struct
[$BaseBuilder:ident]
[$([$attr:meta])*] [$vis:vis] [$name:ident]
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
$($token:tt)+
) => {
$crate::std_compile_error!($crate::indoc_indoc!("
invalid dep type definition, allowed form is
$(#[$attr:meta])* $vis:vis struct $name:ident
$(
= $Id:ty [$DepObjKey:ty]
|
<$generics> = $Id:ty [$DepObjKey:ty] $(where $where_clause)?
)
{
$($(
$(#[$field_attr:meta])* $field_name:ident
$(
: $field_type:ty = $field_value:expr
|
[$vec_field_item_type:ty]
|
yield $event_field_type:ty
)
),+ $(,)?)?
}
"));
};
(
@struct
[$BaseBuilder:ident]
[$([$attr:meta])*] [$vis:vis] [$name:ident]
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
) => {
$crate::std_compile_error!($crate::indoc_indoc!("
invalid dep type definition, allowed form is
$(#[$attr:meta])* $vis:vis struct $name:ident
$(
= $Id:ty [$DepObjKey:ty]
|
<$generics> = $Id:ty [$DepObjKey:ty] $(where $where_clause)?
)
{
$($(
$(#[$field_attr:meta])* $field_name:ident
$(
: $field_type:ty = $field_value:expr
|
[$vec_field_item_type:ty]
|
yield $event_field_type:ty
)
),+ $(,)?)?
}
"));
};
(
@concat_generics
[$([$attr:meta])*] [$vis:vis] [$name:ident] [$id:ident] [$Id:ty] [$DepObjKey:ty]
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
[$BaseBuilder:ident]
[$([[$($inherits:tt)*] $field:ident $delim:tt $($field_ty:ty $(= $field_val:expr)?)?])*]
) => {
$crate::generics_concat! {
$crate::dep_type_impl {
@concat_generics_done
[$BaseBuilder]
[$([$attr])*] [$vis] [$name] [$id] [$Id] [$DepObjKey]
[$($g)*] [$($r)*] [$($w)*]
[$([[$($inherits)*] $field $delim $($field_ty $(= $field_val)?)?])*]
}
[ < $BaseBuilder : $crate::DepObjBuilder <Id= $Id > > ] [ < $BaseBuilder > ] [],
[$($g)*] [$($r)*] [$($w)*]
}
};
(
@concat_generics_done
[$BaseBuilder:ident]
[$([$attr:meta])*] [$vis:vis] [$name:ident] [$id:ident] [$Id:ty] [$DepObjKey:ty]
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
[$([[$($inherits:tt)*] $field:ident $delim:tt $($field_ty:ty $(= $field_val:expr)?)?])*]
[$($bc_g:tt)*] [$($bc_r:tt)*] [$($bc_w:tt)*]
) => {
$crate::dep_type_impl! {
@unroll_fields
[$([$attr])*] [$vis] [$name] [$id] [$Id] [$DepObjKey] [state] [this] [bindings] [handlers]
[$($g)*] [$($r)*] [$($w)*]
[] [] [] [] [] [] []
[$BaseBuilder] [$($bc_g)*] [$($bc_r)*] [$($bc_w)*] []
[$([[$($inherits)*] $field $delim $($field_ty $(= $field_val)?)?])*]
}
};
(
@unroll_fields
[$([$attr:meta])*] [$vis:vis] [$name:ident] [$id:ident] [$Id:ty] [$DepObjKey:ty]
[$state:ident] [$this:ident] [$bindings:ident] [$handlers:ident]
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
[$($core_fields:tt)*]
[$($core_new:tt)*]
[$($core_consts:tt)*]
[$($dep_props:tt)*]
[$($core_bindings:tt)*]
[$($core_handlers:tt)*]
[$($update_handlers:tt)*]
[$BaseBuilder:ident] [$($bc_g:tt)*] [$($bc_r:tt)*] [$($bc_w:tt)*]
[$($builder_methods:tt)*]
[[[ref inherits] $field:ident : $field_ty:ty = $field_val:expr] $($fields:tt)*]
) => {
$crate::dep_type_impl! {
@unroll_fields
[$([$attr])*] [$vis] [$name] [$id] [$Id] [$DepObjKey]
[$state] [$this] [$bindings] [$handlers]
[$($g)*] [$($r)*] [$($w)*]
[
$($core_fields)*
$field: $crate::DepPropEntry<$field_ty>,
]
[
$($core_new)*
$field: $crate::DepPropEntry::new(&Self:: [< $field:upper _DEFAULT >] , true),
]
[
$($core_consts)*
const [< $field:upper _DEFAULT >] : $field_ty = $field_val;
]
[
$($dep_props)*
$vis const [< $field:upper >] : $crate::DepProp<Self, $field_ty> = {
unsafe {
let offset = $crate::memoffset_offset_of!( [< $name Core >] $($r)*, $field );
$crate::DepProp::new(offset)
}
};
]
[
$($core_bindings)*
$this . $field .binding().map(|x| $bindings.push(
<$crate::binding::AnyBindingBase as $crate::std_convert_From<$crate::binding::BindingBase<$field_ty>>>::from(x)
));
]
[
$($core_handlers)*
$this . $field .take_all_handlers($handlers);
]
[
$($update_handlers)*
$name:: [< $field:upper >] .update_parent_children_has_handlers($state, $id);
]
[$BaseBuilder] [$($bc_g)*] [$($bc_r)*] [$($bc_w)*]
[
$($builder_methods)*
#[allow(dead_code)]
$vis fn [< $field _ref >] (mut self, value: $field_ty) -> Self {
let id = <Self as $crate::DepObjBuilder>::id(&self);
let state = <Self as $crate::DepObjBuilder>::state_mut(&mut self);
$name:: [< $field:upper >] .set(state, id, value).immediate();
self
}
]
[$($fields)*]
}
};
(
@unroll_fields
[$([$attr:meta])*] [$vis:vis] [$name:ident] [$id:ident] [$Id:ty] [$DepObjKey:ty]
[$state:ident] [$this:ident] [$bindings:ident] [$handlers:ident]
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
[$($core_fields:tt)*]
[$($core_new:tt)*]
[$($core_consts:tt)*]
[$($dep_props:tt)*]
[$($core_bindings:tt)*]
[$($core_handlers:tt)*]
[$($update_handlers:tt)*]
[$BaseBuilder:ident] [$($bc_g:tt)*] [$($bc_r:tt)*] [$($bc_w:tt)*]
[$($builder_methods:tt)*]
[[[inherits ref] $field:ident : $field_ty:ty = $field_val:expr] $($fields:tt)*]
) => {
$crate::dep_type_impl! {
@unroll_fields
[$([$attr])*] [$vis] [$name] [$id] [$Id] [$DepObjKey] [$state] [$this] [$bindings] [$handlers]
[$($g)*] [$($r)*] [$($w)*]
[
$($core_fields)*
$field: $crate::DepPropEntry<$field_ty>,
]
[
$($core_new)*
$field: $crate::DepPropEntry::new(&Self:: [< $field:upper _DEFAULT >] , true),
]
[
$($core_consts)*
const [< $field:upper _DEFAULT >] : $field_ty = $field_val;
]
[
$($dep_props)*
$vis const [< $field:upper >] : $crate::DepProp<Self, $field_ty> = {
unsafe {
let offset = $crate::memoffset_offset_of!( [< $name Core >] $($r)*, $field );
$crate::DepProp::new(offset)
}
};
]
[
$($core_bindings)*
$this . $field .binding().map(|x| $bindings.push(
<$crate::binding::AnyBindingBase as $crate::std_convert_From<$crate::binding::BindingBase<$field_ty>>>::from(x)
));
]
[
$($core_handlers)*
$this . $field .take_all_handlers($handlers);
]
[
$($update_handlers)*
$name:: [< $field:upper >] .update_parent_children_has_handlers($state, $id);
]
[$BaseBuilder] [$($bc_g)*] [$($bc_r)*] [$($bc_w)*]
[
$($builder_methods)*
#[allow(dead_code)]
$vis fn [< $field _ref >] (mut self, value: $field_ty) -> Self {
let id = <Self as $crate::DepObjBuilder>::id(&self);
let state = <Self as $crate::DepObjBuilder>::state_mut(&mut self);
$name:: [< $field:upper >] .set(state, id, value).immediate();
self
}
]
[$($fields)*]
}
};
(
@unroll_fields
[$([$attr:meta])*] [$vis:vis] [$name:ident] [$id:ident] [$Id:ty] [$DepObjKey:ty]
[$state:ident] [$this:ident] [$bindings:ident] [$handlers:ident]
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
[$($core_fields:tt)*]
[$($core_new:tt)*]
[$($core_consts:tt)*]
[$($dep_props:tt)*]
[$($core_bindings:tt)*]
[$($core_handlers:tt)*]
[$($update_handlers:tt)*]
[$BaseBuilder:ident] [$($bc_g:tt)*] [$($bc_r:tt)*] [$($bc_w:tt)*]
[$($builder_methods:tt)*]
[[[inherits] $field:ident : $field_ty:ty = $field_val:expr] $($fields:tt)*]
) => {
$crate::dep_type_impl! {
@unroll_fields
[$([$attr])*] [$vis] [$name] [$id] [$Id] [$DepObjKey] [$state] [$this] [$bindings] [$handlers]
[$($g)*] [$($r)*] [$($w)*]
[
$($core_fields)*
$field: $crate::DepPropEntry<$field_ty>,
]
[
$($core_new)*
$field: $crate::DepPropEntry::new(&Self:: [< $field:upper _DEFAULT >] , true),
]
[
$($core_consts)*
const [< $field:upper _DEFAULT >] : $field_ty = $field_val;
]
[
$($dep_props)*
$vis const [< $field:upper >] : $crate::DepProp<Self, $field_ty> = {
unsafe {
let offset = $crate::memoffset_offset_of!( [< $name Core >] $($r)*, $field );
$crate::DepProp::new(offset)
}
};
]
[
$($core_bindings)*
$this . $field .binding().map(|x| $bindings.push(
<$crate::binding::AnyBindingBase as $crate::std_convert_From<$crate::binding::BindingBase<$field_ty>>>::from(x)
));
]
[
$($core_handlers)*
$this . $field .take_all_handlers($handlers);
]
[
$($update_handlers)*
$name:: [< $field:upper >] .update_parent_children_has_handlers($state, $id);
]
[$BaseBuilder] [$($bc_g)*] [$($bc_r)*] [$($bc_w)*]
[
$($builder_methods)*
#[allow(dead_code)]
$vis fn $field(mut self, value: $field_ty) -> Self {
let id = <Self as $crate::DepObjBuilder>::id(&self);
let state = <Self as $crate::DepObjBuilder>::state_mut(&mut self);
$name:: [< $field:upper >] .set(state, id, value).immediate();
self
}
]
[$($fields)*]
}
};
(
@unroll_fields
[$([$attr:meta])*] [$vis:vis] [$name:ident] [$id:ident] [$Id:ty] [$DepObjKey:ty]
[$state:ident] [$this:ident] [$bindings:ident] [$handlers:ident]
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
[$($core_fields:tt)*]
[$($core_new:tt)*]
[$($core_consts:tt)*]
[$($dep_props:tt)*]
[$($core_bindings:tt)*]
[$($core_handlers:tt)*]
[$($update_handlers:tt)*]
[$BaseBuilder:ident] [$($bc_g:tt)*] [$($bc_r:tt)*] [$($bc_w:tt)*]
[$($builder_methods:tt)*]
[[[ref] $field:ident : $field_ty:ty = $field_val:expr] $($fields:tt)*]
) => {
$crate::dep_type_impl! {
@unroll_fields
[$([$attr])*] [$vis] [$name] [$id] [$Id] [$DepObjKey] [$state] [$this] [$bindings] [$handlers]
[$($g)*] [$($r)*] [$($w)*]
[
$($core_fields)*
$field: $crate::DepPropEntry<$field_ty>,
]
[
$($core_new)*
$field: $crate::DepPropEntry::new(&Self:: [< $field:upper _DEFAULT >] , false),
]
[
$($core_consts)*
const [< $field:upper _DEFAULT >] : $field_ty = $field_val;
]
[
$($dep_props)*
$vis const [< $field:upper >] : $crate::DepProp<Self, $field_ty> = {
unsafe {
let offset = $crate::memoffset_offset_of!( [< $name Core >] $($r)*, $field );
$crate::DepProp::new(offset)
}
};
]
[
$($core_bindings)*
$this . $field .binding().map(|x| $bindings.push(
<$crate::binding::AnyBindingBase as $crate::std_convert_From<$crate::binding::BindingBase<$field_ty>>>::from(x)
));
]
[
$($core_handlers)*
$this . $field .take_all_handlers($handlers);
]
[
$($update_handlers)*
]
[$BaseBuilder] [$($bc_g)*] [$($bc_r)*] [$($bc_w)*]
[
$($builder_methods)*
#[allow(dead_code)]
$vis fn [< $field _ref >] (mut self, value: $field_ty) -> Self {
let id = <Self as $crate::DepObjBuilder>::id(&self);
let state = <Self as $crate::DepObjBuilder>::state_mut(&mut self);
$name:: [< $field:upper >] .set(state, id, value).immediate();
self
}
]
[$($fields)*]
}
};
(
@unroll_fields
[$([$attr:meta])*] [$vis:vis] [$name:ident] [$id:ident] [$Id:ty] [$DepObjKey:ty]
[$state:ident] [$this:ident] [$bindings:ident] [$handlers:ident]
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
[$($core_fields:tt)*]
[$($core_new:tt)*]
[$($core_consts:tt)*]
[$($dep_props:tt)*]
[$($core_bindings:tt)*]
[$($core_handlers:tt)*]
[$($update_handlers:tt)*]
[$BaseBuilder:ident] [$($bc_g:tt)*] [$($bc_r:tt)*] [$($bc_w:tt)*]
[$($builder_methods:tt)*]
[[[] $field:ident : $field_ty:ty = $field_val:expr] $($fields:tt)*]
) => {
$crate::dep_type_impl! {
@unroll_fields
[$([$attr])*] [$vis] [$name] [$id] [$Id] [$DepObjKey] [$state] [$this] [$bindings] [$handlers]
[$($g)*] [$($r)*] [$($w)*]
[
$($core_fields)*
$field: $crate::DepPropEntry<$field_ty>,
]
[
$($core_new)*
$field: $crate::DepPropEntry::new(&Self:: [< $field:upper _DEFAULT >] , false),
]
[
$($core_consts)*
const [< $field:upper _DEFAULT >] : $field_ty = $field_val;
]
[
$($dep_props)*
$vis const [< $field:upper >] : $crate::DepProp<Self, $field_ty> = {
unsafe {
let offset = $crate::memoffset_offset_of!( [< $name Core >] $($r)*, $field );
$crate::DepProp::new(offset)
}
};
]
[
$($core_bindings)*
$this . $field .binding().map(|x| $bindings.push(
<$crate::binding::AnyBindingBase as $crate::std_convert_From<$crate::binding::BindingBase<$field_ty>>>::from(x)
));
]
[
$($core_handlers)*
$this . $field .take_all_handlers($handlers);
]
[
$($update_handlers)*
]
[$BaseBuilder] [$($bc_g)*] [$($bc_r)*] [$($bc_w)*]
[
$($builder_methods)*
#[allow(dead_code)]
$vis fn $field(mut self, value: $field_ty) -> Self {
let id = <Self as $crate::DepObjBuilder>::id(&self);
let state = <Self as $crate::DepObjBuilder>::state_mut(&mut self);
$name:: [< $field:upper >] .set(state, id, value).immediate();
self
}
]
[$($fields)*]
}
};
(
@unroll_fields
[$([$attr:meta])*] [$vis:vis] [$name:ident] [$id:ident] [$Id:ty] [$DepObjKey:ty]
[$state:ident] [$this:ident] [$bindings:ident] [$handlers:ident]
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
[$($core_fields:tt)*]
[$($core_new:tt)*]
[$($core_consts:tt)*]
[$($dep_props:tt)*]
[$($core_bindings:tt)*]
[$($core_handlers:tt)*]
[$($update_handlers:tt)*]
[$(
[$BaseBuilder:ident] [$($bc_g:tt)*] [$($bc_r:tt)*] [$($bc_w:tt)*]
[$($builder_methods:tt)*]
)?]
[[[$($inherits:tt)*] $field:ident : $field_ty:ty = $field_val:expr] $($fields:tt)*]
) => {
$crate::std_compile_error!($crate::std_concat!(
"invalid dep type property attributes: '",
$crate::std_stringify!($(#[$inherits])*),
"'; allowed attributes are: '#[inherits]', '#[ref]'"
));
};
(
@unroll_fields
[$([$attr:meta])*] [$vis:vis] [$name:ident] [$id:ident] [$Id:ty] [$DepObjKey:ty]
[$state:ident] [$this:ident] [$bindings:ident] [$handlers:ident]
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
[$($core_fields:tt)*]
[$($core_new:tt)*]
[$($core_consts:tt)*]
[$($dep_props:tt)*]
[$($core_bindings:tt)*]
[$($core_handlers:tt)*]
[$($update_handlers:tt)*]
[$BaseBuilder:ident] [$($bc_g:tt)*] [$($bc_r:tt)*] [$($bc_w:tt)*]
[$($builder_methods:tt)*]
[[[bubble] $field:ident yield $field_ty:ty] $($fields:tt)*]
) => {
$crate::dep_type_impl! {
@unroll_fields
[$([$attr])*] [$vis] [$name] [$id] [$Id] [$DepObjKey] [$state] [$this] [$bindings] [$handlers]
[$($g)*] [$($r)*] [$($w)*]
[
$($core_fields)*
$field: $crate::DepEventEntry<$field_ty>,
]
[
$($core_new)*
$field: $crate::DepEventEntry::new(true),
]
[
$($core_consts)*
]
[
$($dep_props)*
$vis const [< $field:upper >] : $crate::DepEvent<Self, $field_ty> = {
unsafe {
let offset = $crate::memoffset_offset_of!( [< $name Core >] $($r)*, $field );
$crate::DepEvent::new(offset)
}
};
]
[
$($core_bindings)*
]
[
$($core_handlers)*
$this . $field .take_all_handlers($handlers);
]
[
$($update_handlers)*
]
[$BaseBuilder] [$($bc_g)*] [$($bc_r)*] [$($bc_w)*]
[
$($builder_methods)*
]
[$($fields)*]
}
};
(
@unroll_fields
[$([$attr:meta])*] [$vis:vis] [$name:ident] [$id:ident] [$Id:ty] [$DepObjKey:ty]
[$state:ident] [$this:ident] [$bindings:ident] [$handlers:ident]
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
[$($core_fields:tt)*]
[$($core_new:tt)*]
[$($core_consts:tt)*]
[$($dep_props:tt)*]
[$($core_bindings:tt)*]
[$($core_handlers:tt)*]
[$($update_handlers:tt)*]
[$BaseBuilder:ident] [$($bc_g:tt)*] [$($bc_r:tt)*] [$($bc_w:tt)*]
[$($builder_methods:tt)*]
[[[] $field:ident yield $field_ty:ty] $($fields:tt)*]
) => {
$crate::dep_type_impl! {
@unroll_fields
[$([$attr])*] [$vis] [$name] [$id] [$Id] [$DepObjKey] [$state] [$this] [$bindings] [$handlers]
[$($g)*] [$($r)*] [$($w)*]
[
$($core_fields)*
$field: $crate::DepEventEntry<$field_ty>,
]
[
$($core_new)*
$field: $crate::DepEventEntry::new(false),
]
[
$($core_consts)*
]
[
$($dep_props)*
$vis const [< $field:upper >] : $crate::DepEvent<Self, $field_ty> = {
unsafe {
let offset = $crate::memoffset_offset_of!( [< $name Core >] $($r)*, $field );
$crate::DepEvent::new(offset)
}
};
]
[
$($core_bindings)*
]
[
$($core_handlers)*
$this . $field .take_all_handlers($handlers);
]
[
$($update_handlers)*
]
[$BaseBuilder] [$($bc_g)*] [$($bc_r)*] [$($bc_w)*]
[
$($builder_methods)*
]
[$($fields)*]
}
};
(
@unroll_fields
[$([$attr:meta])*] [$vis:vis] [$name:ident] [$id:ident] [$Id:ty] [$DepObjKey:ty]
[$state:ident] [$this:ident] [$bindings:ident] [$handlers:ident]
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
[$($core_fields:tt)*]
[$($core_new:tt)*]
[$($core_consts:tt)*]
[$($dep_props:tt)*]
[$($core_bindings:tt)*]
[$($core_handlers:tt)*]
[$($update_handlers:tt)*]
[$BaseBuilder:ident] [$($bc_g:tt)*] [$($bc_r:tt)*] [$($bc_w:tt)*]
[$($builder_methods:tt)*]
[[[$($inherits:tt)*] $field:ident yield $field_ty:ty] $($fields:tt)*]
) => {
$crate::std_compile_error!($crate::std_concat!(
"invalid dep type event attributes: '",
$crate::std_stringify!($(#[$inherits])*),
"'; allowed attributes are: '#[bubble]'"
));
};
(
@unroll_fields
[$([$attr:meta])*] [$vis:vis] [$name:ident] [$id:ident] [$Id:ty] [$DepObjKey:ty]
[$state:ident] [$this:ident] [$bindings:ident] [$handlers:ident]
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
[$($core_fields:tt)*]
[$($core_new:tt)*]
[$($core_consts:tt)*]
[$($dep_props:tt)*]
[$($core_bindings:tt)*]
[$($core_handlers:tt)*]
[$($update_handlers:tt)*]
[$BaseBuilder:ident] [$($bc_g:tt)*] [$($bc_r:tt)*] [$($bc_w:tt)*]
[$($builder_methods:tt)*]
[[[] $field:ident [$field_ty:ty]] $($fields:tt)*]
) => {
$crate::dep_type_impl! {
@unroll_fields
[$([$attr])*] [$vis] [$name] [$id] [$Id] [$DepObjKey] [$state] [$this] [$bindings] [$handlers]
[$($g)*] [$($r)*] [$($w)*]
[
$($core_fields)*
$field: $crate::DepVecEntry<$field_ty>,
]
[
$($core_new)*
$field: $crate::DepVecEntry::new(),
]
[
$($core_consts)*
]
[
$($dep_props)*
$vis const [< $field:upper >] : $crate::DepVec<Self, $field_ty> = {
unsafe {
let offset = $crate::memoffset_offset_of!( [< $name Core >] $($r)*, $field );
$crate::DepVec::new(offset)
}
};
]
[
$($core_bindings)*
$this . $field .collect_all_bindings($bindings);
]
[
$($core_handlers)*
$this . $field .take_all_handlers($handlers);
]
[
$($update_handlers)*
]
[$BaseBuilder] [$($bc_g)*] [$($bc_r)*] [$($bc_w)*]
[
$($builder_methods)*
]
[$($fields)*]
}
};
(
@unroll_fields
[$([$attr:meta])*] [$vis:vis] [$name:ident] [$id:ident] [$Id:ty] [$DepObjKey:ty]
[$state:ident] [$this:ident] [$bindings:ident] [$handlers:ident]
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
[$($core_fields:tt)*]
[$($core_new:tt)*]
[$($core_consts:tt)*]
[$($dep_props:tt)*]
[$($core_bindings:tt)*]
[$($core_handlers:tt)*]
[$($update_handlers:tt)*]
[$BaseBuilder:ident] [$($bc_g:tt)*] [$($bc_r:tt)*] [$($bc_w:tt)*]
[$($builder_methods:tt)*]
[[[$($inherits:tt)*] $field:ident [$field_ty:ty]] $($fields:tt)*]
) => {
$crate::std_compile_error!($crate::std_concat!(
"unexpected dep type vector property attributes: '",
$crate::std_stringify!($(#[$inherits])*),
"'"
));
};
(
@unroll_fields
[$([$attr:meta])*] [$vis:vis] [$name:ident] [$id:ident] [$Id:ty] [$DepObjKey:ty]
[$state:ident] [$this:ident] [$bindings:ident] [$handlers:ident]
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
[$($core_fields:tt)*]
[$($core_new:tt)*]
[$($core_consts:tt)*]
[$($dep_props:tt)*]
[$($core_bindings:tt)*]
[$($core_handlers:tt)*]
[$($update_handlers:tt)*]
[$BaseBuilder:ident] [$($bc_g:tt)*] [$($bc_r:tt)*] [$($bc_w:tt)*]
[$($builder_methods:tt)*]
[[[$($inherits:tt)*] $field:ident $delim:tt $field_ty:ty $(= $field_val:expr)?] $($fields:tt)*]
) => {
$crate::std_compile_error!($crate::std_concat!(
"invalid dep type field definition\n\n",
$crate::std_stringify!($(#[$inherits])? $field $delim $field_ty $(= $field_val)?),
"\n\n",
$crate::indoc_indoc!("
allowed forms are
$(#[$field_attr:meta])* $field_name:ident : $field_type:ty = $field_value:expr
$(#[$field_attr:meta])* $field_name:ident [$vec_field_item_type:ty]
$(#[$field_attr:meta])* $field_name:ident yield $event_field_type:ty
")
));
};
(
@unroll_fields
[$([$attr:meta])*] [$vis:vis] [$name:ident] [$id:ident] [$Id:ty] [$DepObjKey:ty]
[$state:ident] [$this:ident] [$bindings:ident] [$handlers:ident]
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
[$($core_fields:tt)*]
[$($core_new:tt)*]
[$($core_consts:tt)*]
[$($dep_props:tt)*]
[$($core_bindings:tt)*]
[$($core_handlers:tt)*]
[$($update_handlers:tt)*]
[$BaseBuilder:ident] [$($bc_g:tt)*] [$($bc_r:tt)*] [$($bc_w:tt)*]
[$($builder_methods:tt)*]
[]
) => {
$crate::paste_paste! {
#[derive($crate::std_fmt_Debug)]
struct [< $name Core >] $($g)* $($w)* {
dep_type_core_base: $crate::BaseDepObjCore<$name $($r)*>,
$($core_fields)*
}
impl $($g)* [< $name Core >] $($r)* $($w)* {
const fn new() -> Self {
Self {
dep_type_core_base: $crate::BaseDepObjCore::new(),
$($core_new)*
}
}
$($core_consts)*
fn dep_type_core_take_all_handlers(
&mut self,
$handlers: &mut $crate::std_vec_Vec<
$crate::std_boxed_Box<dyn $crate::binding::AnyHandler>,
&dyn $crate::std_alloc_Allocator
>
) {
let $this = self;
$($core_handlers)*
}
fn dep_type_core_collect_all_bindings(
&self,
$bindings: &mut $crate::std_vec_Vec<
$crate::binding::AnyBindingBase,
&dyn $crate::std_alloc_Allocator
>
) {
self.dep_type_core_base.collect_bindings($bindings);
let $this = self;
$($core_bindings)*
}
}
$( #[ $attr ] )*
$vis struct $name $($g)* $($w)* {
core: [< $name Core >] $($r)*
}
impl $($g)* $name $($r)* $($w)* {
const fn new_priv() -> Self {
Self { core: [< $name Core >] ::new() }
}
#[allow(unused_variables)]
fn update_parent_children_has_handlers(
$state: &mut dyn $crate::dyn_context_State,
$id: $crate::components_arena_RawId
) {
$($update_handlers)*
}
$($dep_props)*
}
impl $($g)* $crate::DepType for $name $($r)* $($w)* {
type Id = $Id;
type DepObjKey = $DepObjKey;
fn core_base_priv(&self) -> &$crate::BaseDepObjCore<$name $($r)*> {
&self.core.dep_type_core_base
}
fn core_base_priv_mut(&mut self) -> &mut $crate::BaseDepObjCore<$name $($r)*> {
&mut self.core.dep_type_core_base
}
fn take_all_handlers(
&mut self,
$handlers: &mut $crate::std_vec_Vec<
$crate::std_boxed_Box<dyn $crate::binding::AnyHandler>,
&dyn $crate::std_alloc_Allocator
>
) {
self.core.dep_type_core_take_all_handlers($handlers);
}
fn collect_all_bindings(
&self,
$bindings: &mut $crate::std_vec_Vec<
$crate::binding::AnyBindingBase,
&dyn $crate::std_alloc_Allocator
>
) {
self.core.dep_type_core_collect_all_bindings($bindings);
}
fn update_parent_children_has_handlers(
&self
) -> fn($state: &mut dyn $crate::dyn_context_State, $id: $crate::components_arena_RawId) {
Self::update_parent_children_has_handlers
}
}
$vis struct [< $name Builder >] $($bc_g)* $($bc_w)* (pub $BaseBuilder);
impl $($bc_g)* $crate::DepObjBuilder for [< $name Builder >] $($bc_r)* $($bc_w)* {
type Id = $Id;
fn state(&self) -> &dyn $crate::dyn_context_State {
< $BaseBuilder as $crate::DepObjBuilder >::state(&self.0)
}
fn state_mut(&mut self) -> &mut dyn $crate::dyn_context_State {
< $BaseBuilder as $crate::DepObjBuilder >::state_mut(&mut self.0)
}
fn id(&self) -> $Id {
< $BaseBuilder as $crate::DepObjBuilder >::id(&self.0)
}
}
impl $($bc_g)* [< $name Builder >] $($bc_r)* $($bc_w)* {
$($builder_methods)*
}
}
};
(
$($token:tt)*
) => {
$crate::std_compile_error!($crate::indoc_indoc!("
invalid dep_type macro input, allowed form is
$(#[$attr:meta])* $vis:vis struct $name:ident
$(
= $Id:ty [$DepObjKey:ty]
|
<$generics> = $Id:ty [$DepObjKey:ty] $(where $where_clause)?
)
{
$($(
$(#[$field_attr:meta])* $field_name:ident
$(
: $field_type:ty = $field_value:expr
|
[$vec_field_item_type:ty]
|
yield $event_field_type:ty
)
),+ $(,)?)?
}
"));
};
}
#[macro_export]
macro_rules! impl_dep_obj {
(
$($token:tt)+
) => {
$crate::generics_parse! {
$crate::impl_dep_obj_impl {
}
$($token)+
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! impl_dep_obj_impl {
(
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
$Id:ty {
$($objs:tt)*
}
) => {
$crate::impl_dep_obj_impl! {
@objs
[$($g)*] [$($r)*] [$($w)*] [$Id]
[] [] [] []
[$($objs)*]
}
};
(
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
$($token:tt)*
) => {
$crate::std_compile_error!($crate::indoc_indoc!("
invalid dep obj implementation, allowed form is
$(
$Id:ty
|
<$generics> $Id:ty $(where $where_clause)?
)
{
$(
fn<$DepObjKey:tt>() -> $(optional)? $(($ty:ty) | dyn($tr:path)) {
$StatePart:ty $({ . $state_part_field:tt })? | . $component_field:tt
}
|
fn<$DepObjKey:ty>(
self as $this:ident,
$state_part:ident : $StatePart:ty
) -> $(optional)? $(($ty:ty) | dyn($tr:path)) {
if mut { $field_mut:expr } else { $field:expr }
}
)*
}
"));
};
(
@objs
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*] [$Id:ty]
[$($ty:tt)*] [$($opt_ty:tt)*] [$($tr:tt)*] [$($opt_tr:tt)*]
[ fn<$DepObjKey:tt>() -> ($Obj:ty) { $StatePart:ty | . $component_field:tt } $($tail:tt)* ]
) => {
$crate::impl_dep_obj_impl! {
@objs
[$($g)*] [$($r)*] [$($w)*] [$Id]
[
$($ty)*
[
[$Obj] [$DepObjKey] [$StatePart] [this] [state_part]
[ &mut state_part.0[this.0] . $component_field ]
[ &state_part.0[this.0] . $component_field ]
]
]
[$($opt_ty)*]
[$($tr)*]
[$($opt_tr)*]
[$($tail)*]
}
};
(
@objs
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*] [$Id:ty]
[$($ty:tt)*] [$($opt_ty:tt)*] [$($tr:tt)*] [$($opt_tr:tt)*]
[ fn<$DepObjKey:tt>() -> ($Obj:ty) { $StatePart:ty { . $state_part_field:tt } | . $component_field:tt } $($tail:tt)* ]
) => {
$crate::impl_dep_obj_impl! {
@objs
[$($g)*] [$($r)*] [$($w)*] [$Id]
[
$($ty)*
[
[$Obj] [$DepObjKey] [$StatePart] [this] [state_part]
[ &mut state_part. $state_part_field [this.0] . $component_field ]
[ &state_part. $state_part_field [this.0] . $component_field ]
]
]
[$($opt_ty)*]
[$($tr)*]
[$($opt_tr)*]
[$($tail)*]
}
};
(
@objs
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*] [$Id:ty]
[$($ty:tt)*] [$($opt_ty:tt)*] [$($tr:tt)*] [$($opt_tr:tt)*]
[ fn<$DepObjKey:tt>() -> optional ($Obj:ty) { $StatePart:ty | . $component_field:tt } $($tail:tt)* ]
) => {
$crate::impl_dep_obj_impl! {
@objs
[$($g)*] [$($r)*] [$($w)*] [$Id]
[$($ty)*]
[
$($opt_ty)*
[
[$Obj] [$DepObjKey] [$StatePart] [this] [state_part]
[ state_part.0[this.0] . $component_field .as_mut() ]
[ state_part.0[this.0] . $component_field .as_ref() ]
]
]
[$($tr)*]
[$($opt_tr)*]
[$($tail)*]
}
};
(
@objs
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*] [$Id:ty]
[$($ty:tt)*] [$($opt_ty:tt)*] [$($tr:tt)*] [$($opt_tr:tt)*]
[ fn<$DepObjKey:tt>() -> optional ($Obj:ty) { $StatePart:ty { . $state_part_field:tt } | . $component_field:tt } $($tail:tt)* ]
) => {
$crate::impl_dep_obj_impl! {
@objs
[$($g)*] [$($r)*] [$($w)*] [$Id]
[$($ty)*]
[
$($opt_ty)*
[
[$Obj] [$DepObjKey] [$StatePart] [this] [state_part]
[ state_part. $state_part_field [this.0] . $component_field .as_mut() ]
[ state_part. $state_part_field [this.0] . $component_field .as_ref() ]
]
]
[$($tr)*]
[$($opt_tr)*]
[$($tail)*]
}
};
(
@objs
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*] [$Id:ty]
[$($ty:tt)*] [$($opt_ty:tt)*] [$($tr:tt)*] [$($opt_tr:tt)*]
[ fn<$DepObjKey:tt>() -> dyn($Obj:path) { $StatePart:ty | . $component_field:tt } $($tail:tt)* ]
) => {
$crate::impl_dep_obj_impl! {
@objs
[$($g)*] [$($r)*] [$($w)*] [$Id]
[$($ty)*]
[$($opt_ty)*]
[
$($tr)*
[
[$Obj] [$DepObjKey] [$StatePart] [this] [state_part]
[ state_part.0[this.0] . $component_field .as_mut() ]
[ state_part.0[this.0] . $component_field .as_ref() ]
]
]
[$($opt_tr)*]
[$($tail)*]
}
};
(
@objs
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*] [$Id:ty]
[$($ty:tt)*] [$($opt_ty:tt)*] [$($tr:tt)*] [$($opt_tr:tt)*]
[ fn<$DepObjKey:tt>() -> dyn($Obj:path) { $StatePart:ty { . $state_part_field:tt } | . $component_field:tt } $($tail:tt)* ]
) => {
$crate::impl_dep_obj_impl! {
@objs
[$($g)*] [$($r)*] [$($w)*] [$Id]
[$($ty)*]
[$($opt_ty)*]
[
$($tr)*
[
[$Obj] [$DepObjKey] [$StatePart] [this] [state_part]
[ state_part. $state_part_field [this.0] . $component_field .as_mut() ]
[ state_part. $state_part_field [this.0] . $component_field .as_ref() ]
]
]
[$($opt_tr)*]
[$($tail)*]
}
};
(
@objs
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*] [$Id:ty]
[$($ty:tt)*] [$($opt_ty:tt)*] [$($tr:tt)*] [$($opt_tr:tt)*]
[ fn<$DepObjKey:tt>() -> optional dyn($Obj:path) { $StatePart:ty | . $component_field:tt } $($tail:tt)* ]
) => {
$crate::impl_dep_obj_impl! {
@objs
[$($g)*] [$($r)*] [$($w)*] [$Id]
[$($ty)*]
[$($opt_ty)*]
[$($tr)*]
[
$($opt_tr)*
[
[$Obj] [$DepObjKey] [$StatePart] [this] [state_part]
[ state_part.0[this.0] . $component_field .as_deref_mut() ]
[ state_part.0[this.0] . $component_field .as_deref() ]
]
]
[$($tail)*]
}
};
(
@objs
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*] [$Id:ty]
[$($ty:tt)*] [$($opt_ty:tt)*] [$($tr:tt)*] [$($opt_tr:tt)*]
[ fn<$DepObjKey:tt>() -> optional dyn($Obj:path) { $StatePart:ty { . $state_part_field:tt } | . $component_field:tt } $($tail:tt)* ]
) => {
$crate::impl_dep_obj_impl! {
@objs
[$($g)*] [$($r)*] [$($w)*] [$Id]
[$($ty)*]
[$($opt_ty)*]
[$($tr)*]
[
$($opt_tr)*
[
[$Obj] [$DepObjKey] [$StatePart] [this] [state_part]
[ state_part. $state_part_field [this.0] . $component_field .as_deref_mut() ]
[ state_part. $state_part_field [this.0] . $component_field .as_deref() ]
]
]
[$($tail)*]
}
};
(
@objs
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*] [$Id:ty]
[$($ty:tt)*] [$($opt_ty:tt)*] [$($tr:tt)*] [$($opt_tr:tt)*]
[
fn<$DepObjKey:tt>(
self as $this:ident,
$state_part:ident : $StatePart:ty
) -> ($Obj:ty) {
if mut { $field_mut:expr } else { $field:expr }
}
$($tail:tt)*
]
) => {
$crate::impl_dep_obj_impl! {
@objs
[$($g)*] [$($r)*] [$($w)*] [$Id]
[
$($ty)*
[
[$Obj] [$DepObjKey] [$StatePart] [$this] [$state_part]
[$field_mut] [$field]
]
]
[$($opt_ty)*]
[$($tr)*]
[$($opt_tr)*]
[$($tail)*]
}
};
(
@objs
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*] [$Id:ty]
[$($ty:tt)*] [$($opt_ty:tt)*] [$($tr:tt)*] [$($opt_tr:tt)*]
[
fn<$DepObjKey:tt>(
self as $this:ident,
$state_part:ident : $StatePart:ty
) -> optional ($Obj:ty) {
if mut { $field_mut:expr } else { $field:expr }
}
$($tail:tt)*
]
) => {
$crate::impl_dep_obj_impl! {
@objs
[$($g)*] [$($r)*] [$($w)*] [$Id]
[$($ty)*]
[
$($opt_ty)*
[
[$Obj] [$DepObjKey] [$StatePart] [$this] [$state_part]
[$field_mut] [$field]
]
]
[$($tr)*]
[$($opt_tr)*]
[$($tail)*]
}
};
(
@objs
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*] [$Id:ty]
[$($ty:tt)*] [$($opt_ty:tt)*] [$($tr:tt)*] [$($opt_tr:tt)*]
[
fn<$DepObjKey:tt>(
self as $this:ident,
$state_part:ident : $StatePart:ty
) -> dyn($Obj:path) {
if mut { $field_mut:expr } else { $field:expr }
}
$($tail:tt)*
]
) => {
$crate::impl_dep_obj_impl! {
@objs
[$($g)*] [$($r)*] [$($w)*] [$Id]
[$($ty)*]
[$($opt_ty)*]
[
$($tr)*
[
[$Obj] [$DepObjKey] [$StatePart] [$this] [$state_part]
[$field_mut] [$field]
]
]
[$($opt_tr)*]
[$($tail)*]
}
};
(
@objs
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*] [$Id:ty]
[$($ty:tt)*] [$($opt_ty:tt)*] [$($tr:tt)*] [$($opt_tr:tt)*]
[
fn<$DepObjKey:tt>(
self as $this:ident,
$state_part:ident : $StatePart:ty
) -> optional dyn($Obj:path) {
if mut { $field_mut:expr } else { $field:expr }
}
$($tail:tt)*
]
) => {
$crate::impl_dep_obj_impl! {
@objs
[$($g)*] [$($r)*] [$($w)*] [$Id]
[$($ty)*]
[$($opt_ty)*]
[$($tr)*]
[
$($opt_tr)*
[
[$Obj] [$DepObjKey] [$StatePart] [$this] [$state_part]
[$field_mut] [$field]
]
]
[$($tail)*]
}
};
(
@objs
$g:tt $r:tt $w:tt [$Id:ty]
[$([
[$ty_Obj:ty] [$ty_Key:ty] [$ty_StatePart:ty] [$ty_this:ident] [$ty_state_part:ident]
[$ty_field:expr] [$ty_field_mut:expr]
])*]
[$([
[$opt_ty_Obj:ty] [$opt_ty_Key:ty] [$opt_ty_StatePart:ty] [$opt_ty_this:ident] [$opt_ty_state_part:ident]
[$opt_ty_field:expr] [$opt_ty_field_mut:expr]
])*]
[$([
[$tr_Obj:path] [$tr_Key:ty] [$tr_StatePart:ty] [$tr_this:ident] [$tr_state_part:ident]
[$tr_field:expr] [$tr_field_mut:expr]
])*]
[$([
[$opt_tr_Obj:path] [$opt_tr_Key:ty] [$opt_tr_StatePart:ty] [$opt_tr_this:ident] [$opt_tr_state_part:ident]
[$opt_tr_field:expr] [$opt_tr_field_mut:expr]
])*]
[]
) => {
$crate::impl_dep_obj_impl! {
@drop_bindings
$g $r $w [$Id]
[
$(
[$ty_this] [$ty_state_part] [$ty_StatePart] [] [] [] [$ty_Obj]
[ $ty_field ] [ $ty_field_mut ]
)*
$(
[$opt_ty_this] [$opt_ty_state_part] [$opt_ty_StatePart] [] [] [$opt_ty_Obj] []
[ $opt_ty_field ] [ $opt_ty_field_mut ]
)*
$(
[$tr_this] [$tr_state_part] [$tr_StatePart] [] [$tr_Obj] [] []
[ $tr_field ] [ $tr_field_mut ]
)*
$(
[$opt_tr_this] [$opt_tr_state_part] [$opt_tr_StatePart] [$opt_tr_Obj] [] [] []
[ $opt_tr_field ] [ $opt_tr_field_mut ]
)*
]
}
$(
$crate::impl_dep_obj_impl! {
@impl
$g $w [$Id]
[$ty_this] [$ty_state_part] [$ty_StatePart] [] [] [] [$ty_Obj] [$ty_Key]
[ $ty_field ] [ $ty_field_mut ]
}
)*
$(
$crate::impl_dep_obj_impl! {
@impl
$g $w [$Id]
[$opt_ty_this] [$opt_ty_state_part] [$opt_ty_StatePart] [] [] [$opt_ty_Obj] [] [$opt_ty_Key]
[ $opt_ty_field ] [ $opt_ty_field_mut ]
}
)*
$(
$crate::impl_dep_obj_impl! {
@impl
$g $w [$Id]
[$tr_this] [$tr_state_part] [$tr_StatePart] [] [$tr_Obj] [] [] [$tr_Key]
[ $tr_field ] [ $tr_field_mut ]
}
)*
$(
$crate::impl_dep_obj_impl! {
@impl
$g $w [$Id]
[$opt_tr_this] [$opt_tr_state_part] [$opt_tr_StatePart] [$opt_tr_Obj] [] [] [] [$opt_tr_Key]
[ $opt_tr_field ] [ $opt_tr_field_mut ]
}
)*
};
(
@objs
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*] [$Id:ty]
[$($ty:tt)*] [$($opt_ty:tt)*] [$($tr:tt)*] [$($opt_tr:tt)*]
[($token:tt)+]
) => {
$crate::std_compile_error!($crate::std_concat!(
"invalid dep obj component_field function definition\n\n",
$crate::std_stringify!($token $($tail)*),
"\n\n",
$crate::indoc_indoc!("
allowed forms are
fn<$DepObjKey:ty>() -> $(optional)? $(($ty:ty) | dyn($tr:path)) {
$StatePart:ty $({ . $state_part_field:tt })? | . $component_field:tt
}
fn<$DepObjKey:ty>(
self as $this:ident,
$state_part:ident : $StatePart:ty
) -> $(optional)? $(($ty:ty) | dyn($tr:path)) {
if mut { $field_mut:expr } else { $field:expr }
}
")
));
};
(
@impl
[$($g:tt)*] [$($w:tt)*] [$Id:ty]
[$this:ident] [$state_part:ident] [$StatePart:ty] [$opt_tr:path] [] [] [] [$DepObjKey:ty]
[$field_mut:expr] [$field:expr]
) => {
$crate::impl_dep_obj_impl! {
@add_parameter_to_optional
[DepObjType]
[$($g)*] [$($w)*] [$Id]
[$this] [$state_part] [$StatePart] [$opt_tr] [$DepObjKey]
[$field_mut] [$field]
}
};
(
@add_parameter_to_optional
[$p:ident]
[$($g:tt)*] [$($w:tt)*] [$Id:ty]
[$this:ident] [$state_part:ident] [$StatePart:ty] [$opt_tr:path] [$DepObjKey:ty]
[$field_mut:expr] [$field:expr]
) => {
$crate::generics_concat! {
$crate::impl_dep_obj_impl {
@impl_optional_with_parameter
[$p] [$($g)*] [$($w)*] [$Id]
[$this] [$state_part] [$StatePart] [$DepObjKey]
[$field_mut] [$field]
}
[$($g)*] [] [],
[ < $p : $opt_tr + $crate::DepType<Id=Self> > ] [] []
}
};
(
@impl_optional_with_parameter
[$p:ident] [$($g:tt)*] [$($w:tt)*] [$Id:ty]
[$this:ident] [$state_part:ident] [$StatePart:ty] [$DepObjKey:ty]
[$field_mut:expr] [$field:expr]
[$($gp:tt)*] [] []
) => {
$crate::paste_paste! {
impl $($gp)* $crate::DepObj <$DepObjKey, $p> for $Id $($w)* {
const STATE_PART: $crate::std_any_TypeId = $crate::std_any_TypeId::of::<$StatePart>();
fn get_raw <'state_part_lifetime>(
$state_part: &'state_part_lifetime dyn $crate::std_any_Any,
$this: $crate::components_arena_RawId,
) -> &'state_part_lifetime $p {
let $this = <Self as $crate::components_arena_ComponentId>::from_raw($this);
let $state_part = $state_part.downcast_ref::<$StatePart>().expect("invalid state part cast");
($field)
.expect($crate::std_concat!("missing ", $crate::std_stringify!($name)))
.downcast_ref::<DepObjType>().expect("invalid cast")
}
fn get_raw_mut <'state_part_lifetime>(
$state_part: &'state_part_lifetime mut dyn $crate::std_any_Any,
$this: $crate::components_arena_RawId,
) -> &'state_part_lifetime mut $p {
let $this = <Self as $crate::components_arena_ComponentId>::from_raw($this);
let $state_part = $state_part.downcast_mut::<$StatePart>().expect("invalid state part cast");
($field_mut)
.expect($crate::std_concat!("missing ", $crate::std_stringify!($name)))
.downcast_mut::<DepObjType>().expect("invalid cast")
}
}
}
};
(
@impl
[$($g:tt)*] [$($w:tt)*] [$Id:ty]
[$this:ident] [$state_part:ident] [$StatePart:ty] [] [$tr:path] [] [] [$DepObjKey:ty]
[$field_mut:expr] [$field:expr]
) => {
$crate::impl_dep_obj_impl! {
@add_parameter
[DepObjType]
[$($g)*] [$($w)*] [$Id]
[$this] [$state_part] [$StatePart] [$tr] [$DepObjKey]
[$field_mut] [$field]
}
};
(
@add_parameter
[$p:ident]
[$($g:tt)*] [$($w:tt)*] [$Id:ty]
[$this:ident] [$state_part:ident] [$StatePart:ty] [$tr:path] [$DepObjKey:ty]
[$field_mut:expr] [$field:expr]
) => {
$crate::generics_concat! {
$crate::impl_dep_obj_impl {
@impl_with_parameter
[$p] [$($g)*] [$($w)*] [$Id]
[$this] [$state_part] [$StatePart] [$DepObjKey]
[$field_mut] [$field]
}
[$($g)*] [] [],
[ < $p : $tr + $crate::DepType<Id=Self> > ] [] []
}
};
(
@impl_with_parameter
[$p:ident] [$($g:tt)*] [$($w:tt)*] [$Id:ty]
[$this:ident] [$state_part:ident] [$StatePart:ty] [$DepObjKey:ty]
[$field_mut:expr] [$field:expr]
[$($gp:tt)*] [] []
) => {
$crate::paste_paste! {
impl $($gp)* $crate::DepObj<$DepObjKey, $p> for $Id $($w)* {
const STATE_PART: $crate::std_any_TypeId = $crate::std_any_TypeId::of::<$StatePart>();
fn get_raw <'state_part_lifetime>(
$state_part: &'state_part_lifetime dyn $crate::std_any_Any,
$this: $crate::components_arena_RawId,
) -> &'state_part_lifetime $p {
let $this = <Self as $crate::components_arena_ComponentId>::from_raw($this);
let $state_part = $state_part.downcast_ref::<$StatePart>().expect("invalid state part cast");
($field).downcast_ref::<DepObjType>().expect("invalid cast")
}
fn get_raw_mut <'state_part_lifetime>(
$state_part: &'state_part_lifetime mut dyn $crate::std_any_Any,
$this: $crate::components_arena_RawId,
) -> &'state_part_lifetime mut $p {
let $this = <Self as $crate::components_arena_ComponentId>::from_raw($this);
let $state_part = $state_part.downcast_mut::<$StatePart>().expect("invalid state part cast");
($field_mut).downcast_mut::<DepObjType>().expect("invalid cast")
}
}
}
};
(
@impl
[$($g:tt)*] [$($w:tt)*] [$Id:ty]
[$this:ident] [$state_part:ident] [$StatePart:ty] [] [] [$opt_ty:ty] [] [$DepObjKey:ty]
[$field_mut:expr] [$field:expr]
) => {
$crate::paste_paste! {
impl $($g)* $crate::DepObj<$DepObjKey, $opt_ty> for $Id $($w)* {
const STATE_PART: $crate::std_any_TypeId = $crate::std_any_TypeId::of::<$StatePart>();
fn get_raw <'state_part_lifetime>(
$state_part: &'state_part_lifetime dyn $crate::std_any_Any,
$this: $crate::components_arena_RawId,
) -> &'state_part_lifetime $opt_ty {
let $this = <Self as $crate::components_arena_ComponentId>::from_raw($this);
let $state_part = $state_part.downcast_ref::<$StatePart>().expect("invalid state part cast");
($field).expect($crate::std_concat!("missing ", $crate::std_stringify!($name)))
}
fn get_raw_mut <'state_part_lifetime>(
$state_part: &'state_part_lifetime mut dyn $crate::std_any_Any,
$this: $crate::components_arena_RawId,
) -> &'state_part_lifetime mut $opt_ty {
let $this = <Self as $crate::components_arena_ComponentId>::from_raw($this);
let $state_part = $state_part.downcast_mut::<$StatePart>().expect("invalid state part cast");
($field_mut).expect($crate::std_concat!("missing ", $crate::std_stringify!($name)))
}
}
}
};
(
@impl
[$($g:tt)*] [$($w:tt)*] [$Id:ty]
[$this:ident] [$state_part:ident] [$StatePart:ty] [] [] [] [$ty:ty] [$DepObjKey:ty]
[$field_mut:expr] [$field:expr]
) => {
$crate::paste_paste! {
impl $($g)* $crate::DepObj<$DepObjKey, $ty> for $Id $($w)* {
const STATE_PART: $crate::std_any_TypeId = $crate::std_any_TypeId::of::<$StatePart>();
fn get_raw <'state_part_lifetime>(
$state_part: &'state_part_lifetime dyn $crate::std_any_Any,
$this: $crate::components_arena_RawId,
) -> &'state_part_lifetime $ty {
let $this = <Self as $crate::components_arena_ComponentId>::from_raw($this);
let $state_part = $state_part.downcast_ref::<$StatePart>().expect("invalid state part cast");
$field
}
fn get_raw_mut <'state_part_lifetime>(
$state_part: &'state_part_lifetime mut dyn $crate::std_any_Any,
$this: $crate::components_arena_RawId,
) -> &'state_part_lifetime mut $ty {
let $this = <Self as $crate::components_arena_ComponentId>::from_raw($this);
let $state_part = $state_part.downcast_mut::<$StatePart>().expect("invalid state part cast");
$field_mut
}
}
}
};
(
@drop_bindings
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*] [$Id:ty]
[
$(
[$this:ident] [$state_part:ident] [$StatePart:ty] [$($opt_tr:path)?] [$($tr:path)?] [$($opt_ty:ty)?] [$($ty:ty)?]
[$field_mut:expr] [$field:expr]
)*
]
) => {
impl $($g)* $Id $($w)* {
fn drop_bindings_priv(self, state: &mut dyn $crate::dyn_context_State) {
$(
$crate::composable_allocators::stacked::with_size::<256, _>(|alloc| {
let alloc = $crate::composable_allocators::fallbacked::Fallbacked(
alloc,
$crate::composable_allocators::Global
);
let alloc: &dyn $crate::std_alloc_Allocator = &alloc;
let mut bindings = $crate::std_vec_Vec::new_in(alloc);
let $this = self;
let $state_part: &mut $StatePart =
<dyn $crate::dyn_context_State as $crate::dyn_context_StateExt>::get_mut(state);
$(
<dyn $tr as $crate::DepType>::collect_all_bindings($field, &mut bindings);
)?
$(
if let $crate::std_option_Option::Some(f) = $field {
<dyn $opt_tr as $crate::DepType>::collect_all_bindings(f, &mut bindings);
}
)?
$(
<$ty as $crate::DepType>::collect_all_bindings($field, &mut bindings);
)?
$(
if let $crate::std_option_Option::Some(f) = $field {
<$opt_ty as $crate::DepType>::collect_all_bindings(f, &mut bindings)
}
)?
for binding in bindings {
binding.drop_self(state);
}
});
)*
$(
$crate::composable_allocators::stacked::with_size::<256, _>(|alloc| {
let alloc = $crate::composable_allocators::fallbacked::Fallbacked(
alloc,
$crate::composable_allocators::Global
);
let alloc: &dyn $crate::std_alloc_Allocator = &alloc;
let mut handlers = $crate::std_vec_Vec::new_in(alloc);
let $this = self;
let $state_part: &mut $StatePart = <dyn $crate::dyn_context_State as $crate::dyn_context_StateExt>::get_mut(state);
$(
let f = $field_mut;
<dyn $tr as $crate::DepType>::take_all_handlers(f, &mut handlers);
let update_parent_children_has_handlers =
<dyn $tr as $crate::DepType>::update_parent_children_has_handlers(f);
if !handlers.is_empty() {
update_parent_children_has_handlers(
state,
<Self as $crate::components_arena_ComponentId>::into_raw(self)
);
}
)?
$(
if let $crate::std_option_Option::Some(f) = $field_mut {
<dyn $opt_tr as $crate::DepType>::take_all_handlers(f, &mut handlers);
let update_parent_children_has_handlers =
<dyn $opt_tr as $crate::DepType>::update_parent_children_has_handlers(f);
if !handlers.is_empty() {
update_parent_children_has_handlers(
state,
<Self as $crate::components_arena_ComponentId>::into_raw(self)
);
}
}
)?
$(
let f = $field_mut;
<$ty as $crate::DepType>::take_all_handlers(f, &mut handlers);
let update_parent_children_has_handlers =
<$ty as $crate::DepType>::update_parent_children_has_handlers(f);
if !handlers.is_empty() {
update_parent_children_has_handlers(
state,
<Self as $crate::components_arena_ComponentId>::into_raw(self)
);
}
)?
$(
if let $crate::std_option_Option::Some(f) = $field_mut {
<$opt_ty as $crate::DepType>::take_all_handlers(f, &mut handlers);
let update_parent_children_has_handlers =
<$opt_ty as $crate::DepType>::update_parent_children_has_handlers(f);
if !handlers.is_empty() {
update_parent_children_has_handlers(
state,
<Self as $crate::components_arena_ComponentId>::into_raw(self)
);
}
}
)?
for handler in handlers {
handler.clear(state);
}
});
)*
}
}
};
}
#[cfg(test)]
mod test {
use alloc::borrow::Cow;
use components_arena::{Arena, Component, ComponentStop, NewtypeComponentId, with_arena_in_state_part};
use downcast_rs::{Downcast, impl_downcast};
use dyn_context::{StateRefMut, Stop};
use panicking::set_panicking_callback;
use crate::*;
enum Obj1Key { }
enum Obj2Key { }
trait Obj1: Downcast + DepType<Id=TheId, DepObjKey=Obj1Key> { }
impl_downcast!(Obj1);
trait Obj2: Downcast + DepType<Id=TheId, DepObjKey=Obj2Key> { }
impl_downcast!(Obj2);
macro_attr! {
#[derive(Debug, Component!(stop=TheIdStop))]
struct TheIdComponent {
obj_1: Box<dyn Obj1>,
obj_2: Box<dyn Obj2>,
}
}
impl ComponentStop for TheIdStop {
with_arena_in_state_part!(TheIds);
fn stop(&self, state: &mut dyn State, id: Id<TheIdComponent>) {
TheId(id).drop_bindings_priv(state);
}
}
#[derive(Debug, Stop)]
struct TheIds(Arena<TheIdComponent>);
macro_attr! {
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, NewtypeComponentId!)]
pub struct TheId(Id<TheIdComponent>);
}
impl DetachedDepObjId for TheId { }
impl_dep_obj!(TheId {
fn<Obj1Key>() -> dyn(Obj1) { TheIds | .obj_1 }
fn<Obj2Key>() -> dyn(Obj2) { TheIds | .obj_2 }
});
mod items {
use alloc::borrow::Cow;
use components_arena::{Arena, Component, ComponentStop, NewtypeComponentId, Id, with_arena_in_state_part};
use crate::{DetachedDepObjId, dep_type, impl_dep_obj};
use crate::binding::Binding3;
use dyn_context::{SelfState, State, StateExt, Stop};
use macro_attr_2018::macro_attr;
macro_attr! {
#[derive(Debug, Component!(stop=ItemStop))]
struct ItemComponent {
props: ItemProps,
}
}
impl ComponentStop for ItemStop {
with_arena_in_state_part!(Items);
fn stop(&self, state: &mut dyn State, id: Id<ItemComponent>) {
Item(id).drop_bindings_priv(state);
}
}
macro_attr! {
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, NewtypeComponentId!)]
pub struct Item(Id<ItemComponent>);
}
impl DetachedDepObjId for Item { }
impl Item {
pub fn new(state: &mut dyn State) -> Item {
let items: &mut Items = state.get_mut();
let item = items.0.insert(|id| (ItemComponent { props: ItemProps::new_priv() }, Item(id)));
item.bind_weight(state);
item
}
#[allow(dead_code)]
pub fn drop_self(self, state: &mut dyn State) {
self.drop_bindings_priv(state);
let items: &mut Items = state.get_mut();
items.0.remove(self.0);
}
fn bind_weight(self, state: &mut dyn State) {
let weight = Binding3::new(state, (), |(), base_weight, cursed, equipped| Some(
if equipped && cursed { base_weight + 100.0 } else { base_weight }
));
ItemProps::WEIGHT.bind(state, self, weight);
weight.set_source_1(state, &mut ItemProps::BASE_WEIGHT.value_source(self));
weight.set_source_2(state, &mut ItemProps::CURSED.value_source(self));
weight.set_source_3(state, &mut ItemProps::EQUIPPED.value_source(self));
}
}
impl_dep_obj!(Item {
fn<ItemProps>() -> (ItemProps) { Items | .props }
});
#[derive(Debug, Stop)]
pub struct Items(Arena<ItemComponent>);
impl SelfState for Items { }
impl Items {
pub fn new() -> Items {
Items(Arena::new())
}
}
dep_type! {
#[derive(Debug)]
pub struct ItemProps = Item[ItemProps] {
name: Cow<'static, str> = Cow::Borrowed(""),
base_weight: f32 = 0.0,
weight: f32 = 0.0,
equipped: bool = false,
cursed: bool = false,
}
}
}
use items::*;
fn read_name(state: &mut dyn State, item: Item) -> Cow<'static, str> {
let binding = Binding1::new(state, (), |(), value| Some(value));
let mut buf: Option<Cow<'static, str>> = None;
binding.set_target_fn(state, &raw mut buf, |_state, buf, value| {
unsafe { *buf = Some(value) };
});
binding.set_source_1(state, &mut ItemProps::NAME.value_source(item));
binding.drop_self(state);
buf.unwrap()
}
#[test]
fn apply_style() {
set_panicking_callback(|| true);
(&mut Items::new()).merge_mut_and_then(|state| {
let item = Item::new(state);
let mut style = Style::new();
style.insert(ItemProps::NAME, Cow::Borrowed("name from style"));
assert!(item.apply_style(state, Some(style)).is_none());
assert_eq!(read_name(state, item).as_ref(), "name from style");
Items::stop(state);
}, &mut Bindings::new());
}
}