1#![no_std]
30
31extern crate alloc;
32
33mod class;
34mod method;
35mod ty;
36
37use core::{convert::Infallible, fmt::Debug};
38
39pub use class::*;
40pub use method::*;
41pub use ty::*;
42
43pub type FieldSignature<'a> = TypeSignature<'a>;
45
46pub trait Parse<'s>: Sized {
48 type Error;
50
51 #[allow(clippy::missing_errors_doc)]
53 fn parse_from(cursor: &mut Cursor<'s>) -> Result<Self, Self::Error>;
54}
55
56#[non_exhaustive]
58#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
59pub enum ReprForm {
60 JLS,
62 Internal,
67}
68
69impl ReprForm {
70 #[inline]
71 const fn package_separator(&self) -> char {
72 match self {
73 Self::JLS => '.',
74 Self::Internal => '/',
75 }
76 }
77}
78
79#[derive(Debug, Clone)]
81pub struct Cursor<'a>(&'a str);
82
83impl<'a> Cursor<'a> {
84 #[inline]
86 pub const fn new(s: &'a str) -> Self {
87 Self(s)
88 }
89
90 pub fn get_char(&mut self) -> char {
96 let c = self.0.chars().next().expect("end of file");
97 self.advance_by(c.len_utf8());
98 c
99 }
100
101 #[inline]
103 #[allow(clippy::missing_panics_doc)] pub fn advance<F, U>(&mut self, f: F) -> U
105 where
106 F: FnOnce(&'a str) -> (U, &'a str),
107 {
108 self.try_advance(|s| Result::<_, Infallible>::Ok(f(s)))
109 .unwrap()
110 }
111
112 #[inline]
118 pub fn try_advance<F, U, Err>(&mut self, f: F) -> Result<U, Err>
119 where
120 F: FnOnce(&'a str) -> Result<(U, &'a str), Err>,
121 {
122 let (ret, leftover) = f(self.0)?;
123 self.0 = leftover;
124 Ok(ret)
125 }
126
127 #[inline]
129 pub const fn get(&self) -> &'a str {
130 self.0
131 }
132
133 #[inline]
135 pub const fn set(&mut self, s: &'a str) {
136 self.0 = s;
137 }
138
139 #[inline]
145 pub fn advance_by(&mut self, n: usize) {
146 self.advance(|s| ((), &s[n..]))
147 }
148
149 #[inline]
151 pub fn clear(&mut self) {
152 self.0 = "";
153 }
154}
155
156fn strip_digits_prefix(s: &str) -> (Option<u32>, &str) {
157 let mut chars = s.char_indices();
158 let (digits, last_index) = chars
159 .by_ref()
160 .map_while(|(index, c)| c.to_digit(10).map(|d| (index, d)))
161 .fold((0, None), |(n, _), (ci, d)| (n * 10 + d, Some(ci)));
162 let leftover = last_index.map_or(s, |i| &s[i + 1..]);
163 (last_index.map(|_| digits), leftover)
164}
165
166fn angle_safe_offset(src: &str, sep: &[char]) -> usize {
167 if let Some((a, b)) = src.split_once('<')
168 && !a.contains(sep)
169 {
170 let mut rem = b;
171 let mut layers = 1usize;
172 while layers > 0 {
173 let Some(pos) = rem.find(['<', '>']) else {
174 return 0;
175 };
176 match rem.as_bytes()[pos] {
177 b'<' => layers += 1,
178 b'>' => layers -= 1,
179 _ => unreachable!(),
180 }
181 rem = &rem[pos + 1..];
182 }
183 unsafe { rem.as_ptr().byte_offset_from_unsigned(src.as_ptr()) }
184 } else {
185 0
186 }
187}
188
189fn angle_safe_split<'a>(src: &'a str, sep: &[char]) -> Option<(&'a str, &'a str)> {
193 let offset = angle_safe_offset(src, sep);
194 Some(src.split_at(offset + src[offset..].find(sep)?))
195}
196
197fn angle_safe_rsplit<'a>(src: &'a str, sep: &[char]) -> Option<(&'a str, &'a str)> {
201 let offset = angle_safe_offset(src, sep);
202 Some(src.split_at(offset + src[offset..].find(sep)? + 1))
203}
204
205#[allow(clippy::missing_errors_doc)]
207#[inline]
208pub fn parse<'a, T>(value: &'a str) -> Result<T, T::Error>
209where
210 T: Parse<'a>,
211{
212 T::parse_from(&mut Cursor(value))
213}
214
215#[cfg(test)]
216fn validate_rw<'a, T>(value: &'a str)
217where
218 T: Parse<'a> + core::fmt::Display,
219 T::Error: Debug,
220{
221 use core::marker::PhantomData;
222
223 use alloc::string::String;
224
225 struct ClearValidator<T>(String, PhantomData<T>);
226
227 impl<'a, T> Parse<'a> for ClearValidator<T>
228 where
229 T: Parse<'a> + core::fmt::Display,
230 {
231 type Error = T::Error;
232
233 fn parse_from(cursor: &mut Cursor<'a>) -> Result<Self, Self::Error> {
234 use alloc::string::ToString as _;
235
236 let val = T::parse_from(cursor)?;
237 assert_eq!(cursor.get(), "", "non-empty string buf left");
238 Ok(Self(val.to_string(), PhantomData))
239 }
240 }
241
242 assert_eq!(
243 parse::<'a, ClearValidator<T>>(value).map(|o| o.0).unwrap(),
244 value
245 );
246}