1use core::fmt::{Debug, Display, Write as _};
2
3use alloc::boxed::Box;
4use smallvec::SmallVec;
5
6use crate::{Cursor, Parse};
7
8#[derive(Debug, Clone)]
10pub struct UnknownTypeTag(char);
11
12impl core::error::Error for UnknownTypeTag {}
13
14impl Display for UnknownTypeTag {
15 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
16 write!(f, "unknown field type '{}'", self.0)
17 }
18}
19
20#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
22#[allow(missing_docs)]
23pub enum PrimitiveType {
24 Byte,
25 Char,
26 Double,
27 Float,
28 Int,
29 Long,
30 Short,
31 Boolean,
32}
33
34impl PrimitiveType {
35 #[inline]
37 pub const fn key(self) -> char {
38 match self {
39 Self::Byte => 'B',
40 Self::Char => 'C',
41 Self::Double => 'D',
42 Self::Float => 'F',
43 Self::Int => 'I',
44 Self::Long => 'J',
45 Self::Short => 'S',
46 Self::Boolean => 'Z',
47 }
48 }
49}
50
51impl Debug for PrimitiveType {
52 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
53 match self {
54 Self::Byte => write!(f, "byte"),
55 Self::Char => write!(f, "char"),
56 Self::Double => write!(f, "double"),
57 Self::Float => write!(f, "float"),
58 Self::Int => write!(f, "int"),
59 Self::Long => write!(f, "long"),
60 Self::Short => write!(f, "short"),
61 Self::Boolean => write!(f, "boolean"),
62 }
63 }
64}
65
66#[derive(Clone, PartialEq, Eq, Hash)]
70#[allow(missing_docs)] pub enum FieldType<'a> {
72 Primitive(PrimitiveType),
73 Class(&'a str),
74 Array(Box<Self>),
75}
76
77impl Display for FieldType<'_> {
78 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
79 match self {
80 Self::Primitive(ty) => f.write_char(ty.key()),
81 Self::Class(class_name) => write!(f, "L{class_name};"),
82 Self::Array(field_ty) => write!(f, "[{field_ty}"),
83 }
84 }
85}
86
87impl<'a> Parse<'a> for FieldType<'a> {
88 type Error = UnknownTypeTag;
89
90 fn parse_from(cursor: &mut Cursor<'a>) -> Result<Self, Self::Error> {
91 let leading = cursor.get_char();
92 match leading {
93 'B' => Ok(Self::Primitive(PrimitiveType::Byte)),
94 'C' => Ok(Self::Primitive(PrimitiveType::Char)),
95 'D' => Ok(Self::Primitive(PrimitiveType::Double)),
96 'F' => Ok(Self::Primitive(PrimitiveType::Float)),
97 'I' => Ok(Self::Primitive(PrimitiveType::Int)),
98 'J' => Ok(Self::Primitive(PrimitiveType::Long)),
99 'S' => Ok(Self::Primitive(PrimitiveType::Short)),
100 'Z' => Ok(Self::Primitive(PrimitiveType::Boolean)),
101 'L' => cursor
102 .try_advance(|s| s.split_once(';').ok_or(UnknownTypeTag('L')))
103 .map(Self::Class),
104 '[' => Self::parse_from(cursor).map(|t| Self::Array(Box::new(t))),
105 _ => Err(UnknownTypeTag(leading)),
106 }
107 }
108}
109
110impl Debug for FieldType<'_> {
111 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
112 match self {
113 Self::Primitive(ty) => Debug::fmt(ty, f),
114 Self::Class(arg0) => Debug::fmt(arg0, f),
115 Self::Array(arg0) => {
116 Debug::fmt(arg0, f)?;
117 write!(f, "[]")
118 }
119 }
120 }
121}
122
123#[derive(Clone, PartialEq, Eq)]
127#[allow(missing_docs, variant_size_differences)]
128pub enum TypeSignature<'a> {
129 Primitive(PrimitiveType),
130 Class {
131 sig: ClassTypeSignature<'a>,
132 suffix: Option<ClassTypeSignature<'a>>,
133 },
134 Type(&'a str),
135 Array(Box<Self>),
136}
137
138#[derive(Clone, PartialEq, Eq)]
140pub struct ClassTypeSignature<'a> {
141 pub name: &'a str,
143 pub args: SmallVec<[Option<Box<TypeArgument<'a>>>; 1]>,
147}
148
149#[derive(Clone, PartialEq, Eq)]
151pub struct TypeArgument<'a> {
152 pub kind: TypeArgumentKind,
154 pub signature: TypeSignature<'a>,
156}
157
158#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
160#[allow(missing_docs)]
161pub enum TypeArgumentKind {
162 #[default]
163 Exact,
164 Extends,
166 Super,
168}
169
170impl Display for TypeSignature<'_> {
171 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
172 match self {
173 TypeSignature::Primitive(ty) => write!(f, "{}", ty.key()),
174 TypeSignature::Class { sig, suffix } => {
175 write!(f, "L{}", sig)?;
176 if let Some(suffix) = suffix {
177 write!(f, ".{}", suffix)?;
178 }
179 write!(f, ";")?;
180 Ok(())
181 }
182 TypeSignature::Type(ty) => write!(f, "T{};", ty),
183 TypeSignature::Array(ty) => write!(f, "[{}", ty),
184 }
185 }
186}
187
188impl Display for ClassTypeSignature<'_> {
189 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
190 write!(f, "{}", self.name)?;
191 if !self.args.is_empty() {
192 write!(f, "<")?;
193 for arg in &self.args {
194 if let Some(arg) = arg {
195 write!(f, "{}", arg)?;
196 } else {
197 write!(f, "*")?;
198 }
199 }
200 write!(f, ">")?;
201 }
202 Ok(())
203 }
204}
205
206impl Display for TypeArgument<'_> {
207 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
208 match self.kind {
209 TypeArgumentKind::Exact => (),
210 TypeArgumentKind::Extends => write!(f, "+")?,
211 TypeArgumentKind::Super => write!(f, "-")?,
212 }
213 write!(f, "{}", self.signature)?;
214 Ok(())
215 }
216}
217
218impl<'a> Parse<'a> for TypeSignature<'a> {
219 type Error = UnknownTypeTag;
220
221 fn parse_from(cursor: &mut Cursor<'a>) -> Result<Self, Self::Error> {
222 let leading = cursor.get_char();
223 match leading {
224 'B' => Ok(Self::Primitive(PrimitiveType::Byte)),
225 'C' => Ok(Self::Primitive(PrimitiveType::Char)),
226 'D' => Ok(Self::Primitive(PrimitiveType::Double)),
227 'F' => Ok(Self::Primitive(PrimitiveType::Float)),
228 'I' => Ok(Self::Primitive(PrimitiveType::Int)),
229 'J' => Ok(Self::Primitive(PrimitiveType::Long)),
230 'S' => Ok(Self::Primitive(PrimitiveType::Short)),
231 'Z' => Ok(Self::Primitive(PrimitiveType::Boolean)),
232 'L' => {
233 let mut offset0 = if let Some((a, b)) = cursor.0.split_once('<')
234 && !a.contains(['.', ';'])
235 {
236 let mut rem = b;
237 let mut layers = 1usize;
238 while layers > 0 {
239 let pos = rem.find(['<', '>']).expect("unclosed angles");
240 match rem.as_bytes()[pos] {
241 b'<' => layers += 1,
242 b'>' => layers -= 1,
243 _ => unreachable!(),
244 }
245 rem = &rem[pos + 1..];
246 }
247 unsafe { rem.as_ptr().byte_offset_from_unsigned(cursor.0.as_ptr()) }
248 } else {
249 0
250 };
251 offset0 += cursor.0[offset0..]
252 .find([';', '.'])
253 .ok_or(UnknownTypeTag('L'))?;
254 let major = cursor.advance(|s| s.split_at(offset0));
255 let suffix = match cursor.get_char() {
256 '.' => {
257 let mut offset1 = if let Some((a, b)) = cursor.0.split_once('<')
258 && !a.contains(';')
259 {
260 let mut rem = b;
261 let mut layers = 1usize;
262 while layers > 0 {
263 let pos = rem.find(['<', '>']).expect("unclosed angles");
264 match rem.as_bytes()[pos] {
265 b'<' => layers += 1,
266 b'>' => layers -= 1,
267 _ => unreachable!(),
268 }
269 rem = &rem[pos + 1..];
270 }
271 unsafe { rem.as_ptr().byte_offset_from_unsigned(cursor.0.as_ptr()) }
272 } else {
273 0
274 };
275 offset1 += cursor.0[offset1..].find(';').ok_or(UnknownTypeTag('L'))?;
276 let suffix = cursor.advance(|s| s.split_at(offset1));
277 cursor.get_char();
278 Some(suffix)
279 }
280 ';' => None,
281 _ => unreachable!(),
282 };
283
284 Ok(Self::Class {
285 sig: ClassTypeSignature::parse_from(&mut Cursor(major))?,
286 suffix: suffix
287 .map(|src| ClassTypeSignature::parse_from(&mut Cursor(src)))
288 .transpose()?,
289 })
290 }
291 'T' => cursor
292 .try_advance(|s| s.split_once(';').ok_or(UnknownTypeTag('T')))
293 .map(Self::Type),
294 '[' => Self::parse_from(cursor).map(|t| Self::Array(Box::new(t))),
295 _ => Err(UnknownTypeTag(leading)),
296 }
297 }
298}
299
300impl<'a> Parse<'a> for ClassTypeSignature<'a> {
301 type Error = UnknownTypeTag;
302
303 fn parse_from(input: &mut Cursor<'a>) -> Result<Self, UnknownTypeTag> {
304 let src = input.get();
305 input.0 = "";
306 let (name, rem) = src.split_once('<').unzip();
307 let name = name.unwrap_or(src);
308 let mut args = SmallVec::new();
309 if let Some(rem) = rem {
310 let mut cursor = Cursor(rem.strip_suffix('>').unwrap_or(rem));
311 while !cursor.0.is_empty() {
312 let mut c1 = Cursor(cursor.0);
313 if c1.get_char() == '*' {
314 args.push(None);
315 cursor = c1;
316 } else {
317 args.push(Some(Box::new(TypeArgument::parse_from(&mut cursor)?)));
318 }
319 }
320 }
321 Ok(Self { name, args })
322 }
323}
324
325impl<'a> Parse<'a> for TypeArgument<'a> {
326 type Error = UnknownTypeTag;
327
328 fn parse_from(src: &mut Cursor<'a>) -> Result<Self, UnknownTypeTag> {
329 let kind = match src.0.as_bytes().first() {
330 Some(b'+') => {
331 src.get_char();
332 TypeArgumentKind::Extends
333 }
334 Some(b'_') => {
335 src.get_char();
336 TypeArgumentKind::Super
337 }
338 _ => TypeArgumentKind::Exact,
339 };
340 Ok(Self {
341 kind,
342 signature: TypeSignature::parse_from(src)?,
343 })
344 }
345}
346
347impl Debug for TypeSignature<'_> {
348 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
349 match self {
350 TypeSignature::Primitive(ty) => write!(f, "{ty:?}"),
351 TypeSignature::Class { sig, suffix } => {
352 write!(f, "{:?}", sig)?;
353 if let Some(suffix) = suffix {
354 write!(f, ".{:?}", suffix)?;
355 }
356 Ok(())
357 }
358 TypeSignature::Type(ty) => write!(f, "{}", ty),
359 TypeSignature::Array(ty) => write!(f, "{:?}[]", ty),
360 }
361 }
362}
363
364impl Debug for ClassTypeSignature<'_> {
365 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
366 write!(f, "{}", self.name)?;
367 if !self.args.is_empty() {
368 write!(f, "<")?;
369 let mut iter = self.args.iter().peekable();
370 while let Some(val) = iter.next() {
371 write!(f, "{:?}", val)?;
372 if iter.peek().is_some() {
373 write!(f, ", ")?;
374 }
375 }
376 write!(f, ">")?;
377 }
378 Ok(())
379 }
380}
381
382impl Debug for TypeArgument<'_> {
383 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
384 match self.kind {
385 TypeArgumentKind::Exact => write!(f, "{:?}", self.signature),
386 TypeArgumentKind::Extends => write!(f, "? extends {:?}", self.signature),
387 TypeArgumentKind::Super => write!(f, "? super {:?}", self.signature),
388 }
389 }
390}
391
392#[cfg(test)]
393mod tests {
394 use alloc::boxed::Box;
395 use smallvec::{SmallVec, smallvec};
396
397 use crate::{
398 ClassTypeSignature, FieldType, PrimitiveType, TypeArgument, TypeArgumentKind,
399 TypeSignature, parse, validate_rw,
400 };
401
402 #[test]
403 fn primitives() {
404 macro_rules! primitives {
405 ($($v:ident,$l:expr),*$(,)?) => {
406 $(
407 assert_eq!(parse::<'_, FieldType<'_>>($l).unwrap(), FieldType::Primitive(PrimitiveType::$v));
408 validate_rw::<'_, FieldType<'_>>($l);
409
410 assert_eq!(parse::<'_, TypeSignature<'_>>($l).unwrap(), TypeSignature::Primitive(PrimitiveType::$v));
411 validate_rw::<'_, TypeSignature<'_>>($l);
412 )*
413 };
414 }
415
416 primitives! {
417 Byte, "B",
418 Char, "C",
419 Double, "D",
420 Float, "F",
421 Int, "I",
422 Long, "J",
423 Short, "S",
424 Boolean, "Z",
425 }
426 }
427
428 #[test]
429 fn class() {
430 assert_eq!(
431 parse::<'_, FieldType<'_>>("Ljava/lang/Object;").unwrap(),
432 FieldType::Class("java/lang/Object")
433 );
434 validate_rw::<'_, FieldType<'_>>("Ljava/lang/Object;");
435
436 assert_eq!(
437 parse::<'_, TypeSignature<'_>>("Ljava/lang/Object;").unwrap(),
438 TypeSignature::Class {
439 sig: ClassTypeSignature {
440 name: "java/lang/Object",
441 args: SmallVec::new()
442 },
443 suffix: None
444 }
445 );
446 validate_rw::<'_, TypeSignature<'_>>("Ljava/lang/Object;");
447 }
448
449 #[test]
450 fn array_primitive() {
451 assert_eq!(
452 parse::<'_, FieldType<'_>>("[I").unwrap(),
453 FieldType::Array(Box::new(FieldType::Primitive(PrimitiveType::Int)))
454 );
455 validate_rw::<'_, FieldType<'_>>("[I");
456
457 assert_eq!(
458 parse::<'_, TypeSignature<'_>>("[I").unwrap(),
459 TypeSignature::Array(Box::new(TypeSignature::Primitive(PrimitiveType::Int)))
460 );
461 validate_rw::<'_, TypeSignature<'_>>("[I");
462 }
463
464 #[test]
465 fn array_primitive_2d() {
466 assert_eq!(
467 parse::<'_, FieldType<'_>>("[[I").unwrap(),
468 FieldType::Array(Box::new(FieldType::Array(Box::new(FieldType::Primitive(
469 PrimitiveType::Int
470 )))))
471 );
472 validate_rw::<'_, FieldType<'_>>("[[I");
473 assert_eq!(
474 parse::<'_, TypeSignature<'_>>("[[I").unwrap(),
475 TypeSignature::Array(Box::new(TypeSignature::Array(Box::new(
476 TypeSignature::Primitive(PrimitiveType::Int)
477 ))))
478 );
479 validate_rw::<'_, TypeSignature<'_>>("[[I");
480 }
481
482 #[test]
483 fn array_class() {
484 assert_eq!(
485 parse::<'_, FieldType<'_>>("[Ljava/lang/Object;").unwrap(),
486 FieldType::Array(Box::new(FieldType::Class("java/lang/Object")))
487 );
488 validate_rw::<'_, FieldType<'_>>("[Ljava/lang/Object;");
489 validate_rw::<'_, TypeSignature<'_>>("[Ljava/lang/Object;");
490 }
491
492 #[test]
493 fn array_class_2d() {
494 assert_eq!(
495 parse::<'_, FieldType<'_>>("[[Ljava/lang/Object;").unwrap(),
496 FieldType::Array(Box::new(FieldType::Array(Box::new(FieldType::Class(
497 "java/lang/Object"
498 )))))
499 );
500 validate_rw::<'_, FieldType<'_>>("[[Ljava/lang/Object;");
501 validate_rw::<'_, TypeSignature<'_>>("[[Ljava/lang/Object;");
502 }
503
504 #[test]
505 fn class_generics() {
506 assert_eq!(
507 parse::<'_, TypeSignature<'_>>(
508 "Ljava/util/Map<Ljava/lang/String;+Ljava/lang/Integer;>;"
509 )
510 .unwrap(),
511 TypeSignature::Class {
512 sig: ClassTypeSignature {
513 name: "java/util/Map",
514 args: smallvec![
515 Some(Box::new(TypeArgument {
516 kind: TypeArgumentKind::Exact,
517 signature: TypeSignature::Class {
518 sig: ClassTypeSignature {
519 name: "java/lang/String",
520 args: SmallVec::new(),
521 },
522 suffix: None
523 }
524 })),
525 Some(Box::new(TypeArgument {
526 kind: TypeArgumentKind::Extends,
527 signature: TypeSignature::Class {
528 sig: ClassTypeSignature {
529 name: "java/lang/Integer",
530 args: SmallVec::new(),
531 },
532 suffix: None
533 }
534 })),
535 ]
536 },
537 suffix: None
538 }
539 );
540 validate_rw::<'_, TypeSignature<'_>>(
541 "Ljava/util/Map<Ljava/lang/String;Ljava/lang/Integer;>;",
542 );
543 }
544
545 #[test]
546 fn class_generics_any() {
547 assert_eq!(
548 parse::<'_, TypeSignature<'_>>("Ljava/util/concurrent/Future<*>;").unwrap(),
549 TypeSignature::Class {
550 sig: ClassTypeSignature {
551 name: "java/util/concurrent/Future",
552 args: smallvec![None]
553 },
554 suffix: None
555 }
556 );
557 validate_rw::<'_, TypeSignature<'_>>("Ljava/util/concurrent/Future<*>;");
558 }
559
560 #[test]
561 fn class_generics_suffix() {
562 assert_eq!(
563 parse::<'_, TypeSignature<'_>>("LOuter<TT;>.Inner<TU;>;").unwrap(),
564 TypeSignature::Class {
565 sig: ClassTypeSignature {
566 name: "Outer",
567 args: smallvec![Some(Box::new(TypeArgument {
568 kind: TypeArgumentKind::Exact,
569 signature: TypeSignature::Type("T"),
570 }))]
571 },
572 suffix: Some(ClassTypeSignature {
573 name: "Inner",
574 args: smallvec![Some(Box::new(TypeArgument {
575 kind: TypeArgumentKind::Exact,
576 signature: TypeSignature::Type("U"),
577 }))]
578 },)
579 }
580 );
581 validate_rw::<'_, TypeSignature<'_>>("LOuter<TT;>.Inner<TU;>;");
582 }
583
584 #[test]
585 fn type_sig() {
586 assert_eq!(
587 parse::<'_, TypeSignature<'_>>("TT;").unwrap(),
588 TypeSignature::Type("T")
589 );
590 validate_rw::<'_, TypeSignature<'_>>("TT;");
591 }
592}