Skip to main content

lvm_class/attribute/
shared.rs

1//! Shared attribute types that can appear at multiple locations in a class file.
2//!
3//! These attributes can be attached to classes, fields, methods, and record components.
4
5use super::AttributeKind;
6use super::annotation::Annotation;
7use super::type_annotation::TypeAnnotation;
8use crate::ClassFormatErr;
9use lvm_common::utils::cursor::ByteCursor;
10
11/// Attribute payloads that can appear at multiple locations (class, field, method, record).
12#[derive(Debug, Clone, PartialEq, Eq)]
13pub enum SharedAttribute {
14    Synthetic {
15        attr_name_idx: u16,
16    },
17    Deprecated {
18        attr_name_idx: u16,
19    },
20    Signature {
21        attr_name_idx: u16,
22        signature_idx: u16,
23    },
24    RuntimeVisibleAnnotations {
25        attr_name_idx: u16,
26        annotations: Vec<Annotation>,
27    },
28    RuntimeInvisibleAnnotations {
29        attr_name_idx: u16,
30        annotations: Vec<Annotation>,
31    },
32    RuntimeVisibleTypeAnnotations {
33        attr_name_idx: u16,
34        annotations: Vec<TypeAnnotation>,
35    },
36    RuntimeInvisibleTypeAnnotations {
37        attr_name_idx: u16,
38        annotations: Vec<TypeAnnotation>,
39    },
40}
41
42impl SharedAttribute {
43    pub fn kind(&self) -> AttributeKind {
44        match self {
45            Self::Synthetic { .. } => AttributeKind::Synthetic,
46            Self::Deprecated { .. } => AttributeKind::Deprecated,
47            Self::Signature { .. } => AttributeKind::Signature,
48            Self::RuntimeVisibleAnnotations { .. } => AttributeKind::RuntimeVisibleAnnotations,
49            Self::RuntimeInvisibleAnnotations { .. } => AttributeKind::RuntimeInvisibleAnnotations,
50            Self::RuntimeVisibleTypeAnnotations { .. } => {
51                AttributeKind::RuntimeVisibleTypeAnnotations
52            }
53            Self::RuntimeInvisibleTypeAnnotations { .. } => {
54                AttributeKind::RuntimeInvisibleTypeAnnotations
55            }
56        }
57    }
58}
59
60impl<'a> SharedAttribute {
61    pub(crate) fn read(
62        attr_name_idx: u16,
63        attr_type: AttributeKind,
64        cursor: &mut ByteCursor<'a>,
65    ) -> Result<Self, ClassFormatErr> {
66        match attr_type {
67            AttributeKind::Synthetic => Ok(SharedAttribute::Synthetic { attr_name_idx }),
68            AttributeKind::Deprecated => Ok(SharedAttribute::Deprecated { attr_name_idx }),
69            AttributeKind::Signature => {
70                let signature_idx = cursor.u16()?;
71                Ok(SharedAttribute::Signature {
72                    attr_name_idx,
73                    signature_idx,
74                })
75            }
76            AttributeKind::RuntimeVisibleAnnotations => {
77                let num_annotations = cursor.u16()?;
78                let mut annotations = Vec::with_capacity(num_annotations as usize);
79                for _ in 0..num_annotations {
80                    annotations.push(Annotation::read(cursor)?);
81                }
82                Ok(SharedAttribute::RuntimeVisibleAnnotations {
83                    attr_name_idx,
84                    annotations,
85                })
86            }
87            AttributeKind::RuntimeInvisibleAnnotations => {
88                let num_annotations = cursor.u16()?;
89                let mut annotations = Vec::with_capacity(num_annotations as usize);
90                for _ in 0..num_annotations {
91                    annotations.push(Annotation::read(cursor)?);
92                }
93                Ok(SharedAttribute::RuntimeInvisibleAnnotations {
94                    attr_name_idx,
95                    annotations,
96                })
97            }
98            AttributeKind::RuntimeInvisibleTypeAnnotations => {
99                let num_annotations = cursor.u16()?;
100                let mut annotations = Vec::with_capacity(num_annotations as usize);
101                for _ in 0..num_annotations {
102                    annotations.push(TypeAnnotation::read(cursor)?);
103                }
104                Ok(SharedAttribute::RuntimeInvisibleTypeAnnotations {
105                    attr_name_idx,
106                    annotations,
107                })
108            }
109            AttributeKind::RuntimeVisibleTypeAnnotations => {
110                let num_annotations = cursor.u16()?;
111                let mut annotations = Vec::with_capacity(num_annotations as usize);
112                for _ in 0..num_annotations {
113                    annotations.push(TypeAnnotation::read(cursor)?);
114                }
115                Ok(SharedAttribute::RuntimeVisibleTypeAnnotations {
116                    attr_name_idx,
117                    annotations,
118                })
119            }
120            _ => Err(ClassFormatErr::AttributeIsNotShared(attr_type.to_string())),
121        }
122    }
123}