1 use std
::{convert::TryFrom, fmt, hash, mem::ManuallyDrop, ptr, sync::Arc}
;
3 use crate::{green::SyntaxKind, SmolStr, TextSize}
;
5 #[repr(align(2))] // NB: this is an at-least annotation
6 #[derive(Debug, PartialEq, Eq, Hash)]
7 struct GreenTokenData
{
12 /// Leaf node in the immutable tree.
13 pub struct GreenToken
{
14 ptr
: ptr
::NonNull
<GreenTokenData
>,
17 unsafe impl Send
for GreenToken {}
// where GreenTokenData: Send + Sync
18 unsafe impl Sync
for GreenToken {}
// where GreenTokenData: Send + Sync
21 fn add_tag(ptr
: ptr
::NonNull
<GreenTokenData
>) -> ptr
::NonNull
<GreenTokenData
> {
23 let ptr
= ((ptr
.as_ptr() as usize) | 1) as *mut GreenTokenData
;
24 ptr
::NonNull
::new_unchecked(ptr
)
28 fn remove_tag(ptr
: ptr
::NonNull
<GreenTokenData
>) -> ptr
::NonNull
<GreenTokenData
> {
30 let ptr
= ((ptr
.as_ptr() as usize) & !1) as *mut GreenTokenData
;
31 ptr
::NonNull
::new_unchecked(ptr
)
35 fn data(&self) -> &GreenTokenData
{
36 unsafe { &*Self::remove_tag(self.ptr).as_ptr() }
39 /// Creates new Token.
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) }
47 /// Kind of this Token.
49 pub fn kind(&self) -> SyntaxKind
{
53 /// Text of this Token.
55 pub fn text(&self) -> &SmolStr
{
59 /// Returns the length of the text covered by this token.
61 pub fn text_len(&self) -> TextSize
{
62 TextSize
::try_from(self.text().len()).unwrap()
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()
73 impl Clone
for GreenToken
{
74 fn clone(&self) -> Self {
75 let ptr
= Self::remove_tag(self.ptr
);
77 let arc
= ManuallyDrop
::new(Arc
::from_raw(ptr
.as_ptr()));
78 Arc
::into_raw(Arc
::clone(&arc
))
80 let ptr
= ptr
::NonNull
::new(ptr
as *mut _
).unwrap();
81 GreenToken { ptr: Self::add_tag(ptr) }
85 impl Eq
for GreenToken {}
86 impl PartialEq
for GreenToken
{
87 fn eq(&self, other
: &Self) -> bool
{
88 self.data() == other
.data()
92 impl hash
::Hash
for GreenToken
{
93 fn hash
<H
>(&self, state
: &mut H
)
97 self.data().hash(state
)
101 impl Drop
for GreenToken
{
104 Arc
::from_raw(Self::remove_tag(self.ptr
).as_ptr());