pag_parser/
utilities.rs

1// Copyright (c) 2023 Paguroidea Developers
2//
3// Licensed under the Apache License, Version 2.0
4// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
5// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. All files in the project carrying such notice may not be copied,
7// modified, or distributed except according to those terms.
8
9#[derive(Debug, Clone, Copy, PartialOrd, Ord)]
10pub struct Symbol<'a>(&'a str);
11
12impl<'a> Symbol<'a> {
13    pub fn new(data: &'a str) -> Self {
14        Self(data)
15    }
16    pub fn name(&self) -> &'a str {
17        self.0
18    }
19}
20
21impl<'a> std::hash::Hash for Symbol<'a> {
22    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
23        self.0.as_ptr().hash(state);
24        self.0.len().hash(state);
25    }
26}
27
28fn is_ascii_ident_body(x: char) -> bool {
29    x.is_ascii_alphanumeric() || x == '_'
30}
31
32fn is_ascii_ident_head(x: char) -> bool {
33    x.is_ascii_alphabetic() || x == '_'
34}
35
36fn is_ascii_ident(x: &str) -> bool {
37    !x.is_empty()
38        && is_ascii_ident_head(unsafe { x.chars().next().unwrap_unchecked() })
39        && x[1..].chars().all(is_ascii_ident_body)
40}
41
42impl<'a> std::fmt::Display for Symbol<'a> {
43    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44        if is_ascii_ident(self.0) {
45            write!(f, "{}", self.0)
46        } else {
47            write!(f, "S{:X}_{}", self.0.as_ptr() as usize, self.0.len())
48        }
49    }
50}
51
52impl<'a, 'b> PartialEq<Symbol<'b>> for Symbol<'a> {
53    fn eq(&self, other: &Symbol<'b>) -> bool {
54        self.0.as_ptr().eq(&other.0.as_ptr()) && self.0.len() == other.0.len()
55    }
56}
57
58impl<'a> Eq for Symbol<'a> {}
59
60macro_rules! unreachable_branch {
61    ($($arg:tt)*) => {
62        if cfg!(debug_assertions) {
63            unreachable!($($arg)*)
64        } else {
65            unsafe { std::hint::unreachable_unchecked() }
66        }
67    };
68}
69
70pub(crate) use unreachable_branch;