Skip to main content

fyrox_core/pool/
payload.rs

1// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21use std::cell::UnsafeCell;
22
23pub trait PayloadContainer: Sized {
24    type Element: Sized;
25
26    fn new_empty() -> Self;
27
28    fn new(element: Self::Element) -> Self;
29
30    fn is_some(&self) -> bool;
31
32    fn as_ref(&self) -> Option<&Self::Element>;
33
34    fn as_mut(&mut self) -> Option<&mut Self::Element>;
35
36    fn replace(&mut self, element: Self::Element) -> Option<Self::Element>;
37
38    fn take(&mut self) -> Option<Self::Element>;
39}
40
41impl<T> PayloadContainer for Option<T> {
42    type Element = T;
43
44    #[inline]
45    fn new_empty() -> Self {
46        Self::None
47    }
48
49    #[inline]
50    fn new(element: Self::Element) -> Self {
51        Self::Some(element)
52    }
53
54    #[inline]
55    fn is_some(&self) -> bool {
56        Option::is_some(self)
57    }
58
59    #[inline]
60    fn as_ref(&self) -> Option<&Self::Element> {
61        Option::as_ref(self)
62    }
63
64    #[inline]
65    fn as_mut(&mut self) -> Option<&mut Self::Element> {
66        Option::as_mut(self)
67    }
68
69    #[inline]
70    fn replace(&mut self, element: Self::Element) -> Option<Self::Element> {
71        Option::replace(self, element)
72    }
73
74    #[inline]
75    fn take(&mut self) -> Option<Self::Element> {
76        Option::take(self)
77    }
78}
79
80#[derive(Debug)]
81pub struct Payload<P>(pub UnsafeCell<P>);
82
83impl<T, P> Clone for Payload<P>
84where
85    T: Sized,
86    P: PayloadContainer<Element = T> + Clone,
87{
88    fn clone(&self) -> Self {
89        Self(UnsafeCell::new(self.get().clone()))
90    }
91}
92
93impl<T, P> Payload<P>
94where
95    T: Sized,
96    P: PayloadContainer<Element = T>,
97{
98    pub fn new(data: T) -> Self {
99        Self(UnsafeCell::new(P::new(data)))
100    }
101
102    pub fn new_empty() -> Self {
103        Self(UnsafeCell::new(P::new_empty()))
104    }
105
106    pub fn get(&self) -> &P {
107        unsafe { &*self.0.get() }
108    }
109
110    pub fn get_mut(&mut self) -> &mut P {
111        self.0.get_mut()
112    }
113
114    pub fn is_some(&self) -> bool {
115        self.get().is_some()
116    }
117
118    pub fn as_ref(&self) -> Option<&T> {
119        self.get().as_ref()
120    }
121
122    pub fn as_mut(&mut self) -> Option<&mut T> {
123        self.get_mut().as_mut()
124    }
125
126    pub fn replace(&mut self, element: T) -> Option<T> {
127        self.get_mut().replace(element)
128    }
129
130    pub fn take(&mut self) -> Option<T> {
131        self.get_mut().take()
132    }
133}
134
135// SAFETY: This is safe, because Payload is never directly exposed to the call site. It is always
136// accessed using a sort of read-write lock that forces borrowing rules at runtime.
137unsafe impl<T, P> Sync for Payload<P>
138where
139    T: Sized,
140    P: PayloadContainer<Element = T>,
141{
142}
143
144// SAFETY: This is safe, because Payload is never directly exposed to the call site. It is always
145// accessed using a sort of read-write lock that forces borrowing rules at runtime.
146unsafe impl<T, P> Send for Payload<P>
147where
148    T: Sized,
149    P: PayloadContainer<Element = T>,
150{
151}