diff --git a/fish-rust/src/common.rs b/fish-rust/src/common.rs index cb154f08b..9b29cdd3c 100644 --- a/fish-rust/src/common.rs +++ b/fish-rust/src/common.rs @@ -1985,6 +1985,56 @@ pub fn get_by_sorted_name(name: &wstr, vals: &'static [T]) -> Option<& } } +/// Takes ownership of a variable and `Deref`s/`DerefMut`s into a projection of that variable. +/// +/// Can be used as a workaround for the lack of `MutexGuard::map()` to return a `MutexGuard` +/// exposing only a variable of the Mutex-owned object. +pub struct Projection +where + F1: Fn(&T) -> &V, + F2: Fn(&mut T) -> &mut V, +{ + value: T, + view: F1, + view_mut: F2, +} + +impl Projection +where + F1: Fn(&T) -> &V, + F2: Fn(&mut T) -> &mut V, +{ + pub fn new(owned: T, project: F1, project_mut: F2) -> Self { + Projection { + value: owned, + view: project, + view_mut: project_mut, + } + } +} + +impl Deref for Projection +where + F1: Fn(&T) -> &V, + F2: Fn(&mut T) -> &mut V, +{ + type Target = V; + + fn deref(&self) -> &Self::Target { + (self.view)(&self.value) + } +} + +impl DerefMut for Projection +where + F1: Fn(&T) -> &V, + F2: Fn(&mut T) -> &mut V, +{ + fn deref_mut(&mut self) -> &mut Self::Target { + (self.view_mut)(&mut self.value) + } +} + #[allow(unused_macros)] macro_rules! fwprintf { ($fd:expr, $format:literal $(, $arg:expr)*) => {