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#[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 #[inline]
92 pub fn kind(&self) -> SyntaxKind {
93 self.data.header.kind
94 }
95
96 #[inline]
98 pub fn text(&self) -> &str {
99 unsafe { std::str::from_utf8_unchecked(self.data.slice()) }
100 }
101
102 #[inline]
104 pub fn text_len(&self) -> TextSize {
105 TextSize::of(self.text())
106 }
107}
108
109impl GreenToken {
110 #[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}