rowan/green/
token.rs

1use std::{
2    borrow::Borrow,
3    fmt,
4    mem::{self, ManuallyDrop},
5    ops, ptr,
6};
7
8use countme::Count;
9
10use crate::{
11    arc::{Arc, HeaderSlice, ThinArc},
12    green::SyntaxKind,
13    TextSize,
14};
15
16#[derive(PartialEq, Eq, Hash)]
17struct GreenTokenHead {
18    kind: SyntaxKind,
19    _c: Count<GreenToken>,
20}
21
22type Repr = HeaderSlice<GreenTokenHead, [u8]>;
23type ReprThin = HeaderSlice<GreenTokenHead, [u8; 0]>;
24#[repr(transparent)]
25pub struct GreenTokenData {
26    data: ReprThin,
27}
28
29impl PartialEq for GreenTokenData {
30    fn eq(&self, other: &Self) -> bool {
31        self.kind() == other.kind() && self.text() == other.text()
32    }
33}
34
35/// Leaf node in the immutable tree.
36#[derive(PartialEq, Eq, Hash, Clone)]
37#[repr(transparent)]
38pub struct GreenToken {
39    ptr: ThinArc<GreenTokenHead, u8>,
40}
41
42impl ToOwned for GreenTokenData {
43    type Owned = GreenToken;
44
45    #[inline]
46    fn to_owned(&self) -> GreenToken {
47        let green = unsafe { GreenToken::from_raw(ptr::NonNull::from(self)) };
48        let green = ManuallyDrop::new(green);
49        GreenToken::clone(&green)
50    }
51}
52
53impl Borrow<GreenTokenData> for GreenToken {
54    #[inline]
55    fn borrow(&self) -> &GreenTokenData {
56        &*self
57    }
58}
59
60impl fmt::Debug for GreenTokenData {
61    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62        f.debug_struct("GreenToken")
63            .field("kind", &self.kind())
64            .field("text", &self.text())
65            .finish()
66    }
67}
68
69impl fmt::Debug for GreenToken {
70    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71        let data: &GreenTokenData = &*self;
72        fmt::Debug::fmt(data, f)
73    }
74}
75
76impl fmt::Display for GreenToken {
77    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78        let data: &GreenTokenData = &*self;
79        fmt::Display::fmt(data, f)
80    }
81}
82
83impl fmt::Display for GreenTokenData {
84    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85        write!(f, "{}", self.text())
86    }
87}
88
89impl GreenTokenData {
90    /// Kind of this Token.
91    #[inline]
92    pub fn kind(&self) -> SyntaxKind {
93        self.data.header.kind
94    }
95
96    /// Text of this Token.
97    #[inline]
98    pub fn text(&self) -> &str {
99        unsafe { std::str::from_utf8_unchecked(self.data.slice()) }
100    }
101
102    /// Returns the length of the text covered by this token.
103    #[inline]
104    pub fn text_len(&self) -> TextSize {
105        TextSize::of(self.text())
106    }
107}
108
109impl GreenToken {
110    /// Creates new Token.
111    #[inline]
112    pub fn new(kind: SyntaxKind, text: &str) -> GreenToken {
113        let head = GreenTokenHead { kind, _c: Count::new() };
114        let ptr = ThinArc::from_header_and_iter(head, text.bytes());
115        GreenToken { ptr }
116    }
117    #[inline]
118    pub(crate) fn into_raw(this: GreenToken) -> ptr::NonNull<GreenTokenData> {
119        let green = ManuallyDrop::new(this);
120        let green: &GreenTokenData = &*green;
121        ptr::NonNull::from(&*green)
122    }
123
124    #[inline]
125    pub(crate) unsafe fn from_raw(ptr: ptr::NonNull<GreenTokenData>) -> GreenToken {
126        let arc = Arc::from_raw(&ptr.as_ref().data as *const ReprThin);
127        let arc = mem::transmute::<Arc<ReprThin>, ThinArc<GreenTokenHead, u8>>(arc);
128        GreenToken { ptr: arc }
129    }
130}
131
132impl ops::Deref for GreenToken {
133    type Target = GreenTokenData;
134
135    #[inline]
136    fn deref(&self) -> &GreenTokenData {
137        unsafe {
138            let repr: &Repr = &self.ptr;
139            let repr: &ReprThin = &*(repr as *const Repr as *const ReprThin);
140            mem::transmute::<&ReprThin, &GreenTokenData>(repr)
141        }
142    }
143}