1pub const MAX_ANNOTATION_NESTING: usize = 256;
5
6#[derive(Clone, Copy, Debug, Eq, PartialEq)]
8pub struct AttributeOrigin {
9 pub start: usize,
11 pub end: usize,
13}
14fn annotation_origin(start: usize, reader: &ByteReader<'_>) -> AttributeOrigin {
15 AttributeOrigin {
16 start,
17 end: reader.offset(),
18 }
19}
20
21#[derive(Clone, Debug, Eq, PartialEq)]
23pub struct AnnotationElement {
24 pub name_index: u16,
26 pub value: ElementValue,
28 pub origin: AttributeOrigin,
30}
31
32#[derive(Clone, Debug, Eq, PartialEq)]
34pub struct Annotation {
35 pub type_index: u16,
37 pub elements: Vec<AnnotationElement>,
39 pub origin: AttributeOrigin,
41}
42
43#[derive(Clone, Debug, Eq, PartialEq)]
45pub enum ElementValue {
46 Constant {
48 tag: u8,
50 constant_index: u16,
52 origin: AttributeOrigin,
54 },
55 Enum {
57 type_name_index: u16,
59 constant_name_index: u16,
61 origin: AttributeOrigin,
63 },
64 Class {
66 class_info_index: u16,
68 origin: AttributeOrigin,
70 },
71 Annotation {
73 annotation: Box<Annotation>,
75 origin: AttributeOrigin,
77 },
78 Array {
80 values: Vec<ElementValue>,
82 origin: AttributeOrigin,
84 },
85}
86
87impl ElementValue {
88 pub fn origin(&self) -> AttributeOrigin {
90 match self {
91 Self::Constant { origin, .. }
92 | Self::Enum { origin, .. }
93 | Self::Class { origin, .. }
94 | Self::Annotation { origin, .. }
95 | Self::Array { origin, .. } => *origin,
96 }
97 }
98}
99
100#[derive(Clone, Debug, Eq, PartialEq)]
102pub struct AnnotationsAttribute {
103 pub annotations: Vec<Annotation>,
105}
106
107impl AnnotationsAttribute {
108 pub fn decode(
110 reader: &mut ByteReader<'_>,
111 nesting_budget: usize,
112 ) -> Result<Self, AttributeError> {
113 let annotations = decode_annotations(reader, nesting_budget)?;
114 finish(reader)?;
115 Ok(Self { annotations })
116 }
117
118 pub fn encode(&self, budget: usize) -> Result<Vec<u8>, AttributeError> {
120 let mut out = ByteWriter::new(budget);
121 encode_annotations(&self.annotations, &mut out)?;
122 Ok(out.into_bytes())
123 }
124}
125
126#[derive(Clone, Debug, Eq, PartialEq)]
129pub struct ParameterAnnotationsAttribute {
130 pub parameters: Vec<Vec<Annotation>>,
132}
133
134impl ParameterAnnotationsAttribute {
135 pub fn decode(
137 reader: &mut ByteReader<'_>,
138 nesting_budget: usize,
139 ) -> Result<Self, AttributeError> {
140 let count = usize::from(reader.read_u1()?);
141 reader.preflight_allocation(count)?;
142 let mut parameters = Vec::with_capacity(count);
143 for _ in 0..count {
144 parameters.push(decode_annotations(reader, nesting_budget)?);
145 }
146 finish(reader)?;
147 Ok(Self { parameters })
148 }
149
150 pub fn encode(&self, budget: usize) -> Result<Vec<u8>, AttributeError> {
152 let mut out = ByteWriter::new(budget);
153 out.write_u1(u8::try_from(self.parameters.len()).map_err(|_| {
154 error(
155 AttributeErrorKind::CountOverflow,
156 0,
157 "too many annotated parameters",
158 )
159 })?)?;
160 for annotations in &self.parameters {
161 encode_annotations(annotations, &mut out)?;
162 }
163 Ok(out.into_bytes())
164 }
165}
166
167#[derive(Clone, Copy, Debug, Eq, PartialEq)]
169pub struct TypePathEntry {
170 pub kind: u8,
172 pub argument_index: u8,
174 pub origin: AttributeOrigin,
176}
177
178#[derive(Clone, Debug, Eq, PartialEq)]
180pub enum TypeAnnotationTarget {
181 TypeParameter {
183 index: u8,
185 },
186 Supertype {
188 index: u16,
190 },
191 TypeParameterBound {
193 parameter_index: u8,
195 bound_index: u8,
197 },
198 Empty,
200 FormalParameter {
202 index: u8,
204 },
205 Throws {
207 index: u16,
209 },
210 LocalVariable {
212 table: Vec<LocalVariableTarget>,
214 },
215 Catch {
217 exception_table_index: u16,
219 },
220 Offset {
222 offset: u16,
224 },
225 TypeArgument {
227 offset: u16,
229 argument_index: u8,
231 },
232}
233
234#[derive(Clone, Copy, Debug, Eq, PartialEq)]
236pub struct LocalVariableTarget {
237 pub start_pc: u16,
239 pub length: u16,
241 pub index: u16,
243 pub origin: AttributeOrigin,
245}
246
247#[derive(Clone, Debug, Eq, PartialEq)]
249pub struct TypeAnnotation {
250 pub target_type: u8,
252 pub target: TypeAnnotationTarget,
254 pub path: Vec<TypePathEntry>,
256 pub type_index: u16,
258 pub elements: Vec<AnnotationElement>,
260 pub origin: AttributeOrigin,
262}
263
264#[derive(Clone, Debug, Eq, PartialEq)]
266pub struct TypeAnnotationsAttribute {
267 pub annotations: Vec<TypeAnnotation>,
269}
270
271impl TypeAnnotationsAttribute {
272 pub fn decode(
274 reader: &mut ByteReader<'_>,
275 nesting_budget: usize,
276 ) -> Result<Self, AttributeError> {
277 let n = usize::from(reader.read_u2()?);
278 reader.preflight_allocation(n)?;
279 let mut annotations = Vec::with_capacity(n);
280 for _ in 0..n {
281 annotations.push(decode_type_annotation(reader, nesting_budget)?);
282 }
283 finish(reader)?;
284 Ok(Self { annotations })
285 }
286
287 pub fn encode(&self, budget: usize) -> Result<Vec<u8>, AttributeError> {
289 let mut out = ByteWriter::new(budget);
290 out.write_u2(count(self.annotations.len(), "type annotations")?)?;
291 for annotation in &self.annotations {
292 encode_type_annotation(annotation, &mut out)?;
293 }
294 Ok(out.into_bytes())
295 }
296}
297
298#[derive(Clone, Debug, Eq, PartialEq)]
300pub struct AnnotationDefaultAttribute {
301 pub value: ElementValue,
303}
304
305impl AnnotationDefaultAttribute {
306 pub fn decode(
308 reader: &mut ByteReader<'_>,
309 nesting_budget: usize,
310 ) -> Result<Self, AttributeError> {
311 let mut budget = NestingBudget::new(nesting_budget);
312 let value = decode_element_value(reader, &mut budget)?;
313 finish(reader)?;
314 Ok(Self { value })
315 }
316
317 pub fn encode(&self, budget: usize) -> Result<Vec<u8>, AttributeError> {
319 let mut out = ByteWriter::new(budget);
320 encode_element_value(&self.value, &mut out)?;
321 Ok(out.into_bytes())
322 }
323}
324
325struct NestingBudget {
326 remaining: usize,
327}
328
329impl NestingBudget {
330 fn new(requested: usize) -> Self {
331 Self {
332 remaining: requested.min(MAX_ANNOTATION_NESTING),
333 }
334 }
335
336 fn enter(&mut self, offset: usize) -> Result<(), AttributeError> {
337 self.remaining = self.remaining.checked_sub(1).ok_or_else(|| {
338 error(
339 AttributeErrorKind::NestingBudgetExceeded,
340 offset,
341 "annotation nesting budget exceeded",
342 )
343 })?;
344 Ok(())
345 }
346
347 fn leave(&mut self) {
348 self.remaining += 1;
349 }
350}
351
352fn decode_annotations(
353 reader: &mut ByteReader<'_>,
354 nesting_budget: usize,
355) -> Result<Vec<Annotation>, AttributeError> {
356 let n = usize::from(reader.read_u2()?);
357 reader.preflight_allocation(n)?;
358 let mut budget = NestingBudget::new(nesting_budget);
359 let mut annotations = Vec::with_capacity(n);
360 for _ in 0..n {
361 annotations.push(decode_annotation(reader, &mut budget)?);
362 }
363 Ok(annotations)
364}
365
366fn decode_annotation(
367 reader: &mut ByteReader<'_>,
368 budget: &mut NestingBudget,
369) -> Result<Annotation, AttributeError> {
370 let start = reader.offset();
371 let type_index = reader.read_u2()?;
372 let n = usize::from(reader.read_u2()?);
373 reader.preflight_allocation(n)?;
374 let mut elements = Vec::with_capacity(n);
375 for _ in 0..n {
376 let pair_start = reader.offset();
377 let name_index = reader.read_u2()?;
378 let value = decode_element_value(reader, budget)?;
379 elements.push(AnnotationElement {
380 name_index,
381 value,
382 origin: annotation_origin(pair_start, reader),
383 });
384 }
385 Ok(Annotation {
386 type_index,
387 elements,
388 origin: annotation_origin(start, reader),
389 })
390}
391
392fn decode_element_value(
393 reader: &mut ByteReader<'_>,
394 budget: &mut NestingBudget,
395) -> Result<ElementValue, AttributeError> {
396 let start = reader.offset();
397 let tag = reader.read_u1()?;
398 let value = match tag {
399 b'B' | b'C' | b'D' | b'F' | b'I' | b'J' | b'S' | b'Z' | b's' => ElementValue::Constant {
400 tag,
401 constant_index: reader.read_u2()?,
402 origin: annotation_origin(start, reader),
403 },
404 b'e' => ElementValue::Enum {
405 type_name_index: reader.read_u2()?,
406 constant_name_index: reader.read_u2()?,
407 origin: annotation_origin(start, reader),
408 },
409 b'c' => ElementValue::Class {
410 class_info_index: reader.read_u2()?,
411 origin: annotation_origin(start, reader),
412 },
413 b'@' => {
414 budget.enter(start)?;
415 let annotation = decode_annotation(reader, budget);
416 budget.leave();
417 ElementValue::Annotation {
418 annotation: Box::new(annotation?),
419 origin: annotation_origin(start, reader),
420 }
421 }
422 b'[' => {
423 budget.enter(start)?;
424 let n = usize::from(reader.read_u2()?);
425 reader.preflight_allocation(n)?;
427 let mut values = Vec::with_capacity(n);
428 let result: Result<Vec<ElementValue>, AttributeError> = (|| {
429 for _ in 0..n {
430 values.push(decode_element_value(reader, budget)?);
431 }
432 Ok(values)
433 })();
434 budget.leave();
435 ElementValue::Array {
436 values: result?,
437 origin: annotation_origin(start, reader),
438 }
439 }
440 _ => {
441 return Err(error(
442 AttributeErrorKind::ReservedTag,
443 start,
444 format!("reserved annotation element tag {tag}"),
445 ));
446 }
447 };
448 Ok(value)
449}
450
451fn encode_annotations(values: &[Annotation], out: &mut ByteWriter) -> Result<(), AttributeError> {
452 out.write_u2(count(values.len(), "annotations")?)?;
453 for value in values {
454 encode_annotation(value, out)?;
455 }
456 Ok(())
457}
458
459fn encode_annotation(value: &Annotation, out: &mut ByteWriter) -> Result<(), AttributeError> {
460 out.write_u2(value.type_index)?;
461 out.write_u2(count(value.elements.len(), "annotation elements")?)?;
462 for element in &value.elements {
463 out.write_u2(element.name_index)?;
464 encode_element_value(&element.value, out)?;
465 }
466 Ok(())
467}
468
469fn encode_element_value(value: &ElementValue, out: &mut ByteWriter) -> Result<(), AttributeError> {
470 match value {
471 ElementValue::Constant {
472 tag,
473 constant_index,
474 ..
475 } => {
476 out.write_u1(*tag)?;
477 out.write_u2(*constant_index)?;
478 }
479 ElementValue::Enum {
480 type_name_index,
481 constant_name_index,
482 ..
483 } => {
484 out.write_u1(b'e')?;
485 out.write_u2(*type_name_index)?;
486 out.write_u2(*constant_name_index)?;
487 }
488 ElementValue::Class {
489 class_info_index, ..
490 } => {
491 out.write_u1(b'c')?;
492 out.write_u2(*class_info_index)?;
493 }
494 ElementValue::Annotation { annotation, .. } => {
495 out.write_u1(b'@')?;
496 encode_annotation(annotation, out)?;
497 }
498 ElementValue::Array { values, .. } => {
499 out.write_u1(b'[')?;
500 out.write_u2(count(values.len(), "annotation array values")?)?;
501 for item in values {
502 encode_element_value(item, out)?;
503 }
504 }
505 }
506 Ok(())
507}
508
509fn decode_type_annotation(
510 reader: &mut ByteReader<'_>,
511 nesting_budget: usize,
512) -> Result<TypeAnnotation, AttributeError> {
513 let start = reader.offset();
514 let target_type = reader.read_u1()?;
515 let target = match target_type {
516 0x00 | 0x01 => TypeAnnotationTarget::TypeParameter {
517 index: reader.read_u1()?,
518 },
519 0x10 => TypeAnnotationTarget::Supertype {
520 index: reader.read_u2()?,
521 },
522 0x11 | 0x12 => TypeAnnotationTarget::TypeParameterBound {
523 parameter_index: reader.read_u1()?,
524 bound_index: reader.read_u1()?,
525 },
526 0x13..=0x15 => TypeAnnotationTarget::Empty,
527 0x16 => TypeAnnotationTarget::FormalParameter {
528 index: reader.read_u1()?,
529 },
530 0x17 => TypeAnnotationTarget::Throws {
531 index: reader.read_u2()?,
532 },
533 0x40 | 0x41 => {
534 let n = usize::from(reader.read_u2()?);
535 reader.preflight_allocation(n)?;
536 let mut table = Vec::with_capacity(n);
537 for _ in 0..n {
538 let row_start = reader.offset();
539 table.push(LocalVariableTarget {
540 start_pc: reader.read_u2()?,
541 length: reader.read_u2()?,
542 index: reader.read_u2()?,
543 origin: annotation_origin(row_start, reader),
544 });
545 }
546 TypeAnnotationTarget::LocalVariable { table }
547 }
548 0x42 => TypeAnnotationTarget::Catch {
549 exception_table_index: reader.read_u2()?,
550 },
551 0x43..=0x46 => TypeAnnotationTarget::Offset {
552 offset: reader.read_u2()?,
553 },
554 0x47..=0x4b => TypeAnnotationTarget::TypeArgument {
555 offset: reader.read_u2()?,
556 argument_index: reader.read_u1()?,
557 },
558 _ => {
559 return Err(error(
560 AttributeErrorKind::ReservedTag,
561 start,
562 format!("reserved type annotation target {target_type:#04x}"),
563 ));
564 }
565 };
566 let path_len = usize::from(reader.read_u1()?);
567 reader.preflight_allocation(path_len)?;
568 let mut path = Vec::with_capacity(path_len);
569 for _ in 0..path_len {
570 let path_start = reader.offset();
571 let kind = reader.read_u1()?;
572 let argument_index = reader.read_u1()?;
573 if kind > 3 || (kind != 3 && argument_index != 0) {
574 return Err(error(
575 AttributeErrorKind::StaticConstraint,
576 path_start,
577 "invalid type annotation path entry",
578 ));
579 }
580 path.push(TypePathEntry {
581 kind,
582 argument_index,
583 origin: annotation_origin(path_start, reader),
584 });
585 }
586 let mut budget = NestingBudget::new(nesting_budget);
587 let annotation = decode_annotation(reader, &mut budget)?;
588 Ok(TypeAnnotation {
589 target_type,
590 target,
591 path,
592 type_index: annotation.type_index,
593 elements: annotation.elements,
594 origin: annotation_origin(start, reader),
595 })
596}
597
598fn encode_type_annotation(
599 value: &TypeAnnotation,
600 out: &mut ByteWriter,
601) -> Result<(), AttributeError> {
602 out.write_u1(value.target_type)?;
603 match (&value.target, value.target_type) {
604 (TypeAnnotationTarget::TypeParameter { index }, 0x00 | 0x01) => out.write_u1(*index)?,
605 (TypeAnnotationTarget::Supertype { index }, 0x10) => out.write_u2(*index)?,
606 (
607 TypeAnnotationTarget::TypeParameterBound {
608 parameter_index,
609 bound_index,
610 },
611 0x11 | 0x12,
612 ) => {
613 out.write_u1(*parameter_index)?;
614 out.write_u1(*bound_index)?;
615 }
616 (TypeAnnotationTarget::Empty, 0x13..=0x15) => {}
617 (TypeAnnotationTarget::FormalParameter { index }, 0x16) => out.write_u1(*index)?,
618 (TypeAnnotationTarget::Throws { index }, 0x17) => out.write_u2(*index)?,
619 (TypeAnnotationTarget::LocalVariable { table }, 0x40 | 0x41) => {
620 out.write_u2(count(table.len(), "local-variable targets")?)?;
621 for row in table {
622 out.write_u2(row.start_pc)?;
623 out.write_u2(row.length)?;
624 out.write_u2(row.index)?;
625 }
626 }
627 (
628 TypeAnnotationTarget::Catch {
629 exception_table_index,
630 },
631 0x42,
632 ) => out.write_u2(*exception_table_index)?,
633 (TypeAnnotationTarget::Offset { offset }, 0x43..=0x46) => out.write_u2(*offset)?,
634 (
635 TypeAnnotationTarget::TypeArgument {
636 offset,
637 argument_index,
638 },
639 0x47..=0x4b,
640 ) => {
641 out.write_u2(*offset)?;
642 out.write_u1(*argument_index)?;
643 }
644 _ => {
645 return Err(error(
646 AttributeErrorKind::StaticConstraint,
647 0,
648 "type annotation target does not match target_type",
649 ));
650 }
651 }
652 out.write_u1(u8::try_from(value.path.len()).map_err(|_| {
653 error(
654 AttributeErrorKind::CountOverflow,
655 0,
656 "type path is too long",
657 )
658 })?)?;
659 for entry in &value.path {
660 if entry.kind > 3 || (entry.kind != 3 && entry.argument_index != 0) {
661 return Err(error(
662 AttributeErrorKind::StaticConstraint,
663 0,
664 "invalid type annotation path entry",
665 ));
666 }
667 out.write_u1(entry.kind)?;
668 out.write_u1(entry.argument_index)?;
669 }
670 encode_annotation(
671 &Annotation {
672 type_index: value.type_index,
673 elements: value.elements.clone(),
674 origin: value.origin,
675 },
676 out,
677 )
678}