1use std::{
16 hash::{Hash, Hasher},
17 marker::PhantomData,
18};
19
20use rowan::TextRange;
21
22use crate::{syntax_node::OpenQASM3Language, AstNode, SyntaxNode};
23
24pub type SyntaxNodePtr = rowan::ast::SyntaxNodePtr<OpenQASM3Language>;
26
27#[derive(Debug)]
29pub struct AstPtr<N: AstNode> {
30 raw: SyntaxNodePtr,
31 _ty: PhantomData<fn() -> N>,
32}
33
34impl<N: AstNode> Clone for AstPtr<N> {
35 #[rustversion::before(1.74)]
36 fn clone(&self) -> AstPtr<N> {
37 AstPtr {
38 raw: self.raw,
39 _ty: PhantomData,
40 }
41 }
42 #[rustversion::since(1.74)]
43 fn clone(&self) -> AstPtr<N> {
44 AstPtr {
45 raw: self.raw,
46 _ty: PhantomData,
47 }
48 }
49}
50
51impl<N: AstNode> Eq for AstPtr<N> {}
52
53impl<N: AstNode> PartialEq for AstPtr<N> {
54 fn eq(&self, other: &AstPtr<N>) -> bool {
55 self.raw == other.raw
56 }
57}
58
59impl<N: AstNode> Hash for AstPtr<N> {
60 fn hash<H: Hasher>(&self, state: &mut H) {
61 self.raw.hash(state);
62 }
63}
64
65impl<N: AstNode> AstPtr<N> {
66 pub fn new(node: &N) -> AstPtr<N> {
67 AstPtr {
68 raw: SyntaxNodePtr::new(node.syntax()),
69 _ty: PhantomData,
70 }
71 }
72
73 pub fn to_node(&self, root: &SyntaxNode) -> N {
74 let syntax_node = self.raw.to_node(root);
75 N::cast(syntax_node).unwrap()
76 }
77
78 #[rustversion::since(1.74)]
79 pub fn syntax_node_ptr(&self) -> SyntaxNodePtr {
80 self.raw
81 }
82
83 #[rustversion::before(1.74)]
84 pub fn syntax_node_ptr(&self) -> SyntaxNodePtr {
85 self.raw
86 }
87
88 pub fn text_range(&self) -> TextRange {
89 self.raw.text_range()
90 }
91
92 pub fn cast<U: AstNode>(self) -> Option<AstPtr<U>> {
93 if !U::can_cast(self.raw.kind()) {
94 return None;
95 }
96 Some(AstPtr {
97 raw: self.raw,
98 _ty: PhantomData,
99 })
100 }
101
102 pub fn upcast<M: AstNode>(self) -> AstPtr<M>
103 where
104 N: Into<M>,
105 {
106 AstPtr {
107 raw: self.raw,
108 _ty: PhantomData,
109 }
110 }
111
112 pub fn try_from_raw(raw: SyntaxNodePtr) -> Option<AstPtr<N>> {
114 N::can_cast(raw.kind()).then_some(AstPtr {
115 raw,
116 _ty: PhantomData,
117 })
118 }
119}
120
121impl<N: AstNode> From<AstPtr<N>> for SyntaxNodePtr {
122 fn from(ptr: AstPtr<N>) -> SyntaxNodePtr {
123 ptr.raw
124 }
125}
126
127