1use std::marker::PhantomData;
7use std::ptr::NonNull;
8
9use ruby_prism_sys::{pm_constant_id_list_t, pm_constant_id_t, pm_integer_t, pm_node_list, pm_node_t, pm_parser_t};
10
11use crate::Node;
14
15pub struct NodeListIter<'pr> {
21 pub(crate) parser: *const pm_parser_t,
22 pub(crate) pointer: NonNull<pm_node_list>,
23 pub(crate) index: usize,
24 pub(crate) marker: PhantomData<&'pr mut pm_node_list>,
25}
26
27impl<'pr> Iterator for NodeListIter<'pr> {
28 type Item = Node<'pr>;
29
30 fn next(&mut self) -> Option<Self::Item> {
31 if self.index >= unsafe { self.pointer.as_ref().size } {
32 None
33 } else {
34 let node: *mut pm_node_t = unsafe { *(self.pointer.as_ref().nodes.add(self.index)) };
35 self.index += 1;
36 Some(Node::new(self.parser, node))
37 }
38 }
39}
40
41pub struct NodeList<'pr> {
43 pub(crate) parser: *const pm_parser_t,
44 pub(crate) pointer: NonNull<pm_node_list>,
45 pub(crate) marker: PhantomData<&'pr mut pm_node_list>,
46}
47
48impl<'pr> NodeList<'pr> {
49 unsafe fn at(&self, index: usize) -> Node<'pr> {
50 let node: *mut pm_node_t = *(self.pointer.as_ref().nodes.add(index));
51 Node::new(self.parser, node)
52 }
53
54 #[must_use]
56 pub const fn iter(&self) -> NodeListIter<'pr> {
57 NodeListIter {
58 parser: self.parser,
59 pointer: self.pointer,
60 index: 0,
61 marker: PhantomData,
62 }
63 }
64
65 #[must_use]
67 pub const fn len(&self) -> usize {
68 unsafe { self.pointer.as_ref().size }
69 }
70
71 #[must_use]
73 pub const fn is_empty(&self) -> bool {
74 self.len() == 0
75 }
76
77 #[must_use]
79 pub fn first(&self) -> Option<Node<'pr>> {
80 if self.is_empty() {
81 None
82 } else {
83 Some(unsafe { self.at(0) })
84 }
85 }
86
87 #[must_use]
89 pub fn last(&self) -> Option<Node<'pr>> {
90 if self.is_empty() {
91 None
92 } else {
93 Some(unsafe { self.at(self.len() - 1) })
94 }
95 }
96}
97
98impl<'pr> IntoIterator for &NodeList<'pr> {
99 type Item = Node<'pr>;
100 type IntoIter = NodeListIter<'pr>;
101 fn into_iter(self) -> Self::IntoIter {
102 self.iter()
103 }
104}
105
106impl std::fmt::Debug for NodeList<'_> {
107 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108 write!(f, "{:?}", self.iter().collect::<Vec<_>>())
109 }
110}
111
112pub struct ConstantId<'pr> {
118 pub(crate) parser: *const pm_parser_t,
119 pub(crate) id: pm_constant_id_t,
120 pub(crate) marker: PhantomData<&'pr mut pm_constant_id_t>,
121}
122
123impl<'pr> ConstantId<'pr> {
124 pub(crate) const fn new(parser: *const pm_parser_t, id: pm_constant_id_t) -> Self {
125 ConstantId { parser, id, marker: PhantomData }
126 }
127
128 #[must_use]
134 pub fn as_slice(&self) -> &'pr [u8] {
135 unsafe {
136 let constant = ruby_prism_sys::pm_parser_constant(self.parser, self.id);
137 let start = ruby_prism_sys::pm_constant_start(constant);
138 let length = ruby_prism_sys::pm_constant_length(constant);
139 std::slice::from_raw_parts(start, length)
140 }
141 }
142}
143
144impl std::fmt::Debug for ConstantId<'_> {
145 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
146 write!(f, "{:?}", self.id)
147 }
148}
149
150pub struct ConstantListIter<'pr> {
152 pub(crate) parser: *const pm_parser_t,
153 pub(crate) pointer: NonNull<pm_constant_id_list_t>,
154 pub(crate) index: usize,
155 pub(crate) marker: PhantomData<&'pr mut pm_constant_id_list_t>,
156}
157
158impl<'pr> Iterator for ConstantListIter<'pr> {
159 type Item = ConstantId<'pr>;
160
161 fn next(&mut self) -> Option<Self::Item> {
162 if self.index >= unsafe { self.pointer.as_ref().size } {
163 None
164 } else {
165 let constant_id: pm_constant_id_t = unsafe { *(self.pointer.as_ref().ids.add(self.index)) };
166 self.index += 1;
167 Some(ConstantId::new(self.parser, constant_id))
168 }
169 }
170}
171
172pub struct ConstantList<'pr> {
174 pub(crate) parser: *const pm_parser_t,
176
177 pub(crate) pointer: NonNull<pm_constant_id_list_t>,
179
180 pub(crate) marker: PhantomData<&'pr mut pm_constant_id_list_t>,
182}
183
184impl<'pr> ConstantList<'pr> {
185 const unsafe fn at(&self, index: usize) -> ConstantId<'pr> {
186 let constant_id: pm_constant_id_t = *(self.pointer.as_ref().ids.add(index));
187 ConstantId::new(self.parser, constant_id)
188 }
189
190 #[must_use]
192 pub const fn iter(&self) -> ConstantListIter<'pr> {
193 ConstantListIter {
194 parser: self.parser,
195 pointer: self.pointer,
196 index: 0,
197 marker: PhantomData,
198 }
199 }
200
201 #[must_use]
203 pub const fn len(&self) -> usize {
204 unsafe { self.pointer.as_ref().size }
205 }
206
207 #[must_use]
209 pub const fn is_empty(&self) -> bool {
210 self.len() == 0
211 }
212
213 #[must_use]
215 pub const fn first(&self) -> Option<ConstantId<'pr>> {
216 if self.is_empty() {
217 None
218 } else {
219 Some(unsafe { self.at(0) })
220 }
221 }
222
223 #[must_use]
225 pub const fn last(&self) -> Option<ConstantId<'pr>> {
226 if self.is_empty() {
227 None
228 } else {
229 Some(unsafe { self.at(self.len() - 1) })
230 }
231 }
232}
233
234impl<'pr> IntoIterator for &ConstantList<'pr> {
235 type Item = ConstantId<'pr>;
236 type IntoIter = ConstantListIter<'pr>;
237 fn into_iter(self) -> Self::IntoIter {
238 self.iter()
239 }
240}
241
242impl std::fmt::Debug for ConstantList<'_> {
243 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
244 write!(f, "{:?}", self.iter().collect::<Vec<_>>())
245 }
246}
247
248pub struct Integer<'pr> {
254 pub(crate) pointer: *const pm_integer_t,
256
257 pub(crate) marker: PhantomData<&'pr mut pm_constant_id_t>,
259}
260
261impl Integer<'_> {
262 pub(crate) const fn new(pointer: *const pm_integer_t) -> Self {
263 Integer { pointer, marker: PhantomData }
264 }
265
266 #[must_use]
269 pub const fn to_u32_digits(&self) -> (bool, &[u32]) {
270 let negative = unsafe { (*self.pointer).negative };
271 let length = unsafe { (*self.pointer).length };
272 let values = unsafe { (*self.pointer).values };
273
274 if values.is_null() {
275 let value_ptr = unsafe { std::ptr::addr_of!((*self.pointer).value) };
276 let slice = unsafe { std::slice::from_raw_parts(value_ptr, 1) };
277 (negative, slice)
278 } else {
279 let slice = unsafe { std::slice::from_raw_parts(values, length) };
280 (negative, slice)
281 }
282 }
283}
284
285impl std::fmt::Debug for Integer<'_> {
286 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
287 write!(f, "{:?}", self.pointer)
288 }
289}
290
291impl TryInto<i32> for Integer<'_> {
292 type Error = ();
293
294 fn try_into(self) -> Result<i32, Self::Error> {
295 let negative = unsafe { (*self.pointer).negative };
296 let length = unsafe { (*self.pointer).length };
297
298 if length == 0 {
299 i32::try_from(unsafe { (*self.pointer).value }).map_or(Err(()), |value| if negative { Ok(-value) } else { Ok(value) })
300 } else {
301 Err(())
302 }
303 }
304}