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 | let green: GreenToken = unsafe { GreenToken::from_raw(ptr:ptr::NonNull::from(self)) }; |
48 | let green: ManuallyDrop = ManuallyDrop::new(green); |
49 | GreenToken::clone(&green) |
50 | } |
51 | } |
52 | |
53 | impl Borrow<GreenTokenData> for GreenToken { |
54 | #[inline ] |
55 | fn borrow(&self) -> &GreenTokenData { |
56 | &*self |
57 | } |
58 | } |
59 | |
60 | impl fmt::Debug for GreenTokenData { |
61 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
62 | f&mut DebugStruct<'_, '_>.debug_struct("GreenToken" ) |
63 | .field("kind" , &self.kind()) |
64 | .field(name:"text" , &self.text()) |
65 | .finish() |
66 | } |
67 | } |
68 | |
69 | impl fmt::Debug for GreenToken { |
70 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
71 | let data: &GreenTokenData = &*self; |
72 | fmt::Debug::fmt(self:data, f) |
73 | } |
74 | } |
75 | |
76 | impl fmt::Display for GreenToken { |
77 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
78 | let data: &GreenTokenData = &*self; |
79 | fmt::Display::fmt(self:data, f) |
80 | } |
81 | } |
82 | |
83 | impl fmt::Display for GreenTokenData { |
84 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
85 | write!(f, " {}" , self.text()) |
86 | } |
87 | } |
88 | |
89 | impl 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 | |
109 | impl GreenToken { |
110 | /// Creates new Token. |
111 | #[inline ] |
112 | pub fn new(kind: SyntaxKind, text: &str) -> GreenToken { |
113 | let head: GreenTokenHead = GreenTokenHead { kind, _c: Count::new() }; |
114 | let ptr: ThinArc = ThinArc::from_header_and_iter(header:head, items:text.bytes()); |
115 | GreenToken { ptr } |
116 | } |
117 | #[inline ] |
118 | pub(crate) fn into_raw(this: GreenToken) -> ptr::NonNull<GreenTokenData> { |
119 | let green: ManuallyDrop = 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> = Arc::from_raw(&ptr.as_ref().data as *const ReprThin); |
127 | let arc: ThinArc = mem::transmute::<Arc<ReprThin>, ThinArc<GreenTokenHead, u8>>(src:arc); |
128 | GreenToken { ptr: arc } |
129 | } |
130 | } |
131 | |
132 | impl 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>(src:repr) |
141 | } |
142 | } |
143 | } |
144 | |