Skip to content

Commit

Permalink
Add support for arrays casting
Browse files Browse the repository at this point in the history
  • Loading branch information
hextriclosan committed Dec 18, 2024
1 parent df2118b commit a60ef78
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 3 deletions.
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ It features abstract classes, interfaces, and polymorphism to demonstrate the ca
package game;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Demo {
Expand Down Expand Up @@ -86,9 +87,7 @@ class DarkTemplar extends AbstractUnit {
class ControlGroup implements Unit {
private final List<Unit> units = new ArrayList<>();
public void addUnits(Unit... units) {
for (Unit unit : units) {
this.units.add(unit);
}
this.units.addAll(Arrays.asList(units));
}
@Override
public int damage() {
Expand Down
11 changes: 11 additions & 0 deletions tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -570,3 +570,14 @@ fn should_support_returning_interface_from_static_method() {
"[some string]\n",
);
}

#[test]
fn should_cast_arrays_when_possible() {
assert_success(
"samples.javacore.cast.arrays.ArrayCastExample",
r#"[Ljava.lang.String;
[I
HelloWorld!
"#,
);
}
20 changes: 20 additions & 0 deletions tests/test_data/ArrayCastExample.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package samples.javacore.cast.arrays;

import static java.lang.String.valueOf;

public class ArrayCastExample {
public static void main(String[] args) {
int[] ints = new int[] {1, 2, 3};
String[] strings = new String[] {"Hello", "World", "!"};
Object stringsObject = strings;
System.out.println(valueOf(stringsObject).substring(0, 19));
Object intsObject = ints;
System.out.println(valueOf(intsObject).substring(0, 2));

Object[] objects = (Object[]) stringsObject;
for (Object o : objects) {
System.out.print(o);
}
System.out.println();
}
}
Binary file not shown.
21 changes: 21 additions & 0 deletions vm/src/method_area/instance_checker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ pub(crate) struct InstanceChecker {}

impl InstanceChecker {
pub fn checkcast(class_cast_from: &str, class_cast_to: &str) -> crate::error::Result<bool> {
let (class_cast_from, class_cast_to) =
Self::try_unwrap_arrays(class_cast_from, class_cast_to);

if let Some(base_of) = Self::is_base_of(class_cast_to, class_cast_from) {
return Ok(base_of);
}
Expand All @@ -15,6 +18,24 @@ impl InstanceChecker {
Ok(false)
}

fn try_unwrap_arrays<'a>(first: &'a str, second: &'a str) -> (&'a str, &'a str) {
fn unwrap_descriptor(descr: &str) -> &str {
if descr.starts_with('L') {
&descr[1..descr.len() - 1]
} else {
descr
}
}

if first.starts_with('[') && first.starts_with('[') {
Self::try_unwrap_arrays(&first[1..], &second[1..])
} else {
let first = unwrap_descriptor(first);
let second = unwrap_descriptor(second);
(first, second)
}
}

fn is_base_of(base: &str, child: &str) -> Option<bool> {
if base == child {
return Some(true);
Expand Down

0 comments on commit a60ef78

Please sign in to comment.