Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions ristretto_classloader/src/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ impl TryInto<bool> for Object {

fn try_into(self) -> Result<bool> {
let value = self.class_value("java/lang/Boolean")?;
let value = value.to_int()?;
let value: i32 = value.try_into()?;
Ok(value != 0)
}
}
Expand All @@ -459,8 +459,9 @@ impl TryInto<char> for Object {

fn try_into(self) -> Result<char> {
let value = self.class_value("java/lang/Character")?;
let value: i32 = value.try_into()?;
#[expect(clippy::cast_sign_loss)]
let value = value.to_int()? as u32;
let value = value as u32;
let character = char::try_from(value)
.map_err(|_| InvalidValueType("Invalid character value".to_string()))?;
Ok(character)
Expand All @@ -472,7 +473,7 @@ impl TryInto<i8> for Object {

fn try_into(self) -> Result<i8> {
let value = self.class_value("java/lang/Byte")?;
let value = value.to_int()?;
let value: i32 = value.try_into()?;
let value =
i8::try_from(value).map_err(|_| InvalidValueType("Invalid byte value".to_string()))?;
Ok(value)
Expand All @@ -494,7 +495,7 @@ impl TryInto<i16> for Object {

fn try_into(self) -> Result<i16> {
let value = self.class_value("java/lang/Short")?;
let value = value.to_int()?;
let value: i32 = value.try_into()?;
let value = i16::try_from(value)
.map_err(|_| InvalidValueType("Invalid short value".to_string()))?;
Ok(value)
Expand All @@ -516,7 +517,7 @@ impl TryInto<i32> for Object {

fn try_into(self) -> Result<i32> {
let value = self.class_value("java/lang/Integer")?;
let value = value.to_int()?;
let value: i32 = value.try_into()?;
Ok(value)
}
}
Expand All @@ -536,7 +537,7 @@ impl TryInto<i64> for Object {

fn try_into(self) -> Result<i64> {
let value = self.class_value("java/lang/Long")?;
let value = value.to_long()?;
let value = value.try_into()?;
Ok(value)
}
}
Expand Down Expand Up @@ -576,7 +577,7 @@ impl TryInto<f32> for Object {

fn try_into(self) -> Result<f32> {
let value = self.class_value("java/lang/Float")?;
let value = value.to_float()?;
let value = value.try_into()?;
Ok(value)
}
}
Expand All @@ -586,7 +587,7 @@ impl TryInto<f64> for Object {

fn try_into(self) -> Result<f64> {
let value = self.class_value("java/lang/Double")?;
let value = value.to_double()?;
let value = value.try_into()?;
Ok(value)
}
}
Expand All @@ -603,7 +604,7 @@ impl TryInto<String> for Object {
};
match reference {
ByteArray(bytes) => {
let coder = self.value("coder")?.to_int()?;
let coder: i32 = self.value("coder")?.try_into()?;
if coder == 0 {
// Latin-1 encoded string
let bytes = bytes
Expand Down
120 changes: 27 additions & 93 deletions ristretto_classloader/src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,62 +17,20 @@ pub enum Value {
}

impl Value {
/// Returns the value as an `i32`.
///
/// # Errors
///
/// if the value is not an `Int`.
pub fn to_int(&self) -> Result<i32> {
match self {
Value::Int(value) => Ok(*value),
_ => Err(InvalidValueType("Expected an int value".to_string())),
}
}

/// Returns the value as an `i64`.
///
/// # Errors
///
/// if the value is not a `Long`
pub fn to_long(&self) -> Result<i64> {
match self {
Value::Long(value) => Ok(*value),
_ => Err(InvalidValueType("Expected a long value".to_string())),
}
}

/// Returns the value as an `f32`.
///
/// # Errors
///
/// if the value is not a `Float`
pub fn to_float(&self) -> Result<f32> {
match self {
Value::Float(value) => Ok(*value),
_ => Err(InvalidValueType("Expected a float value".to_string())),
}
}

/// Returns the value as an `f64`.
///
/// # Errors
///
/// if the value is not a `Double`
pub fn to_double(&self) -> Result<f64> {
match self {
Value::Double(value) => Ok(*value),
_ => Err(InvalidValueType("Expected a double value".to_string())),
}
/// Returns true if the value is null.
#[must_use]
pub fn is_null(&self) -> bool {
matches!(self, Value::Object(None))
}

/// Returns the value as an `Option<Reference>`.
/// Returns a reference to the value if it is an object.
///
/// # Errors
///
/// if the value is not a `Reference`
pub fn to_reference(&self) -> Result<Option<Reference>> {
/// If the value is not an object or if it cannot be converted to a reference.
pub fn as_reference(&self) -> Result<&Reference> {
match self {
Value::Object(value) => Ok(value.clone()),
Value::Object(Some(reference)) => Ok(reference),
_ => Err(InvalidValueType("Expected a reference value".to_string())),
}
}
Expand Down Expand Up @@ -689,88 +647,63 @@ mod tests {
}

#[test]
fn test_int_format() -> Result<()> {
fn test_int_format() {
let value = Value::Int(42);
assert_eq!(42, value.to_int()?);
assert_eq!("int(42)", value.to_string());
assert!(value.is_category_1());
assert!(!value.is_category_2());
Ok(())
}

#[test]
fn test_to_int_error() {
let result = Value::Long(42).to_int();
assert!(matches!(result, Err(InvalidValueType(_))));
}

#[test]
fn test_long_format() -> Result<()> {
fn test_long_format() {
let value = Value::Long(42);
assert_eq!(42, value.to_long()?);
assert_eq!("long(42)", value.to_string());
assert!(!value.is_category_1());
assert!(value.is_category_2());
Ok(())
}

#[test]
fn test_to_long_error() {
let result = Value::Int(42).to_long();
assert!(matches!(result, Err(InvalidValueType(_))));
}

#[test]
fn test_float_format() -> Result<()> {
fn test_float_format() {
let value = Value::Float(42.1);
let compare_value = value.to_float()? - 42.1f32;
assert!(compare_value.abs() < 0.1f32);
assert_eq!("float(42.1)", value.to_string());
assert!(value.is_category_1());
assert!(!value.is_category_2());
Ok(())
}

#[test]
fn test_to_float_error() {
let result = Value::Int(42).to_float();
assert!(matches!(result, Err(InvalidValueType(_))));
}

#[test]
fn test_double_format() -> Result<()> {
fn test_double_format() {
let value = Value::Double(42.1);
let compare_value = value.to_double()? - 42.1f64;
assert!(compare_value.abs() < 0.1f64);
assert_eq!("double(42.1)", value.to_string());
assert!(!value.is_category_1());
assert!(value.is_category_2());
Ok(())
}

#[test]
fn test_to_double_error() {
let result = Value::Int(42).to_double();
assert!(matches!(result, Err(InvalidValueType(_))));
}

#[test]
fn test_object_format() -> Result<()> {
fn test_object_format() {
let value = Value::Object(None);
assert_eq!(None, value.to_reference()?);
assert_eq!("Object(null)", value.to_string());
assert!(value.is_null());
assert!(value.is_category_1());
assert!(!value.is_category_2());
assert_eq!(
"byte[1, 2, 3]",
format!("{}", Value::from(vec![1i8, 2i8, 3i8]))
);
}

#[test]
fn test_as_reference() -> Result<()> {
let reference = Reference::from(vec![1i8, 2i8, 3i8]);
let value = Value::Object(Some(reference));
let reference = value.as_reference()?;
let array = reference.as_byte_vec_ref()?;
assert_eq!(array.to_vec(), vec![1, 2, 3]);
Ok(())
}

#[test]
fn test_to_object_error() {
let result = Value::Int(42).to_reference();
fn test_as_reference_error() {
let result: Result<&Reference> = Value::Int(42).as_reference();
assert!(matches!(result, Err(InvalidValueType(_))));
}

Expand All @@ -782,6 +715,7 @@ mod tests {
let object = Object::new(class)?;
let string_bytes: Vec<i8> = "foo".as_bytes().to_vec().iter().map(|&b| b as i8).collect();
let string_value = Value::from(string_bytes);
assert!(!string_value.is_null());
object.set_value("value", string_value)?;
let value = Value::from(object);
assert_eq!("String(\"foo\")", value.to_string());
Expand Down Expand Up @@ -1322,7 +1256,7 @@ mod tests {
let value = Value::from(object);
let original_values = vec![value];
let value = Value::try_from((original_class.clone(), original_values.clone()))?;
let reference = value.to_reference()?.expect("vec");
let reference: Reference = value.try_into()?;
let reference_class_name = reference.class_name().to_string();
let reference_values: Vec<Value> = reference.try_into()?;
assert_eq!(original_class.name(), reference_class_name);
Expand Down
2 changes: 1 addition & 1 deletion ristretto_cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ fn process_error(error: Error) -> Result<()> {
if let Value::Object(Some(ref _file_object)) = file {
source = file.try_into()?;
}
let line = stack_trace_element.value("lineNumber")?.to_int()?;
let line: i32 = stack_trace_element.value("lineNumber")?.try_into()?;
if line > 0 {
if source.is_empty() {
source = format!("{line}");
Expand Down
5 changes: 2 additions & 3 deletions ristretto_vm/src/intrinsic_methods/java/io/console.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,8 @@ mod tests {
let (_vm, thread) = crate::test::thread().await.expect("thread");
let value = encoding(thread, Parameters::default())
.await?
.expect("encoding")
.to_reference()?;
assert!(value.is_none());
.expect("encoding");
assert!(value.is_null());
Ok(())
}

Expand Down
6 changes: 3 additions & 3 deletions ristretto_vm/src/intrinsic_methods/java/io/filedescriptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,16 @@ pub(crate) fn file_descriptor_from_java_object(
let fd = if vm.java_class_file_version() >= &JAVA_11 {
#[cfg(not(target_os = "windows"))]
{
let fd = file_descriptor.value("fd")?.to_int()?;
let fd: i32 = file_descriptor.value("fd")?.try_into()?;
i64::from(fd)
}
#[cfg(target_os = "windows")]
{
let fd: i64 = file_descriptor.value("handle")?.to_long()?;
let fd: i64 = file_descriptor.value("handle")?.try_into()?;
fd
}
} else {
let fd = file_descriptor.value("fd")?.to_int()?;
let fd: i32 = file_descriptor.value("fd")?.try_into()?;
i64::from(fd)
};
Ok(fd)
Expand Down
4 changes: 2 additions & 2 deletions ristretto_vm/src/intrinsic_methods/java/io/unixfilesystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1049,7 +1049,7 @@ mod tests {
let mut parameters = Parameters::default();
parameters.push(file_object);
let value = list(thread, parameters).await?.expect("paths");
let reference = value.to_reference()?.expect("paths");
let reference: Reference = value.try_into()?;
let class_name = reference.class_name().to_string();
let elements: Vec<Value> = reference.try_into()?;
assert_eq!(class_name, "java/lang/String");
Expand All @@ -1067,7 +1067,7 @@ mod tests {
let mut parameters = Parameters::default();
parameters.push(file_object);
let value = list_0(thread, parameters).await?.expect("paths");
let reference = value.to_reference()?.expect("paths");
let reference: Reference = value.clone().try_into()?;
let class_name = reference.class_name().to_string();
let elements: Vec<Value> = value.try_into()?;
assert_eq!(class_name, "java/lang/String");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ mod tests {
use super::*;
use crate::JavaError::RuntimeException;
use crate::JavaObject;
use ristretto_classloader::Reference;
use std::path::Path;
use tempfile::NamedTempFile;

Expand Down Expand Up @@ -491,7 +492,7 @@ mod tests {
let mut parameters = Parameters::default();
parameters.push(file_object);
let value = list(thread, parameters).await?.expect("paths");
let reference = value.to_reference()?.expect("paths");
let reference: Reference = value.clone().try_into()?;
let class_name = reference.class_name().to_string();
let elements: Vec<Value> = value.try_into()?;
assert_eq!(class_name, "java/lang/String");
Expand Down
10 changes: 5 additions & 5 deletions ristretto_vm/src/intrinsic_methods/java/lang/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1186,7 +1186,7 @@ mod tests {
let value = get_declared_classes_0(thread, parameters)
.await?
.expect("interfaces");
let reference = value.to_reference()?.expect("interfaces");
let reference: Reference = value.try_into()?;
let class_name = reference.class_name().to_string();
let values: Vec<Value> = reference.try_into()?;
assert_eq!(class_name, "[Ljava/lang/Class;");
Expand All @@ -1213,7 +1213,7 @@ mod tests {
let value = get_declared_constructors_0(thread, parameters)
.await?
.expect("constructors");
let reference = value.to_reference()?.expect("constructors");
let reference: Reference = value.try_into()?;
let class_name = reference.class_name().to_string();
let values: Vec<Value> = reference.try_into()?;
assert_eq!(class_name, "[Ljava/lang/reflect/Constructor;");
Expand Down Expand Up @@ -1253,7 +1253,7 @@ mod tests {
let value = get_declared_fields_0(thread, parameters)
.await?
.expect("fields");
let reference = value.to_reference()?.expect("fields");
let reference: Reference = value.try_into()?;
let class_name = reference.class_name().to_string();
let values: Vec<Value> = reference.try_into()?;
assert_eq!(class_name, "[Ljava/lang/reflect/Field;");
Expand Down Expand Up @@ -1297,7 +1297,7 @@ mod tests {
let value = get_declared_methods_0(thread, parameters)
.await?
.expect("methods");
let reference = value.to_reference()?.expect("methods");
let reference: Reference = value.try_into()?;
let class_name = reference.class_name().to_string();
let values: Vec<Value> = reference.try_into()?;
assert_eq!(class_name, "[Ljava/lang/reflect/Method;");
Expand Down Expand Up @@ -1438,7 +1438,7 @@ mod tests {
let value = get_interfaces_0(thread, parameters)
.await?
.expect("interfaces");
let reference = value.to_reference()?.expect("interfaces");
let reference: Reference = value.try_into()?;
let class_name = reference.class_name().to_string();
let values: Vec<Value> = reference.try_into()?;
assert_eq!(class_name, "[Ljava/lang/Class;");
Expand Down
Loading
Loading