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
|
||||
}
|
||||
}
|
||||
19
src/criteria/clm/clm_matchers.rs
Normal file
19
src/criteria/clm/clm_matchers.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#[expect(unused_macros)]
|
||||
macro_rules! fixed_root_criterion {
|
||||
($ty:ty, $field:ident) => {
|
||||
impl crate::criteria::crit_graph::CritFixedRootCriterionBase<Rc<crate::client::Client>>
|
||||
for $ty
|
||||
{
|
||||
fn constant(&self) -> bool {
|
||||
self.0
|
||||
}
|
||||
|
||||
fn not<'a>(
|
||||
&self,
|
||||
mgr: &'a crate::criteria::clm::ClMatcherManager,
|
||||
) -> &'a crate::criteria::FixedRootMatcher<Rc<crate::client::Client>, Self> {
|
||||
&mgr.$field
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -129,7 +129,6 @@ where
|
|||
slf
|
||||
}
|
||||
|
||||
#[expect(dead_code)]
|
||||
pub fn handle(&self, target: &Target) {
|
||||
let new = self.criterion.matches(target) ^ self.not;
|
||||
let node = match new {
|
||||
|
|
|
|||
|
|
@ -104,7 +104,6 @@ impl<Target> CritLeafEvent<Target>
|
|||
where
|
||||
Target: CritTarget,
|
||||
{
|
||||
#[expect(dead_code)]
|
||||
pub fn run(self) {
|
||||
let n = self.node;
|
||||
n.needs_event.set(true);
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ impl<Target> CritMatchConstant<Target>
|
|||
where
|
||||
Target: CritTarget,
|
||||
{
|
||||
#[expect(dead_code)]
|
||||
pub fn create(
|
||||
roots: &Rc<Target::RootMatchers>,
|
||||
ids: &CritMatcherIds,
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ pub trait CritDestroyListener<Target>: 'static
|
|||
where
|
||||
Target: CritTarget,
|
||||
{
|
||||
#[expect(dead_code)]
|
||||
fn destroyed(&self, target_id: Target::Id);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue