]> git.proxmox.com Git - rustc.git/blob - vendor/rowan/src/green/element.rs
New upstream version 1.46.0~beta.2+dfsg1
[rustc.git] / vendor / rowan / src / green / element.rs
1 use std::{fmt, hash, mem};
2
3 use thin_dst::ErasedPtr;
4
5 use crate::{
6 green::{GreenNode, GreenToken, SyntaxKind},
7 NodeOrToken, TextSize,
8 };
9
10 pub(super) type GreenElement = NodeOrToken<GreenNode, GreenToken>;
11 pub(crate) type GreenElementRef<'a> = NodeOrToken<&'a GreenNode, &'a GreenToken>;
12
13 #[repr(transparent)]
14 pub(super) struct PackedGreenElement {
15 ptr: ErasedPtr,
16 }
17
18 impl From<GreenNode> for GreenElement {
19 #[inline]
20 fn from(node: GreenNode) -> GreenElement {
21 NodeOrToken::Node(node)
22 }
23 }
24
25 impl<'a> From<&'a GreenNode> for GreenElementRef<'a> {
26 #[inline]
27 fn from(node: &'a GreenNode) -> GreenElementRef<'a> {
28 NodeOrToken::Node(node)
29 }
30 }
31
32 impl From<GreenNode> for PackedGreenElement {
33 #[inline]
34 fn from(node: GreenNode) -> PackedGreenElement {
35 unsafe { mem::transmute(node) }
36 }
37 }
38
39 impl From<GreenToken> for GreenElement {
40 #[inline]
41 fn from(token: GreenToken) -> GreenElement {
42 NodeOrToken::Token(token)
43 }
44 }
45
46 impl<'a> From<&'a GreenToken> for GreenElementRef<'a> {
47 #[inline]
48 fn from(token: &'a GreenToken) -> GreenElementRef<'a> {
49 NodeOrToken::Token(token)
50 }
51 }
52
53 impl From<GreenToken> for PackedGreenElement {
54 #[inline]
55 fn from(token: GreenToken) -> PackedGreenElement {
56 unsafe { mem::transmute(token) }
57 }
58 }
59
60 impl GreenElement {
61 /// Returns kind of this element.
62 #[inline]
63 pub fn kind(&self) -> SyntaxKind {
64 self.as_ref().kind()
65 }
66
67 /// Returns the length of the text covered by this element.
68 #[inline]
69 pub fn text_len(&self) -> TextSize {
70 self.as_ref().text_len()
71 }
72 }
73
74 impl GreenElementRef<'_> {
75 /// Returns kind of this element.
76 #[inline]
77 pub fn kind(&self) -> SyntaxKind {
78 match self {
79 NodeOrToken::Node(it) => it.kind(),
80 NodeOrToken::Token(it) => it.kind(),
81 }
82 }
83
84 /// Returns the length of the text covered by this element.
85 #[inline]
86 pub fn text_len(self) -> TextSize {
87 match self {
88 NodeOrToken::Node(it) => it.text_len(),
89 NodeOrToken::Token(it) => it.text_len(),
90 }
91 }
92 }
93
94 impl From<GreenElement> for PackedGreenElement {
95 fn from(element: GreenElement) -> Self {
96 match element {
97 NodeOrToken::Node(node) => node.into(),
98 NodeOrToken::Token(token) => token.into(),
99 }
100 }
101 }
102
103 impl From<PackedGreenElement> for GreenElement {
104 fn from(element: PackedGreenElement) -> Self {
105 if element.is_node() {
106 NodeOrToken::Node(element.into_node().unwrap())
107 } else {
108 NodeOrToken::Token(element.into_token().unwrap())
109 }
110 }
111 }
112
113 impl PackedGreenElement {
114 fn is_node(&self) -> bool {
115 self.ptr.as_ptr() as usize & 1 == 0
116 }
117
118 pub(crate) fn as_node(&self) -> Option<&GreenNode> {
119 if self.is_node() {
120 unsafe { Some(&*(&self.ptr as *const ErasedPtr as *const GreenNode)) }
121 } else {
122 None
123 }
124 }
125
126 pub(crate) fn into_node(self) -> Option<GreenNode> {
127 if self.is_node() {
128 unsafe { Some(mem::transmute(self)) }
129 } else {
130 None
131 }
132 }
133
134 pub(crate) fn as_token(&self) -> Option<&GreenToken> {
135 if !self.is_node() {
136 unsafe { Some(&*(&self.ptr as *const ErasedPtr as *const GreenToken)) }
137 } else {
138 None
139 }
140 }
141
142 pub(crate) fn into_token(self) -> Option<GreenToken> {
143 if !self.is_node() {
144 unsafe { Some(mem::transmute(self)) }
145 } else {
146 None
147 }
148 }
149
150 pub(crate) fn as_ref(&self) -> GreenElementRef<'_> {
151 if self.is_node() {
152 NodeOrToken::Node(self.as_node().unwrap())
153 } else {
154 NodeOrToken::Token(self.as_token().unwrap())
155 }
156 }
157 }
158
159 impl fmt::Debug for PackedGreenElement {
160 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
161 if self.is_node() {
162 self.as_node().unwrap().fmt(f)
163 } else {
164 self.as_token().unwrap().fmt(f)
165 }
166 }
167 }
168
169 impl Eq for PackedGreenElement {}
170 impl PartialEq for PackedGreenElement {
171 fn eq(&self, other: &Self) -> bool {
172 self.as_node() == other.as_node() && self.as_token() == other.as_token()
173 }
174 }
175
176 impl hash::Hash for PackedGreenElement {
177 fn hash<H>(&self, state: &mut H)
178 where
179 H: hash::Hasher,
180 {
181 if self.is_node() {
182 self.as_node().unwrap().hash(state)
183 } else {
184 self.as_token().unwrap().hash(state)
185 }
186 }
187 }
188
189 impl Drop for PackedGreenElement {
190 fn drop(&mut self) {
191 if self.is_node() {
192 PackedGreenElement { ptr: self.ptr }.into_node();
193 } else {
194 PackedGreenElement { ptr: self.ptr }.into_token();
195 }
196 }
197 }
198
199 unsafe impl Send for PackedGreenElement
200 where
201 GreenToken: Send,
202 GreenNode: Send,
203 {
204 }
205 unsafe impl Sync for PackedGreenElement
206 where
207 GreenToken: Sync,
208 GreenNode: Sync,
209 {
210 }