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, V> Debug for Id<M, V>
41where
42    V: Display,
43{
44    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
45        let marker = any::type_name::<M>().split("::").last().expect("not empty");
46        write!(f, "{marker}Id({})", self.inner)
47    }
48}
49
50impl<M, V> Serialize for Id<M, V>
51where
52    V: Serialize,
53{
54    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
55    where
56        S: serde::Serializer,
57    {
58        self.inner.serialize(serializer)
59    }
60}
61
62impl<'de, M, V> Deserialize<'de> for Id<M, V>
63where
64    V: Deserialize<'de>,
65{
66    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
67    where
68        D: serde::Deserializer<'de>,
69    {
70        let inner = V::deserialize(deserializer)?;
71        Ok(Self {
72            inner,
73            _phantom: PhantomData,
74        })
75    }
76}
77
78pub mod marker {
79    #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
80    pub struct Var;
81    #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
82    pub struct Decl;
83    #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
84    pub struct Block;
85    #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
86    pub struct Module;
87    #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
88    pub struct Overlay;
89    #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
90    pub struct File;
91    #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
92    pub struct VirtualPath;
93    #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
94    pub struct Span;
95    #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
96    pub struct Reg;
97    #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
98    pub struct Job;
99}
100
101pub type VarId = Id<marker::Var>;
102pub type DeclId = Id<marker::Decl>;
103pub type BlockId = Id<marker::Block>;
104pub type ModuleId = Id<marker::Module>;
105pub type OverlayId = Id<marker::Overlay>;
106pub type FileId = Id<marker::File>;
107pub type VirtualPathId = Id<marker::VirtualPath>;
108pub type SpanId = Id<marker::Span>;
109pub type JobId = Id<marker::Job>;
110
111/// An ID for an [IR](crate::ir) register.
112///
113/// `%n` is a common shorthand for `RegId(n)`.
114///
115/// Note: `%0` is allocated with the block input at the beginning of a compiled block.
116pub type RegId = Id<marker::Reg, u32>;
117
118impl Display for RegId {
119    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
120        write!(f, "%{}", self.get())
121    }
122}