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: NonNull<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: NonNull<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: NonNull<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: NonNull<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 pool = &(*self.parser.as_ptr()).constant_pool;
137 let constant = &(*pool.constants.add((self.id - 1).try_into().unwrap()));
138 std::slice::from_raw_parts(constant.start, constant.length)
139 }
140 }
141}
142
143impl std::fmt::Debug for ConstantId<'_> {
144 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
145 write!(f, "{:?}", self.id)
146 }
147}
148
149pub struct ConstantListIter<'pr> {
151 pub(crate) parser: NonNull<pm_parser_t>,
152 pub(crate) pointer: NonNull<pm_constant_id_list_t>,
153 pub(crate) index: usize,
154 pub(crate) marker: PhantomData<&'pr mut pm_constant_id_list_t>,
155}
156
157impl<'pr> Iterator for ConstantListIter<'pr> {
158 type Item = ConstantId<'pr>;
159
160 fn next(&mut self) -> Option<Self::Item> {
161 if self.index >= unsafe { self.pointer.as_ref().size } {
162 None
163 } else {
164 let constant_id: pm_constant_id_t = unsafe { *(self.pointer.as_ref().ids.add(self.index)) };
165 self.index += 1;
166 Some(ConstantId::new(self.parser, constant_id))
167 }
168 }
169}
170
171pub struct ConstantList<'pr> {
173 pub(crate) parser: NonNull<pm_parser_t>,
175
176 pub(crate) pointer: NonNull<pm_constant_id_list_t>,
178
179 pub(crate) marker: PhantomData<&'pr mut pm_constant_id_list_t>,
181}
182
183impl<'pr> ConstantList<'pr> {
184 const unsafe fn at(&self, index: usize) -> ConstantId<'pr> {
185 let constant_id: pm_constant_id_t = *(self.pointer.as_ref().ids.add(index));
186 ConstantId::new(self.parser, constant_id)
187 }
188
189 #[must_use]
191 pub const fn iter(&self) -> ConstantListIter<'pr> {
192 ConstantListIter {
193 parser: self.parser,
194 pointer: self.pointer,
195 index: 0,
196 marker: PhantomData,
197 }
198 }
199
200 #[must_use]
202 pub const fn len(&self) -> usize {
203 unsafe { self.pointer.as_ref().size }
204 }
205
206 #[must_use]
208 pub const fn is_empty(&self) -> bool {
209 self.len() == 0
210 }
211
212 #[must_use]
214 pub const fn first(&self) -> Option<ConstantId<'pr>> {
215 if self.is_empty() {
216 None
217 } else {
218 Some(unsafe { self.at(0) })
219 }
220 }
221
222 #[must_use]
224 pub const fn last(&self) -> Option<ConstantId<'pr>> {
225 if self.is_empty() {
226 None
227 } else {
228 Some(unsafe { self.at(self.len() - 1) })
229 }
230 }
231}
232
233impl<'pr> IntoIterator for &ConstantList<'pr> {
234 type Item = ConstantId<'pr>;
235 type IntoIter = ConstantListIter<'pr>;
236 fn into_iter(self) -> Self::IntoIter {
237 self.iter()
238 }
239}
240
241impl std::fmt::Debug for ConstantList<'_> {
242 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
243 write!(f, "{:?}", self.iter().collect::<Vec<_>>())
244 }
245}
246
247pub struct Integer<'pr> {
253 pub(crate) pointer: *const pm_integer_t,
255
256 pub(crate) marker: PhantomData<&'pr mut pm_constant_id_t>,
258}
259
260impl Integer<'_> {
261 pub(crate) const fn new(pointer: *const pm_integer_t) -> Self {
262 Integer { pointer, marker: PhantomData }
263 }
264
265 #[must_use]
268 pub const fn to_u32_digits(&self) -> (bool, &[u32]) {
269 let negative = unsafe { (*self.pointer).negative };
270 let length = unsafe { (*self.pointer).length };
271 let values = unsafe { (*self.pointer).values };
272
273 if values.is_null() {
274 let value_ptr = unsafe { std::ptr::addr_of!((*self.pointer).value) };
275 let slice = unsafe { std::slice::from_raw_parts(value_ptr, 1) };
276 (negative, slice)
277 } else {
278 let slice = unsafe { std::slice::from_raw_parts(values, length) };
279 (negative, slice)
280 }
281 }
282}
283
284impl std::fmt::Debug for Integer<'_> {
285 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
286 write!(f, "{:?}", self.pointer)
287 }
288}
289
290impl TryInto<i32> for Integer<'_> {
291 type Error = ();
292
293 fn try_into(self) -> Result<i32, Self::Error> {
294 let negative = unsafe { (*self.pointer).negative };
295 let length = unsafe { (*self.pointer).length };
296
297 if length == 0 {
298 i32::try_from(unsafe { (*self.pointer).value }).map_or(Err(()), |value| if negative { Ok(-value) } else { Ok(value) })
299 } else {
300 Err(())
301 }
302 }
303}