nu_protocol/
id.rs

1use std::any;
2use std::fmt::{Debug, Display, Error, Formatter};
3use std::marker::PhantomData;
4
5use serde::{Deserialize, Serialize};
6
7#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
8pub struct Id<M, V = usize> {
9    inner: V,
10    _phantom: PhantomData<M>,
11}
12
13impl<M, V> Id<M, V> {
14    /// Creates a new `Id`.
15    ///
16    /// Using a distinct type like `Id` instead of `usize` helps us avoid mixing plain integers
17    /// with identifiers.
18    #[inline]
19    pub const fn new(inner: V) -> Self {
20        Self {
21            inner,
22            _phantom: PhantomData,
23        }
24    }
25}
26
27impl<M, V> Id<M, V>
28where
29    V: Copy,
30{
31    /// Returns the inner value.
32    ///
33    /// This requires an explicit call, ensuring we only use the raw value when intended.
34    #[inline]
35    pub const fn get(self) -> V {
36        self.inner
37    }
38}
39
40impl<M> Id<M, usize> {
41    pub const ZERO: Self = Self::new(0);
42}
43
44impl<M, V> Debug for Id<M, V>
45where
46    V: Display,
47{
48    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
49        let marker = any::type_name::<M>().split("::").last().expect("not empty");
50        write!(f, "{marker}Id({})", self.inner)
51    }
52}
53
54impl<M, V> Serialize for Id<M, V>
55where
56    V: Serialize,
57{
58    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
59    where
60        S: serde::Serializer,
61    {
62        self.inner.serialize(serializer)
63    }
64}
65
66impl<'de, M, V> Deserialize<'de> for Id<M, V>
67where
68    V: Deserialize<'de>,
69{
70    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
71    where
72        D: serde::Deserializer<'de>,
73    {
74        let inner = V::deserialize(deserializer)?;
75        Ok(Self {
76            inner,
77            _phantom: PhantomData,
78        })
79    }
80}
81
82pub mod marker {
83    #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
84    pub struct Var;
85    #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
86    pub struct Decl;
87    #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
88    pub struct Block;
89    #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
90    pub struct Module;
91    #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
92    pub struct Overlay;
93    #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
94    pub struct File;
95    #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
96    pub struct VirtualPath;
97    #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
98    pub struct Span;
99    #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
100    pub struct Reg;
101    #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
102    pub struct Job;
103}
104
105pub type VarId = Id<marker::Var>;
106pub type DeclId = Id<marker::Decl>;
107pub type BlockId = Id<marker::Block>;
108pub type ModuleId = Id<marker::Module>;
109pub type OverlayId = Id<marker::Overlay>;
110pub type FileId = Id<marker::File>;
111pub type VirtualPathId = Id<marker::VirtualPath>;
112pub type SpanId = Id<marker::Span>;
113pub type JobId = Id<marker::Job>;
114
115/// An ID for an [IR](crate::ir) register.
116///
117/// `%n` is a common shorthand for `RegId(n)`.
118///
119/// Note: `%0` is allocated with the block input at the beginning of a compiled block.
120pub type RegId = Id<marker::Reg, u32>;
121
122impl Display for JobId {
123    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
124        write!(f, "{}", self.inner)
125    }
126}
127
128impl Display for RegId {
129    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
130        write!(f, "%{}", self.get())
131    }
132}