ruby_prism/parse_result/
comments.rs1use std::marker::PhantomData;
4use std::ptr::NonNull;
5
6use ruby_prism_sys::{pm_comment_t, pm_comment_type_t, pm_magic_comment_t, pm_parser_t};
7
8use super::Location;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum CommentType {
13 InlineComment,
15 EmbDocComment,
17}
18
19#[derive(Debug)]
21pub struct Comment<'pr> {
22 content: NonNull<pm_comment_t>,
23 parser: NonNull<pm_parser_t>,
24 marker: PhantomData<&'pr pm_comment_t>,
25}
26
27impl<'pr> Comment<'pr> {
28 #[must_use]
33 pub fn text(&self) -> &[u8] {
34 self.location().as_slice()
35 }
36
37 #[must_use]
39 pub fn type_(&self) -> CommentType {
40 let type_ = unsafe { self.content.as_ref().type_ };
41 if type_ == pm_comment_type_t::PM_COMMENT_EMBDOC {
42 CommentType::EmbDocComment
43 } else {
44 CommentType::InlineComment
45 }
46 }
47
48 #[must_use]
50 pub const fn location(&self) -> Location<'pr> {
51 Location::new(self.parser, unsafe { &self.content.as_ref().location })
52 }
53}
54
55pub struct Comments<'pr> {
58 comment: *mut pm_comment_t,
59 parser: NonNull<pm_parser_t>,
60 marker: PhantomData<&'pr pm_comment_t>,
61}
62
63impl Comments<'_> {
64 pub(crate) const fn new(comment: *mut pm_comment_t, parser: NonNull<pm_parser_t>) -> Self {
65 Comments { comment, parser, marker: PhantomData }
66 }
67}
68
69impl<'pr> Iterator for Comments<'pr> {
70 type Item = Comment<'pr>;
71
72 fn next(&mut self) -> Option<Self::Item> {
73 if let Some(comment) = NonNull::new(self.comment) {
74 let current = Comment {
75 content: comment,
76 parser: self.parser,
77 marker: PhantomData,
78 };
79 self.comment = unsafe { comment.as_ref().node.next.cast::<pm_comment_t>() };
80 Some(current)
81 } else {
82 None
83 }
84 }
85}
86
87#[derive(Debug)]
89pub struct MagicComment<'pr> {
90 parser: NonNull<pm_parser_t>,
91 comment: NonNull<pm_magic_comment_t>,
92 marker: PhantomData<&'pr pm_magic_comment_t>,
93}
94
95impl MagicComment<'_> {
96 #[must_use]
98 pub const fn key(&self) -> &[u8] {
99 unsafe {
100 let start = self.parser.as_ref().start.add(self.comment.as_ref().key.start as usize);
101 let len = self.comment.as_ref().key.length as usize;
102 std::slice::from_raw_parts(start, len)
103 }
104 }
105
106 #[must_use]
108 pub const fn value(&self) -> &[u8] {
109 unsafe {
110 let start = self.parser.as_ref().start.add(self.comment.as_ref().value.start as usize);
111 let len = self.comment.as_ref().value.length as usize;
112 std::slice::from_raw_parts(start, len)
113 }
114 }
115}
116
117pub struct MagicComments<'pr> {
120 parser: NonNull<pm_parser_t>,
121 comment: *mut pm_magic_comment_t,
122 marker: PhantomData<&'pr pm_magic_comment_t>,
123}
124
125impl MagicComments<'_> {
126 pub(crate) const fn new(parser: NonNull<pm_parser_t>, comment: *mut pm_magic_comment_t) -> Self {
127 MagicComments { parser, comment, marker: PhantomData }
128 }
129}
130
131impl<'pr> Iterator for MagicComments<'pr> {
132 type Item = MagicComment<'pr>;
133
134 fn next(&mut self) -> Option<Self::Item> {
135 if let Some(comment) = NonNull::new(self.comment) {
136 let current = MagicComment { parser: self.parser, comment, marker: PhantomData };
137 self.comment = unsafe { comment.as_ref().node.next.cast::<pm_magic_comment_t>() };
138 Some(current)
139 } else {
140 None
141 }
142 }
143}