1 | use std::{ |
2 | borrow::Borrow, |
3 | fmt, |
4 | mem::{self, ManuallyDrop}, |
5 | ops, ptr, |
6 | }; |
7 | |
8 | use countme::Count; |
9 | |
10 | use crate::{ |
11 | arc::{Arc, HeaderSlice, ThinArc}, |
12 | green::SyntaxKind, |
13 | TextSize, |
14 | }; |
15 | |
16 | #[derive (PartialEq, Eq, Hash)] |
17 | struct GreenTokenHead { |
18 | kind: SyntaxKind, |
19 | _c: Count<GreenToken>, |
20 | } |
21 | |
22 | type Repr = HeaderSlice<GreenTokenHead, [u8]>; |
23 | type ReprThin = HeaderSlice<GreenTokenHead, [u8; 0]>; |
24 | #[repr (transparent)] |
25 | pub struct GreenTokenData { |
26 | data: ReprThin, |
27 | } |
28 | |
29 | impl 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)] |
38 | pub struct GreenToken { |
39 | ptr: ThinArc<GreenTokenHead, u8>, |
40 | } |
41 | |
42 | impl 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 | |
55 | impl Borrow<GreenTokenData> for GreenToken { |
56 | #[inline ] |
57 | fn borrow(&self) -> &GreenTokenData { |
58 | &*self |
59 | } |
60 | } |
61 | |
62 | impl 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 | |
71 | impl 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 | |
78 | impl 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 | |
85 | impl fmt::Display for GreenTokenData { |
86 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
87 | write!(f, " {}" , self.text()) |
88 | } |
89 | } |
90 | |
91 | impl 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 | |
111 | impl 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 | |
134 | impl 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 | |