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