veloren_common/
link.rs

1use serde::{Deserialize, Serialize};
2use specs::{Component, DerefFlaggedStorage, SystemData};
3use std::{
4    any::Any,
5    ops::Deref,
6    sync::{Arc, Weak},
7};
8
9pub trait Link: Sized + Send + Sync + 'static {
10    type Error;
11
12    type CreateData<'a>: SystemData<'a>;
13    fn create(this: &LinkHandle<Self>, data: &mut Self::CreateData<'_>) -> Result<(), Self::Error>;
14
15    type PersistData<'a>: SystemData<'a>;
16    fn persist(this: &LinkHandle<Self>, data: &mut Self::PersistData<'_>) -> bool;
17
18    type DeleteData<'a>: SystemData<'a>;
19    fn delete(this: &LinkHandle<Self>, data: &mut Self::DeleteData<'_>);
20}
21
22pub trait Role {
23    type Link: Link;
24}
25
26#[derive(Serialize, Deserialize, Debug)]
27pub struct Is<R: Role> {
28    #[serde(bound(serialize = "R::Link: Serialize"))]
29    #[serde(bound(deserialize = "R::Link: Deserialize<'de>"))]
30    link: LinkHandle<R::Link>,
31}
32
33impl<R: Role> Is<R> {
34    pub fn delete(&self, data: &mut <R::Link as Link>::DeleteData<'_>) {
35        Link::delete(&self.link, data)
36    }
37
38    pub fn get_link(&self) -> &LinkHandle<R::Link> { &self.link }
39}
40
41impl<R: Role> Clone for Is<R> {
42    fn clone(&self) -> Self {
43        Self {
44            link: self.link.clone(),
45        }
46    }
47}
48
49impl<R: Role> Deref for Is<R> {
50    type Target = R::Link;
51
52    fn deref(&self) -> &Self::Target { &self.link }
53}
54
55impl<R: Role + 'static> Component for Is<R>
56where
57    R::Link: Send + Sync + 'static,
58{
59    type Storage = DerefFlaggedStorage<Self, specs::VecStorage<Self>>;
60}
61
62#[derive(Serialize, Deserialize, Debug)]
63pub struct LinkHandle<L: Link> {
64    link: Arc<L>,
65}
66
67impl<L: Link> Clone for LinkHandle<L> {
68    fn clone(&self) -> Self {
69        Self {
70            link: Arc::clone(&self.link),
71        }
72    }
73}
74
75impl<L: Link> LinkHandle<L> {
76    pub fn from_link(link: L) -> Self {
77        Self {
78            link: Arc::new(link),
79        }
80    }
81
82    pub fn make_role<R: Role<Link = L>>(&self) -> Is<R> { Is { link: self.clone() } }
83
84    pub fn downgrade(&self) -> WeakLinkHandle<L> {
85        WeakLinkHandle {
86            link: Arc::downgrade(&self.link),
87        }
88    }
89}
90
91impl<L: Link> Deref for LinkHandle<L> {
92    type Target = L;
93
94    fn deref(&self) -> &Self::Target { &self.link }
95}
96
97/// The inner data is not shared with the client, so it can't rely on this.
98#[derive(Serialize, Deserialize, Debug)]
99pub struct WeakLinkHandle<L: Link> {
100    #[serde(skip)]
101    link: Weak<L>,
102}
103
104impl<L: Link> Clone for WeakLinkHandle<L> {
105    fn clone(&self) -> Self {
106        Self {
107            link: Weak::clone(&self.link),
108        }
109    }
110}
111
112impl<L: Link> WeakLinkHandle<L> {
113    pub fn upgrade(&self) -> Option<LinkHandle<L>> {
114        Some(LinkHandle {
115            link: self.link.upgrade()?,
116        })
117    }
118
119    pub fn into_dyn(self) -> DynWeakLinkHandle {
120        DynWeakLinkHandle {
121            inner: InnerDynWeakLinkHandle(self.link as DynWeak),
122        }
123    }
124}
125
126type DynWeak = Weak<dyn Any + Sync + Send>;
127
128#[derive(Clone)]
129struct InnerDynWeakLinkHandle(DynWeak);
130
131impl Default for InnerDynWeakLinkHandle {
132    fn default() -> Self { Self(Weak::<()>::new() as DynWeak) }
133}
134
135impl PartialEq for InnerDynWeakLinkHandle {
136    fn eq(&self, other: &Self) -> bool { self.0.ptr_eq(&other.0) }
137}
138
139impl Eq for InnerDynWeakLinkHandle {}
140
141/// The inner data is not shared with the client, so it can't rely on this.
142#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)]
143pub struct DynWeakLinkHandle {
144    #[serde(skip)]
145    inner: InnerDynWeakLinkHandle,
146}
147
148impl std::fmt::Debug for DynWeakLinkHandle {
149    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
150        f.debug_tuple("DynWeakLinkHandle")
151            .field(&self.exists())
152            .finish()
153    }
154}
155
156impl DynWeakLinkHandle {
157    /// If the link this refers to still exists.
158    pub fn exists(&self) -> bool { self.inner.0.strong_count() > 0 }
159
160    /// If this is the same link as `link`.
161    pub fn is_link(&self, link: &LinkHandle<impl Link>) -> bool {
162        std::ptr::addr_eq(self.inner.0.as_ptr(), Arc::as_ptr(&link.link))
163    }
164}