1#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
5#[cfg_attr(feature = "serde", derive(rserde::Serialize, rserde::Deserialize))]
6#[cfg_attr(feature = "serde", serde(crate = "rserde"))]
7pub struct FileId(u32);
8
9const MAX_VALUE: u32 = 0x7FFFFFFF;
10const BUILTIN_BIT: u32 = 0x80000000;
11
12impl FileId {
13 pub fn new(raw: u32) -> Self {
19 if raw > MAX_VALUE {
20 panic!("file identifier is too large");
21 }
22
23 Self(raw)
24 }
25
26 pub fn builtin(raw: u32) -> Self {
32 if raw > (MAX_VALUE - 1) {
33 panic!("file identifier is too large");
34 }
35
36 Self(BUILTIN_BIT | (raw + 1))
37 }
38
39 pub fn number(&self) -> u32 {
41 if (self.0 & BUILTIN_BIT) == BUILTIN_BIT {
42 let raw = self.0 & !BUILTIN_BIT;
43 if raw == 0 {
44 raw
45 } else {
46 raw - 1
47 }
48 } else {
49 self.0
50 }
51 }
52}
53
54impl Default for FileId {
55 fn default() -> Self {
56 Self(BUILTIN_BIT)
57 }
58}
59
60impl std::fmt::Display for FileId {
61 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62 if (self.0 & BUILTIN_BIT) == BUILTIN_BIT {
63 let raw = self.0 & !BUILTIN_BIT;
64
65 if raw == 0 {
66 write!(f, "internal")
67 } else {
68 write!(f, "builtin-{}", raw - 1)
69 }
70 } else {
71 write!(f, "{}", self.0)
72 }
73 }
74}
75
76impl From<u32> for FileId {
77 fn from(value: u32) -> Self {
78 Self(value)
79 }
80}
81
82impl From<FileId> for u32 {
83 fn from(value: FileId) -> Self {
84 value.0
85 }
86}