Skip to main content

sim_codec_classfile/attribute/
class.rs

1/// One bootstrap method and its ordered, arity-preserving constant-pool arguments.
2#[derive(Clone, Debug, Eq, PartialEq)]
3pub struct BootstrapMethod {
4    /// Constant-pool index of the method handle.
5    pub method_ref: u16,
6    /// Constant-pool argument indices in invocation order.
7    pub arguments: Vec<u16>,
8}
9
10/// An ordered `BootstrapMethods` payload.
11#[derive(Clone, Debug, Eq, PartialEq)]
12pub struct BootstrapMethodsAttribute {
13    /// Bootstrap methods in classfile index order.
14    pub methods: Vec<BootstrapMethod>,
15}
16
17impl BootstrapMethodsAttribute {
18    /// Decode without resolving method handles, arguments, or dynamic constants.
19    pub fn decode(reader: &mut ByteReader<'_>) -> Result<Self, AttributeError> {
20        let n = usize::from(reader.read_u2()?);
21        reader.preflight_allocation(n)?;
22        let mut methods = Vec::with_capacity(n);
23        for _ in 0..n {
24            let method_ref = reader.read_u2()?;
25            let argc = usize::from(reader.read_u2()?);
26            reader.preflight_allocation(argc)?;
27            let mut arguments = Vec::with_capacity(argc);
28            for _ in 0..argc {
29                arguments.push(reader.read_u2()?)
30            }
31            methods.push(BootstrapMethod {
32                method_ref,
33                arguments,
34            });
35        }
36        finish(reader)?;
37        Ok(Self { methods })
38    }
39    /// Encode method and argument sequences exactly in stored order.
40    pub fn encode(&self, budget: usize) -> Result<Vec<u8>, AttributeError> {
41        let mut out = ByteWriter::new(budget);
42        out.write_u2(count(self.methods.len(), "bootstrap methods")?)?;
43        for method in &self.methods {
44            out.write_u2(method.method_ref)?;
45            out.write_u2(count(method.arguments.len(), "bootstrap arguments")?)?;
46            for argument in &method.arguments {
47                out.write_u2(*argument)?
48            }
49        }
50        Ok(out.into_bytes())
51    }
52}
53
54/// One nested attribute attached to a record component.
55pub type RecordComponentAttribute = NestedAttribute;
56
57/// One component in a `Record` attribute.
58#[derive(Clone, Debug, Eq, PartialEq)]
59pub struct RecordComponent {
60    /// Component name index.
61    pub name_index: u16,
62    /// Component descriptor index.
63    pub descriptor_index: u16,
64    /// Component attributes in classfile order.
65    pub attributes: Vec<RecordComponentAttribute>,
66}
67
68/// The ordered `Record` payload.
69#[derive(Clone, Debug, Eq, PartialEq)]
70pub struct RecordAttribute {
71    /// Components in declaration order.
72    pub components: Vec<RecordComponent>,
73}
74
75impl RecordAttribute {
76    /// Decode components and retain every nested attribute as exact bytes.
77    pub fn decode(reader: &mut ByteReader<'_>) -> Result<Self, AttributeError> {
78        let n = usize::from(reader.read_u2()?);
79        reader.preflight_allocation(n)?;
80        let mut components = Vec::with_capacity(n);
81        for _ in 0..n {
82            let name_index = reader.read_u2()?;
83            let descriptor_index = reader.read_u2()?;
84            let attribute_count = usize::from(reader.read_u2()?);
85            reader.preflight_allocation(attribute_count)?;
86            let mut attributes = Vec::with_capacity(attribute_count);
87            for order in 0..attribute_count {
88                let start = reader.offset();
89                let name_index = reader.read_u2()?;
90                let declared_length = reader.read_u4()?;
91                let length = usize::try_from(declared_length).map_err(|_| {
92                    error(
93                        AttributeErrorKind::StaticConstraint,
94                        reader.offset(),
95                        "record component attribute length is not addressable",
96                    )
97                })?;
98                attributes.push(NestedAttribute {
99                    name_index,
100                    owner: NestedAttributeOwner::RecordComponent,
101                    order,
102                    declared_length,
103                    bytes: reader.take(length)?.to_vec(),
104                    origin: annotation_origin(start, reader),
105                });
106            }
107            components.push(RecordComponent {
108                name_index,
109                descriptor_index,
110                attributes,
111            });
112        }
113        finish(reader)?;
114        Ok(Self { components })
115    }
116
117    /// Encode component and nested-attribute order exactly as stored.
118    pub fn encode(&self, budget: usize) -> Result<Vec<u8>, AttributeError> {
119        let mut out = ByteWriter::new(budget);
120        out.write_u2(count(self.components.len(), "record components")?)?;
121        for component in &self.components {
122            out.write_u2(component.name_index)?;
123            out.write_u2(component.descriptor_index)?;
124            out.write_u2(count(
125                component.attributes.len(),
126                "record component attributes",
127            )?)?;
128            for attribute in &component.attributes {
129                if usize::try_from(attribute.declared_length).ok() != Some(attribute.bytes.len()) {
130                    return Err(error(
131                        AttributeErrorKind::StaticConstraint,
132                        attribute.origin.start,
133                        "record component attribute declared length differs from retained bytes",
134                    ));
135                }
136                out.write_u2(attribute.name_index)?;
137                out.write_u4(attribute.declared_length)?;
138                out.write_bytes(&attribute.bytes)?;
139            }
140        }
141        Ok(out.into_bytes())
142    }
143}
144
145/// One `requires` directive in a `Module` attribute.
146#[derive(Clone, Copy, Debug, Eq, PartialEq)]
147pub struct ModuleRequire {
148    /// Module constant index.
149    pub module_index: u16,
150    /// Raw requires flags.
151    pub flags: u16,
152    /// Version string index, or zero.
153    pub version_index: u16,
154}
155/// One `exports` or `opens` directive in a `Module` attribute.
156#[derive(Clone, Debug, Eq, PartialEq)]
157pub struct ModuleExport {
158    /// Package constant index.
159    pub package_index: u16,
160    /// Raw directive flags.
161    pub flags: u16,
162    /// Target module indices in encoded order.
163    pub targets: Vec<u16>,
164}
165/// One `provides` directive in a `Module` attribute.
166#[derive(Clone, Debug, Eq, PartialEq)]
167pub struct ModuleProvide {
168    /// Service class index.
169    pub service_index: u16,
170    /// Provider class indices in encoded order.
171    pub providers: Vec<u16>,
172}
173/// The complete structural `Module` payload.
174#[derive(Clone, Debug, Eq, PartialEq)]
175pub struct ModuleAttribute {
176    /// Module constant index.
177    pub name_index: u16,
178    /// Raw module flags.
179    pub flags: u16,
180    /// Module version string index, or zero.
181    pub version_index: u16,
182    /// Required modules in declaration order.
183    pub requires: Vec<ModuleRequire>,
184    /// Export directives in declaration order.
185    pub exports: Vec<ModuleExport>,
186    /// Open directives in declaration order.
187    pub opens: Vec<ModuleExport>,
188    /// Used service class indices in declaration order.
189    pub uses: Vec<u16>,
190    /// Service provider directives in declaration order.
191    pub provides: Vec<ModuleProvide>,
192}
193
194fn decode_module_exports(reader: &mut ByteReader<'_>) -> Result<Vec<ModuleExport>, AttributeError> {
195    let n = usize::from(reader.read_u2()?);
196    reader.preflight_allocation(n)?;
197    let mut values = Vec::with_capacity(n);
198    for _ in 0..n {
199        let package_index = reader.read_u2()?;
200        let flags = reader.read_u2()?;
201        let m = usize::from(reader.read_u2()?);
202        reader.preflight_allocation(m)?;
203        let mut targets = Vec::with_capacity(m);
204        for _ in 0..m {
205            targets.push(reader.read_u2()?);
206        }
207        values.push(ModuleExport {
208            package_index,
209            flags,
210            targets,
211        });
212    }
213    Ok(values)
214}
215fn encode_module_exports(
216    values: &[ModuleExport],
217    out: &mut ByteWriter,
218    what: &str,
219) -> Result<(), AttributeError> {
220    out.write_u2(count(values.len(), what)?)?;
221    for v in values {
222        out.write_u2(v.package_index)?;
223        out.write_u2(v.flags)?;
224        out.write_u2(count(v.targets.len(), "module directive targets")?)?;
225        for target in &v.targets {
226            out.write_u2(*target)?;
227        }
228    }
229    Ok(())
230}
231
232impl ModuleAttribute {
233    /// Decode all module directives without resolving or interpreting them.
234    pub fn decode(reader: &mut ByteReader<'_>) -> Result<Self, AttributeError> {
235        let name_index = reader.read_u2()?;
236        let flags = reader.read_u2()?;
237        let version_index = reader.read_u2()?;
238        let n = usize::from(reader.read_u2()?);
239        reader.preflight_allocation(n)?;
240        let mut requires = Vec::with_capacity(n);
241        for _ in 0..n {
242            requires.push(ModuleRequire {
243                module_index: reader.read_u2()?,
244                flags: reader.read_u2()?,
245                version_index: reader.read_u2()?,
246            });
247        }
248        let exports = decode_module_exports(reader)?;
249        let opens = decode_module_exports(reader)?;
250        let n = usize::from(reader.read_u2()?);
251        reader.preflight_allocation(n)?;
252        let mut uses = Vec::with_capacity(n);
253        for _ in 0..n {
254            uses.push(reader.read_u2()?);
255        }
256        let n = usize::from(reader.read_u2()?);
257        reader.preflight_allocation(n)?;
258        let mut provides = Vec::with_capacity(n);
259        for _ in 0..n {
260            let service_index = reader.read_u2()?;
261            let m = usize::from(reader.read_u2()?);
262            reader.preflight_allocation(m)?;
263            let mut providers = Vec::with_capacity(m);
264            for _ in 0..m {
265                providers.push(reader.read_u2()?);
266            }
267            provides.push(ModuleProvide {
268                service_index,
269                providers,
270            });
271        }
272        finish(reader)?;
273        Ok(Self {
274            name_index,
275            flags,
276            version_index,
277            requires,
278            exports,
279            opens,
280            uses,
281            provides,
282        })
283    }
284    /// Encode every directive exactly in stored order.
285    pub fn encode(&self, budget: usize) -> Result<Vec<u8>, AttributeError> {
286        let mut out = ByteWriter::new(budget);
287        out.write_u2(self.name_index)?;
288        out.write_u2(self.flags)?;
289        out.write_u2(self.version_index)?;
290        out.write_u2(count(self.requires.len(), "module requires")?)?;
291        for v in &self.requires {
292            out.write_u2(v.module_index)?;
293            out.write_u2(v.flags)?;
294            out.write_u2(v.version_index)?;
295        }
296        encode_module_exports(&self.exports, &mut out, "module exports")?;
297        encode_module_exports(&self.opens, &mut out, "module opens")?;
298        out.write_u2(count(self.uses.len(), "module uses")?)?;
299        for v in &self.uses {
300            out.write_u2(*v)?;
301        }
302        out.write_u2(count(self.provides.len(), "module provides")?)?;
303        for v in &self.provides {
304            out.write_u2(v.service_index)?;
305            out.write_u2(count(v.providers.len(), "module providers")?)?;
306            for provider in &v.providers {
307                out.write_u2(*provider)?;
308            }
309        }
310        Ok(out.into_bytes())
311    }
312}
313
314/// Earliest classfile major version for a standard attribute.
315pub fn standard_attribute_min_major(name: &str) -> Option<u16> {
316    match name {
317        "Signature"
318        | "SourceDebugExtension"
319        | "LocalVariableTypeTable"
320        | "EnclosingMethod"
321        | "RuntimeVisibleAnnotations"
322        | "RuntimeInvisibleAnnotations"
323        | "RuntimeVisibleParameterAnnotations"
324        | "RuntimeInvisibleParameterAnnotations"
325        | "AnnotationDefault" => Some(49),
326        "StackMapTable" => Some(50),
327        "BootstrapMethods" => Some(51),
328        "MethodParameters"
329        | "RuntimeVisibleTypeAnnotations"
330        | "RuntimeInvisibleTypeAnnotations" => Some(52),
331        "Module" | "ModulePackages" | "ModuleMainClass" => Some(53),
332        "NestHost" | "NestMembers" => Some(55),
333        "Record" => Some(60),
334        "PermittedSubclasses" => Some(61),
335        "ConstantValue" | "Code" | "Exceptions" | "InnerClasses" | "Synthetic" | "SourceFile"
336        | "LineNumberTable" | "LocalVariableTable" | "Deprecated" => Some(45),
337        _ => None,
338    }
339}