config: add client-rule infrastructure
This commit is contained in:
parent
17e715cde4
commit
fd2163d658
32 changed files with 1804 additions and 27 deletions
203
src/criteria/clm.rs
Normal file
203
src/criteria/clm.rs
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
pub mod clm_matchers;
|
||||
|
||||
use {
|
||||
crate::{
|
||||
client::{Client, ClientId},
|
||||
criteria::{
|
||||
CritDestroyListener, CritMatcherId, CritMatcherIds, CritUpstreamNode, FixedRootMatcher,
|
||||
RootMatcherMap,
|
||||
crit_graph::{CritMgr, CritTarget, CritTargetOwner, WeakCritTargetOwner},
|
||||
crit_leaf::{CritLeafEvent, CritLeafMatcher},
|
||||
crit_matchers::critm_constant::CritMatchConstant,
|
||||
},
|
||||
state::State,
|
||||
utils::{copyhashmap::CopyHashMap, hash_map_ext::HashMapExt, queue::AsyncQueue},
|
||||
},
|
||||
std::rc::{Rc, Weak},
|
||||
};
|
||||
|
||||
bitflags! {
|
||||
ClMatcherChange: u32;
|
||||
CL_CHANGED_DESTROYED = 1 << 0,
|
||||
CL_CHANGED_NEW = 1 << 1,
|
||||
}
|
||||
|
||||
type ClmFixedRootMatcher<T> = FixedRootMatcher<Rc<Client>, T>;
|
||||
|
||||
pub struct ClMatcherManager {
|
||||
ids: Rc<CritMatcherIds>,
|
||||
changes: AsyncQueue<Rc<Client>>,
|
||||
leaf_events: Rc<AsyncQueue<CritLeafEvent<Rc<Client>>>>,
|
||||
constant: ClmFixedRootMatcher<CritMatchConstant<Rc<Client>>>,
|
||||
matchers: Rc<RootMatchers>,
|
||||
}
|
||||
|
||||
#[expect(dead_code)]
|
||||
type ClmRootMatcherMap<T> = RootMatcherMap<Rc<Client>, T>;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct RootMatchers {}
|
||||
|
||||
pub async fn handle_cl_changes(state: Rc<State>) {
|
||||
let mgr = &state.cl_matcher_manager;
|
||||
loop {
|
||||
let tl = mgr.changes.pop().await;
|
||||
mgr.update_matches(&tl);
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn handle_cl_leaf_events(state: Rc<State>) {
|
||||
let mgr = &state.cl_matcher_manager;
|
||||
let debouncer = state.ring.debouncer(1000);
|
||||
loop {
|
||||
let event = mgr.leaf_events.pop().await;
|
||||
event.run();
|
||||
debouncer.debounce().await;
|
||||
}
|
||||
}
|
||||
|
||||
#[expect(dead_code)]
|
||||
pub type ClmUpstreamNode = dyn CritUpstreamNode<Rc<Client>>;
|
||||
pub type ClmLeafMatcher = CritLeafMatcher<Rc<Client>>;
|
||||
|
||||
impl ClMatcherManager {
|
||||
pub fn new(ids: &Rc<CritMatcherIds>) -> Self {
|
||||
let matchers = Rc::new(RootMatchers::default());
|
||||
#[expect(unused_macros)]
|
||||
macro_rules! bool {
|
||||
($name:ident) => {{
|
||||
static_map! {
|
||||
v => CritRoot::new(
|
||||
&matchers,
|
||||
ids.next(),
|
||||
CritRootFixed($name(v), PhantomData),
|
||||
)
|
||||
}
|
||||
}};
|
||||
}
|
||||
Self {
|
||||
constant: CritMatchConstant::create(&matchers, ids),
|
||||
changes: Default::default(),
|
||||
leaf_events: Default::default(),
|
||||
ids: ids.clone(),
|
||||
matchers,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear(&self) {
|
||||
self.changes.clear();
|
||||
self.leaf_events.clear();
|
||||
}
|
||||
|
||||
pub fn rematch_all(&self, state: &Rc<State>) {
|
||||
for client in state.clients.clients.borrow().values() {
|
||||
client.data.property_changed(CL_CHANGED_NEW);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn changed(&self, client: &Rc<Client>) {
|
||||
self.changes.push(client.clone());
|
||||
}
|
||||
|
||||
fn update_matches(&self, data: &Rc<Client>) {
|
||||
let mut changed = data.changed_properties.take();
|
||||
if changed.contains(CL_CHANGED_DESTROYED) {
|
||||
for destroyed in data.destroyed.lock().drain_values() {
|
||||
if let Some(destroyed) = destroyed.upgrade() {
|
||||
destroyed.destroyed(data.id);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
#[expect(unused_macros)]
|
||||
macro_rules! handlers {
|
||||
($name:ident) => {
|
||||
self.matchers
|
||||
.$name
|
||||
.lock()
|
||||
.values()
|
||||
.filter_map(|m| m.upgrade())
|
||||
};
|
||||
}
|
||||
#[expect(unused_macros)]
|
||||
macro_rules! fixed {
|
||||
($name:ident) => {
|
||||
self.$name[false].handle(data);
|
||||
self.$name[true].handle(data);
|
||||
};
|
||||
}
|
||||
if changed.contains(CL_CHANGED_NEW) {
|
||||
changed |= ClMatcherChange::all();
|
||||
#[expect(unused_macros)]
|
||||
macro_rules! unconditional {
|
||||
($field:ident) => {
|
||||
for m in handlers!($field) {
|
||||
m.handle(data);
|
||||
}
|
||||
};
|
||||
}
|
||||
self.constant[true].handle(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CritTarget for Rc<Client> {
|
||||
type Id = ClientId;
|
||||
type Mgr = ClMatcherManager;
|
||||
type RootMatchers = RootMatchers;
|
||||
type LeafData = ClientId;
|
||||
type Owner = Weak<Client>;
|
||||
|
||||
fn owner(&self) -> Self::Owner {
|
||||
Rc::downgrade(self)
|
||||
}
|
||||
|
||||
fn id(&self) -> Self::Id {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn destroyed(&self) -> &CopyHashMap<CritMatcherId, Weak<dyn CritDestroyListener<Self>>> {
|
||||
&self.destroyed
|
||||
}
|
||||
|
||||
fn leaf_data(&self) -> Self::LeafData {
|
||||
self.id
|
||||
}
|
||||
}
|
||||
|
||||
impl CritTargetOwner for Rc<Client> {
|
||||
type Target = Rc<Client>;
|
||||
|
||||
fn data(&self) -> &Self::Target {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl WeakCritTargetOwner for Weak<Client> {
|
||||
type Target = Rc<Client>;
|
||||
type Owner = Rc<Client>;
|
||||
|
||||
fn upgrade(&self) -> Option<Self::Owner> {
|
||||
self.upgrade()
|
||||
}
|
||||
}
|
||||
|
||||
impl CritMgr for ClMatcherManager {
|
||||
type Target = Rc<Client>;
|
||||
|
||||
fn id(&self) -> CritMatcherId {
|
||||
self.ids.next()
|
||||
}
|
||||
|
||||
fn leaf_events(&self) -> &Rc<AsyncQueue<CritLeafEvent<Self::Target>>> {
|
||||
&self.leaf_events
|
||||
}
|
||||
|
||||
fn match_constant(&self) -> &FixedRootMatcher<Self::Target, CritMatchConstant<Self::Target>> {
|
||||
&self.constant
|
||||
}
|
||||
|
||||
fn roots(&self) -> &Rc<<Self::Target as CritTarget>::RootMatchers> {
|
||||
&self.matchers
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue