1use std::{
2 fmt::{Debug, Display},
3 mem::transmute_copy,
4 num::{NonZero, NonZeroU64, TryFromIntError},
5 ops::Deref,
6};
7
8use bincode::{
9 Decode, Encode,
10 de::Decoder,
11 enc::Encoder,
12 error::{DecodeError, EncodeError},
13 impl_borrow_decode,
14};
15use serde::{Deserialize, Serialize, de::Visitor};
16
17use crate::{TaskPersistence, registry};
18
19macro_rules! define_id {
20 (
21 $name:ident : $primitive:ty
22 $(,max = $max:expr)?
23 $(,derive($($derive:ty),*))?
24 $(,serde($serde:tt))?
25 $(,doc = $doc:literal)*
26 $(,)?
27 ) => {
28 $(#[doc = $doc])*
29 #[derive(Hash, Clone, Copy, PartialEq, Eq, PartialOrd, Ord $($(,$derive)*)? )]
30 $(#[serde($serde)])?
31 pub struct $name {
32 id: NonZero<$primitive>,
33 }
34
35 impl $name {
36 pub const MIN: Self = Self { id: NonZero::<$primitive>::MIN };
37 pub const MAX: Self = {
40 let _max: $primitive = NonZero::<$primitive>::MAX.get();
41 $( let _max: $primitive = $max; )?
42 Self { id: unsafe { NonZero::<$primitive>::new_unchecked(_max) } }
45 };
46
47 pub const unsafe fn new_unchecked(id: $primitive) -> Self {
53 Self { id: unsafe { NonZero::<$primitive>::new_unchecked(id) } }
54 }
55 pub fn new(id: $primitive) -> Option<Self> {
60 NonZero::<$primitive>::new(id).map(|id| Self{id})
61 }
62 pub const fn to_non_zero_u64(self) -> NonZeroU64 {
65 const {
66 assert!(<$primitive>::BITS <= u64::BITS);
67 }
68 unsafe { NonZeroU64::new_unchecked(self.id.get() as u64) }
69 }
70 pub const fn to_non_zero_primitive(self) -> NonZero<$primitive> {
72 self.id
73 }
74 pub const fn to_primitive(self) -> $primitive {
75 self.id.get()
76 }
77 }
78
79 impl Display for $name {
80 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
81 write!(f, concat!(stringify!($name), " {}"), self.id)
82 }
83 }
84
85 impl Deref for $name {
86 type Target = $primitive;
87
88 fn deref(&self) -> &Self::Target {
89 unsafe { transmute_copy(&&self.id) }
91 }
92 }
93
94 define_id!(@impl_try_from_primitive_conversion $name $primitive);
95
96 impl From<NonZero<$primitive>> for $name {
97 fn from(id: NonZero::<$primitive>) -> Self {
98 Self {
99 id,
100 }
101 }
102 }
103
104 impl From<$name> for NonZeroU64 {
105 fn from(id: $name) -> Self {
106 id.to_non_zero_u64()
107 }
108 }
109 };
110 (
111 @impl_try_from_primitive_conversion $name:ident u64
112 ) => {
113 };
115 (
116 @impl_try_from_primitive_conversion $name:ident $primitive:ty
117 ) => {
118 impl TryFrom<$primitive> for $name {
119 type Error = TryFromIntError;
120
121 fn try_from(id: $primitive) -> Result<Self, Self::Error> {
122 Ok(Self {
123 id: NonZero::try_from(id)?
124 })
125 }
126 }
127
128 impl TryFrom<NonZeroU64> for $name {
129 type Error = TryFromIntError;
130
131 fn try_from(id: NonZeroU64) -> Result<Self, Self::Error> {
132 Ok(Self { id: NonZero::try_from(id)? })
133 }
134 }
135 };
136}
137
138define_id!(
139 TaskId: u32,
140 max = TASK_ID_MAX,
142 derive(Deserialize, Decode),
143 serde(transparent),
144);
145define_id!(
146 ValueTypeId: u16,
147 max = crate::CellId::MAX_VALUE_TYPE_ID,
149);
150define_id!(FunctionId: u16);
151define_id!(TraitTypeId: u16);
152define_id!(
153 LocalTaskId: u32,
154 derive(Debug, Serialize, Deserialize, Encode, Decode),
155 serde(transparent),
156 doc = "Represents the nth `local` function call inside a task.",
157);
158define_id!(
159 ExecutionId: u16,
160 derive(Debug, Serialize, Deserialize, Encode, Decode),
161 serde(transparent),
162 doc = "An identifier for a specific task execution. Used to assert that local `Vc`s don't \
163 leak. This value may overflow and re-use old values.",
164);
165
166impl Serialize for TaskId {
169 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
170 debug_assert!(
171 !self.is_transient(),
172 "transient TaskId must not be serialized"
173 );
174 self.id.serialize(serializer)
175 }
176}
177
178impl Encode for TaskId {
179 fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
180 debug_assert!(!self.is_transient(), "transient TaskId must not be encoded");
181 self.id.encode(encoder)
182 }
183}
184
185impl Debug for TaskId {
186 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
187 f.debug_struct("TaskId").field("id", &self.id).finish()
188 }
189}
190
191unsafe impl crate::NonLocalValue for TaskId {}
192
193pub const TRANSIENT_TASK_BIT: u32 = 0x4000_0000;
196
197pub const TASK_ID_MAX: u32 = 0x7FFF_FFFF;
199
200impl TaskId {
201 pub fn is_transient(&self) -> bool {
202 **self & TRANSIENT_TASK_BIT != 0
203 }
204 pub fn persistence(&self) -> TaskPersistence {
205 if self.is_transient() {
207 TaskPersistence::Transient
208 } else {
209 TaskPersistence::Persistent
210 }
211 }
212}
213
214macro_rules! make_registered_serializable {
215 ($ty:ty, $primitive:ty, $get_object:path, $validate_type_id:path $(,)?) => {
216 impl Serialize for $ty {
217 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
218 where
219 S: serde::Serializer,
220 {
221 serializer.serialize_u16(self.id.into())
222 }
223 }
224
225 impl<'de> Deserialize<'de> for $ty {
226 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
227 where
228 D: serde::Deserializer<'de>,
229 {
230 struct DeserializeVisitor;
231 impl<'de> Visitor<'de> for DeserializeVisitor {
232 type Value = $ty;
233
234 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
235 formatter.write_str(concat!("an id of a registered ", stringify!($ty)))
236 }
237
238 fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
239 where
240 E: serde::de::Error,
241 {
242 match Self::Value::new(v) {
243 Some(value) => {
244 if let Some(error) = $validate_type_id(value) {
245 Err(E::custom(error))
246 } else {
247 Ok(value)
248 }
249 }
250 None => Err(E::unknown_variant(&format!("{v}"), &["a non zero u16"])),
251 }
252 }
253 }
254
255 deserializer.deserialize_u16(DeserializeVisitor)
256 }
257 }
258
259 impl Debug for $ty {
260 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
261 f.debug_struct(stringify!($ty))
262 .field("id", &self.id)
263 .field("name", &$get_object(*self))
264 .finish()
265 }
266 }
267
268 impl Encode for $ty {
269 fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
270 <NonZero<$primitive> as Encode>::encode(&self.id, encoder)
271 }
272 }
273
274 impl<Context> Decode<Context> for $ty {
275 fn decode<D: Decoder<Context = Context>>(decoder: &mut D) -> Result<Self, DecodeError> {
276 let value = Self {
277 id: NonZero::<$primitive>::decode(decoder)?,
278 };
279 if let Some(error) = $validate_type_id(value) {
280 Err(DecodeError::OtherString(error.to_string()))
281 } else {
282 Ok(value)
283 }
284 }
285 }
286
287 impl_borrow_decode!($ty);
288 };
289}
290
291make_registered_serializable!(
292 ValueTypeId,
293 u16,
294 registry::get_value_type,
295 registry::validate_value_type_id,
296);
297make_registered_serializable!(
298 TraitTypeId,
299 u16,
300 registry::get_trait,
301 registry::validate_trait_type_id,
302);
303make_registered_serializable!(
304 FunctionId,
305 u16,
306 registry::get_native_function,
307 registry::validate_function_id,
308);