polyhorn_core/
reference.rs

1use std::cell::{Ref, RefMut};
2use std::marker::PhantomData;
3
4use super::{Link, Weak, WeakReference};
5
6pub struct Reference<T> {
7    instance_id: usize,
8    reference_id: usize,
9    marker: PhantomData<T>,
10}
11
12impl<T> Reference<T>
13where
14    T: 'static,
15{
16    pub(crate) fn new(instance_id: usize, reference_id: usize) -> Reference<T> {
17        Reference {
18            instance_id,
19            reference_id,
20            marker: PhantomData,
21        }
22    }
23
24    pub fn get<'a, L>(&self, link: &'a L) -> Ref<'a, T>
25    where
26        L: Link,
27    {
28        assert_eq!(self.instance_id, link.instance().id);
29
30        Ref::map(link.memory().reference(self.reference_id), |reference| {
31            reference.downcast_ref().unwrap()
32        })
33    }
34
35    pub fn replace<L>(&self, link: &L, value: T) -> T
36    where
37        L: Link,
38    {
39        assert_eq!(self.instance_id, link.instance().id);
40
41        let reference = link.memory().reference_mut(self.reference_id);
42        let mut reference = RefMut::map(reference, |reference| reference.downcast_mut().unwrap());
43        std::mem::replace(&mut reference, value)
44    }
45
46    pub fn apply<L, F, O>(&self, link: &L, op: F) -> O
47    where
48        L: Link,
49        F: FnOnce(&mut T) -> O,
50    {
51        assert_eq!(self.instance_id, link.instance().id);
52
53        let reference = link.memory().reference_mut(self.reference_id);
54        let mut reference = RefMut::map(reference, |reference| reference.downcast_mut().unwrap());
55        op(&mut reference)
56    }
57
58    pub fn weak<L>(self, link: &L) -> WeakReference<L::Platform, T>
59    where
60        L: Link,
61    {
62        assert_eq!(self.instance_id, link.instance().id);
63
64        WeakReference::new(Weak::new(link.instance()), self)
65    }
66}
67
68impl<T> Reference<T>
69where
70    T: Clone + 'static,
71{
72    pub fn cloned<L>(self, link: &L) -> T
73    where
74        L: Link,
75    {
76        assert_eq!(self.instance_id, link.instance().id);
77
78        link.memory()
79            .reference(self.reference_id)
80            .downcast_ref::<T>()
81            .unwrap()
82            .clone()
83    }
84}
85
86impl<T> Reference<T>
87where
88    T: Default + 'static,
89{
90    pub fn take<L>(&self, link: &L) -> T
91    where
92        L: Link,
93        T: Default,
94    {
95        self.replace(link, Default::default())
96    }
97}
98
99impl<T> Clone for Reference<T> {
100    fn clone(&self) -> Self {
101        *self
102    }
103}
104
105impl<T> Copy for Reference<T> {}