pui_cell/
get_all_mut.rs

1use pui_core::Identifier;
2use typsy::hlist::{Cons, Nil};
3
4use seal::Seal;
5
6use crate::{IdCell, IdentifierExt};
7#[forbid(missing_docs)]
8mod seal {
9    pub trait Seal {
10        fn __internal_find(&self, ptr: *mut ()) -> bool;
11    }
12}
13
14/// A trait that defines all the types defines how to get all
15/// of mutable references out of the heterogeneous list
16/// of [`IdCell`]s.
17pub trait GetAllMut<I>: Seal {
18    /// A hlist of mutable references
19    type Output;
20
21    /// Gets all mutable references from the `IdCell`s, returns
22    /// `None` if some of the types overlap
23    fn get_all_mut(self, ident: I) -> Option<Self::Output>;
24}
25
26impl Seal for Nil {
27    #[inline]
28    fn __internal_find(&self, _: *mut ()) -> bool { false }
29}
30
31impl<T> GetAllMut<T> for Nil {
32    type Output = Nil;
33
34    fn get_all_mut(self, _: T) -> Option<Self::Output> { Some(Self) }
35}
36
37impl<T: ?Sized, R: Seal> Seal for Cons<&T, R> {
38    fn __internal_find(&self, ptr: *mut ()) -> bool {
39        let value = self.value as *const T as *const ();
40        value == ptr || self.rest.__internal_find(ptr)
41    }
42}
43
44impl<'a, T: ?Sized, R, I: ?Sized + Identifier> GetAllMut<&'a mut I> for Cons<&'a IdCell<T, I::Token>, R>
45where
46    R: GetAllMut<&'a mut I>,
47{
48    type Output = Cons<&'a mut T, R::Output>;
49
50    fn get_all_mut(self, ident: &'a mut I) -> Option<Self::Output> {
51        assert!(ident.owns(self.value));
52
53        let ptr = self.value.as_ptr();
54
55        if self.rest.__internal_find(ptr as *mut ()) {
56            return None
57        }
58
59        Some(Cons {
60            value: unsafe { &mut *ptr },
61            rest: self.rest.get_all_mut(ident)?,
62        })
63    }
64}