]> git.proxmox.com Git - rustc.git/blob - vendor/rowan/src/green/token.rs
New upstream version 1.46.0~beta.2+dfsg1
[rustc.git] / vendor / rowan / src / green / token.rs
1 use std::{convert::TryFrom, fmt, hash, mem::ManuallyDrop, ptr, sync::Arc};
2
3 use crate::{green::SyntaxKind, SmolStr, TextSize};
4
5 #[repr(align(2))] // NB: this is an at-least annotation
6 #[derive(Debug, PartialEq, Eq, Hash)]
7 struct GreenTokenData {
8 kind: SyntaxKind,
9 text: SmolStr,
10 }
11
12 /// Leaf node in the immutable tree.
13 pub struct GreenToken {
14 ptr: ptr::NonNull<GreenTokenData>,
15 }
16
17 unsafe impl Send for GreenToken {} // where GreenTokenData: Send + Sync
18 unsafe impl Sync for GreenToken {} // where GreenTokenData: Send + Sync
19
20 impl GreenToken {
21 fn add_tag(ptr: ptr::NonNull<GreenTokenData>) -> ptr::NonNull<GreenTokenData> {
22 unsafe {
23 let ptr = ((ptr.as_ptr() as usize) | 1) as *mut GreenTokenData;
24 ptr::NonNull::new_unchecked(ptr)
25 }
26 }
27
28 fn remove_tag(ptr: ptr::NonNull<GreenTokenData>) -> ptr::NonNull<GreenTokenData> {
29 unsafe {
30 let ptr = ((ptr.as_ptr() as usize) & !1) as *mut GreenTokenData;
31 ptr::NonNull::new_unchecked(ptr)
32 }
33 }
34
35 fn data(&self) -> &GreenTokenData {
36 unsafe { &*Self::remove_tag(self.ptr).as_ptr() }
37 }
38
39 /// Creates new Token.
40 #[inline]
41 pub fn new(kind: SyntaxKind, text: SmolStr) -> GreenToken {
42 let ptr = Arc::into_raw(Arc::new(GreenTokenData { kind, text }));
43 let ptr = ptr::NonNull::new(ptr as *mut _).unwrap();
44 GreenToken { ptr: Self::add_tag(ptr) }
45 }
46
47 /// Kind of this Token.
48 #[inline]
49 pub fn kind(&self) -> SyntaxKind {
50 self.data().kind
51 }
52
53 /// Text of this Token.
54 #[inline]
55 pub fn text(&self) -> &SmolStr {
56 &self.data().text
57 }
58
59 /// Returns the length of the text covered by this token.
60 #[inline]
61 pub fn text_len(&self) -> TextSize {
62 TextSize::try_from(self.text().len()).unwrap()
63 }
64 }
65
66 impl fmt::Debug for GreenToken {
67 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68 let data = self.data();
69 f.debug_struct("GreenToken").field("kind", &data.kind).field("text", &data.text).finish()
70 }
71 }
72
73 impl Clone for GreenToken {
74 fn clone(&self) -> Self {
75 let ptr = Self::remove_tag(self.ptr);
76 let ptr = unsafe {
77 let arc = ManuallyDrop::new(Arc::from_raw(ptr.as_ptr()));
78 Arc::into_raw(Arc::clone(&arc))
79 };
80 let ptr = ptr::NonNull::new(ptr as *mut _).unwrap();
81 GreenToken { ptr: Self::add_tag(ptr) }
82 }
83 }
84
85 impl Eq for GreenToken {}
86 impl PartialEq for GreenToken {
87 fn eq(&self, other: &Self) -> bool {
88 self.data() == other.data()
89 }
90 }
91
92 impl hash::Hash for GreenToken {
93 fn hash<H>(&self, state: &mut H)
94 where
95 H: hash::Hasher,
96 {
97 self.data().hash(state)
98 }
99 }
100
101 impl Drop for GreenToken {
102 fn drop(&mut self) {
103 unsafe {
104 Arc::from_raw(Self::remove_tag(self.ptr).as_ptr());
105 }
106 }
107 }