use std::{ops::Deref, sync::Arc}; use arc_swap::ArcSwap; use serde::Deserialize; use yazi_shared::Layer; use yazi_shim::{arc_swap::{ArcSwapExt, IntoPointee}, vec::{IndexAtError, VecExt}}; use super::Chord; use crate::keymap::ChordMatcher; #[derive(Debug, Default, Deserialize)] pub struct Chords(ArcSwap>>>); impl Deref for Chords { type Target = ArcSwap>>>; fn deref(&self) -> &Self::Target { &self.0 } } impl From>>> for Chords { fn from(inner: Vec>>) -> Self { Self(inner.into_pointee()) } } impl Chords { pub fn as_erased(&self) -> Arc>>> { let chords = self.0.load_full(); unsafe { Arc::from_raw(Arc::into_raw(chords) as *const Vec>>) } } 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.as_erased().clone()]) .chain(after.iter().cloned()) .collect::>(), ) })?; Ok(()) } pub fn remove(&self, matcher: ChordMatcher) { self.0.rcu(|chords| { let mut next = Vec::clone(chords); next.retain(|chord| !matcher.matches(chord.as_erased())); next }); } pub(crate) fn unwrap_unchecked(self) -> Vec>> { Arc::try_unwrap(self.0.into_inner()).expect("unique chords arc") } }