Skip to main content

substrate_data/model/atom/
atom.rs

1//! [`Atom`]: a name kept once a process, a number in frames.
2
3use std::fmt;
4
5use super::table::table;
6
7/// A name kept once a process; see the module.
8#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
9pub struct Atom(u32);
10
11impl Atom {
12    /// `name`'s atom.
13    #[must_use]
14    pub fn new(name: &str) -> Atom {
15        Atom((table().intern)(name))
16    }
17
18    /// The atom numbered `n`, if there's one.
19    #[must_use]
20    pub fn from_number(n: u32) -> Option<Atom> {
21        (table().name)(n).map(|_| Atom(n))
22    }
23
24    /// Its number in this process's table.
25    #[must_use]
26    pub fn number(self) -> u32 {
27        self.0
28    }
29
30    /// Its text.
31    #[must_use]
32    pub fn as_str(self) -> &'static str {
33        (table().name)(self.0).unwrap_or_default()
34    }
35}
36
37impl fmt::Debug for Atom {
38    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39        write!(f, "Atom({:?})", self.as_str())
40    }
41}
42
43impl fmt::Display for Atom {
44    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45        f.write_str(self.as_str())
46    }
47}
48
49impl From<&str> for Atom {
50    fn from(name: &str) -> Atom {
51        Atom::new(name)
52    }
53}
54
55impl From<String> for Atom {
56    fn from(name: String) -> Atom {
57        Atom::new(&name)
58    }
59}
60
61impl From<&String> for Atom {
62    fn from(name: &String) -> Atom {
63        Atom::new(name)
64    }
65}
66
67impl PartialEq<str> for Atom {
68    fn eq(&self, other: &str) -> bool {
69        self.as_str() == other
70    }
71}
72
73impl PartialEq<&str> for Atom {
74    fn eq(&self, other: &&str) -> bool {
75        self.as_str() == *other
76    }
77}
78
79impl PartialEq<String> for Atom {
80    fn eq(&self, other: &String) -> bool {
81        self.as_str() == other
82    }
83}
84
85impl PartialEq<Atom> for String {
86    fn eq(&self, other: &Atom) -> bool {
87        self == other.as_str()
88    }
89}
90
91impl std::ops::Deref for Atom {
92    type Target = str;
93    fn deref(&self) -> &str {
94        self.as_str()
95    }
96}
97
98impl Default for Atom {
99    /// The empty name's atom.
100    fn default() -> Atom {
101        Atom::new("")
102    }
103}
104
105#[cfg(test)]
106mod tests {
107    use super::*;
108
109    #[test]
110    fn a_name_is_one_atom() {
111        let a = Atom::new("test:atom_a");
112        assert_eq!(a, Atom::new("test:atom_a"));
113        assert_ne!(a, Atom::new("test:atom_b"));
114        assert_eq!(Atom::from_number(a.number()), Some(a));
115        assert_eq!(Atom::from_number(u32::MAX), None);
116        assert_eq!(a.to_string(), "test:atom_a");
117    }
118}