sqry_classpath/bytecode/
constants.rs1use cafebabe::attributes::{AttributeData, AttributeInfo};
7use cafebabe::constant_pool::LiteralConstant;
8use cafebabe::descriptors::{FieldDescriptor, FieldType, MethodDescriptor, ReturnDescriptor};
9
10use crate::stub::model::{BaseType, ConstantValue, OrderedFloat, TypeSignature};
11
12pub(crate) fn field_descriptor_to_type(desc: &FieldDescriptor<'_>) -> TypeSignature {
21 let base = field_type_to_signature(&desc.field_type);
22 wrap_in_arrays(base, desc.dimensions)
23}
24
25pub(crate) fn return_descriptor_to_type(desc: &ReturnDescriptor<'_>) -> TypeSignature {
30 match desc {
31 ReturnDescriptor::Void => TypeSignature::Base(BaseType::Void),
32 ReturnDescriptor::Return(fd) => field_descriptor_to_type(fd),
33 }
34}
35
36pub(crate) fn method_descriptor_to_types(
38 desc: &MethodDescriptor<'_>,
39) -> (Vec<TypeSignature>, TypeSignature) {
40 let param_types = desc
41 .parameters
42 .iter()
43 .map(field_descriptor_to_type)
44 .collect();
45 let return_type = return_descriptor_to_type(&desc.return_type);
46 (param_types, return_type)
47}
48
49fn field_type_to_signature(ft: &FieldType<'_>) -> TypeSignature {
52 match ft {
53 FieldType::Byte => TypeSignature::Base(BaseType::Byte),
54 FieldType::Char => TypeSignature::Base(BaseType::Char),
55 FieldType::Double => TypeSignature::Base(BaseType::Double),
56 FieldType::Float => TypeSignature::Base(BaseType::Float),
57 FieldType::Integer => TypeSignature::Base(BaseType::Int),
58 FieldType::Long => TypeSignature::Base(BaseType::Long),
59 FieldType::Short => TypeSignature::Base(BaseType::Short),
60 FieldType::Boolean => TypeSignature::Base(BaseType::Boolean),
61 FieldType::Object(class_name) => TypeSignature::Class {
62 fqn: class_name_to_fqn(class_name),
63 type_arguments: vec![],
64 },
65 }
66}
67
68fn wrap_in_arrays(inner: TypeSignature, dimensions: u8) -> TypeSignature {
70 let mut sig = inner;
71 for _ in 0..dimensions {
72 sig = TypeSignature::Array(Box::new(sig));
73 }
74 sig
75}
76
77pub(crate) fn class_name_to_fqn(name: &str) -> String {
86 name.replace('/', ".")
87}
88
89pub(crate) fn literal_to_constant_value(lit: &LiteralConstant<'_>) -> ConstantValue {
95 match lit {
96 LiteralConstant::Integer(v) => ConstantValue::Int(*v),
97 LiteralConstant::Long(v) => ConstantValue::Long(*v),
98 LiteralConstant::Float(v) => ConstantValue::Float(OrderedFloat(*v)),
99 LiteralConstant::Double(v) => ConstantValue::Double(OrderedFloat(*v)),
100 LiteralConstant::String(s) => ConstantValue::String(s.to_string()),
101 LiteralConstant::StringBytes(bytes) => {
102 ConstantValue::String(String::from_utf8_lossy(bytes).into_owned())
104 }
105 }
106}
107
108pub(crate) fn extract_source_file(attrs: &[AttributeInfo<'_>]) -> Option<String> {
114 attrs.iter().find_map(|a| match &a.data {
115 AttributeData::SourceFile(s) => Some(s.to_string()),
116 _ => None,
117 })
118}
119
120pub(crate) fn extract_method_parameter_names(attrs: &[AttributeInfo<'_>]) -> Vec<String> {
122 for attr in attrs {
123 if let AttributeData::MethodParameters(params) = &attr.data {
124 return params
125 .iter()
126 .filter_map(|p| p.name.as_ref().map(std::string::ToString::to_string))
127 .collect();
128 }
129 }
130 vec![]
131}
132
133pub(crate) fn extract_constant_value(attrs: &[AttributeInfo<'_>]) -> Option<ConstantValue> {
135 attrs.iter().find_map(|a| match &a.data {
136 AttributeData::ConstantValue(lit) => Some(literal_to_constant_value(lit)),
137 _ => None,
138 })
139}
140
141#[cfg(test)]
146mod tests {
147 use super::*;
148
149 #[test]
150 fn test_class_name_to_fqn() {
151 assert_eq!(class_name_to_fqn("java/lang/String"), "java.lang.String");
152 assert_eq!(class_name_to_fqn("com/example/Foo"), "com.example.Foo");
153 assert_eq!(class_name_to_fqn("SimpleClass"), "SimpleClass");
154 }
155
156 #[test]
157 fn test_literal_to_constant_value() {
158 assert_eq!(
159 literal_to_constant_value(&LiteralConstant::Integer(42)),
160 ConstantValue::Int(42)
161 );
162 assert_eq!(
163 literal_to_constant_value(&LiteralConstant::Long(123_456_789)),
164 ConstantValue::Long(123_456_789)
165 );
166 assert_eq!(
167 literal_to_constant_value(&LiteralConstant::Float(std::f32::consts::PI)),
168 ConstantValue::Float(OrderedFloat(std::f32::consts::PI))
169 );
170 assert_eq!(
171 literal_to_constant_value(&LiteralConstant::Double(std::f64::consts::E)),
172 ConstantValue::Double(OrderedFloat(std::f64::consts::E))
173 );
174 assert_eq!(
175 literal_to_constant_value(&LiteralConstant::String("hello".into())),
176 ConstantValue::String("hello".to_owned())
177 );
178 }
179}