use std::{mem, ops::Deref, sync::Arc}; use arc_swap::ArcSwap; use hashbrown::{HashMap, hash_map}; use serde::Deserialize; use yazi_shim::{arc_swap::{ArcSwapExt, IntoPointee}, toml::DeserializeOverHook, vec::{IndexAtError, VecExt}}; use super::OpenerRule; use crate::opener::{Opener, OpenerRuleMatcher}; #[derive(Debug, Default, Deserialize)] pub struct OpenerRules(ArcSwap>>); impl Deref for OpenerRules { type Target = ArcSwap>>; fn deref(&self) -> &Self::Target { &self.0 } } impl From>> for OpenerRules { fn from(inner: Vec>) -> Self { Self(inner.into_pointee()) } } impl OpenerRules { pub fn insert(&self, index: isize, rule: Arc) -> Result<(), IndexAtError> { self.0.try_rcu(|rules| { let (before, after) = rules.split_at(rules.index_at(index)?); Ok( before .iter() .cloned() .chain([rule.clone()]) .chain(after.iter().cloned()) .collect::>(), ) })?; Ok(()) } pub fn remove(&self, matcher: OpenerRuleMatcher) { self.0.rcu(|rules| { let mut next = Vec::clone(rules); next.retain(|rule| !matcher.matches(rule)); next }); } pub(crate) fn unwrap_unchecked(self) -> Vec> { Arc::try_unwrap(self.0.into_inner()).expect("unique opener rules arc") } } impl DeserializeOverHook for OpenerRules { fn deserialize_over_hook(self) -> Result { let mut inner = self.unwrap_unchecked(); inner.retain(|r| r.r#for.matches()); inner.iter_mut().for_each(|r| Arc::get_mut(r).expect("unique opener rule arc").fill()); Ok(Self(inner.into_pointee())) } } // --- Matcher pub struct OpenerRulesMatcher { iter: hash_map::Iter<'static, String, Arc>, _opener: Arc>>, } impl From<&Opener> for OpenerRulesMatcher { fn from(opener: &Opener) -> Self { let opener = opener.load_full(); let iter: hash_map::Iter> = opener.iter(); Self { iter: unsafe { mem::transmute(iter) }, _opener: opener } } } impl Iterator for OpenerRulesMatcher { type Item = (String, Arc); fn next(&mut self) -> Option { self.iter.next().map(|(name, rules)| (name.clone(), rules.clone())) } }