miden_rowan/green/
token.rs1use alloc::borrow::ToOwned;
2use core::{
3 borrow::Borrow,
4 fmt,
5 mem::{self, ManuallyDrop},
6 ops, ptr,
7};
8
9use crate::{
10 TextSize,
11 arc::{Arc, HeaderSlice, ThinArc},
12 countme::Count,
13 green::SyntaxKind,
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 { core::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]
134 pub(crate) unsafe fn from_raw(ptr: ptr::NonNull<GreenTokenData>) -> GreenToken {
135 let arc = unsafe {
136 let arc = Arc::from_raw(&ptr.as_ref().data as *const ReprThin);
137 mem::transmute::<Arc<ReprThin>, ThinArc<GreenTokenHead, u8>>(arc)
138 };
139 GreenToken { ptr: arc }
140 }
141}
142
143impl ops::Deref for GreenToken {
144 type Target = GreenTokenData;
145
146 #[inline]
147 fn deref(&self) -> &GreenTokenData {
148 unsafe {
149 let repr: &Repr = &self.ptr;
150 let repr: &ReprThin = &*(repr as *const Repr as *const ReprThin);
151 mem::transmute::<&ReprThin, &GreenTokenData>(repr)
152 }
153 }
154}