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 unsafe {
48 let green: GreenToken = GreenToken::from_raw(ptr:ptr::NonNull::from(self));
49 let green: ManuallyDrop = ManuallyDrop::new(green);
50 GreenToken::clone(&green)
51 }
52 }
53}
54
55impl Borrow<GreenTokenData> for GreenToken {
56 #[inline]
57 fn borrow(&self) -> &GreenTokenData {
58 &*self
59 }
60}
61
62impl fmt::Debug for GreenTokenData {
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 f&mut DebugStruct<'_, '_>.debug_struct("GreenToken")
65 .field("kind", &self.kind())
66 .field(name:"text", &self.text())
67 .finish()
68 }
69}
70
71impl fmt::Debug for GreenToken {
72 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73 let data: &GreenTokenData = &*self;
74 fmt::Debug::fmt(self:data, f)
75 }
76}
77
78impl fmt::Display for GreenToken {
79 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
80 let data: &GreenTokenData = &*self;
81 fmt::Display::fmt(self:data, f)
82 }
83}
84
85impl fmt::Display for GreenTokenData {
86 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87 write!(f, "{}", self.text())
88 }
89}
90
91impl GreenTokenData {
92 /// Kind of this Token.
93 #[inline]
94 pub fn kind(&self) -> SyntaxKind {
95 self.data.header.kind
96 }
97
98 /// Text of this Token.
99 #[inline]
100 pub fn text(&self) -> &str {
101 unsafe { std::str::from_utf8_unchecked(self.data.slice()) }
102 }
103
104 /// Returns the length of the text covered by this token.
105 #[inline]
106 pub fn text_len(&self) -> TextSize {
107 TextSize::of(self.text())
108 }
109}
110
111impl GreenToken {
112 /// Creates new Token.
113 #[inline]
114 pub fn new(kind: SyntaxKind, text: &str) -> GreenToken {
115 let head: GreenTokenHead = GreenTokenHead { kind, _c: Count::new() };
116 let ptr: ThinArc = ThinArc::from_header_and_iter(header:head, items:text.bytes());
117 GreenToken { ptr }
118 }
119 #[inline]
120 pub(crate) fn into_raw(this: GreenToken) -> ptr::NonNull<GreenTokenData> {
121 let green: ManuallyDrop = ManuallyDrop::new(this);
122 let green: &GreenTokenData = &*green;
123 ptr::NonNull::from(&*green)
124 }
125
126 #[inline]
127 pub(crate) unsafe fn from_raw(ptr: ptr::NonNull<GreenTokenData>) -> GreenToken {
128 let arc: Arc> = Arc::from_raw(&ptr.as_ref().data as *const ReprThin);
129 let arc: ThinArc = mem::transmute::<Arc<ReprThin>, ThinArc<GreenTokenHead, u8>>(src:arc);
130 GreenToken { ptr: arc }
131 }
132}
133
134impl ops::Deref for GreenToken {
135 type Target = GreenTokenData;
136
137 #[inline]
138 fn deref(&self) -> &GreenTokenData {
139 unsafe {
140 let repr: &Repr = &self.ptr;
141 let repr: &ReprThin = &*(repr as *const Repr as *const ReprThin);
142 mem::transmute::<&ReprThin, &GreenTokenData>(src:repr)
143 }
144 }
145}
146