#[cfg(test)]
mod tests {
#[test]
fn test_simple_array_subscript_read() {
let c_code = r#"
int x = arr[i];
"#;
let rust_expected = r#"
let x = arr[i];
"#;
assert!(c_code.contains("arr[i]"));
assert!(rust_expected.contains("arr[i]"));
}
#[test]
fn test_array_subscript_write() {
let c_code = r#"
arr[i] = 42;
"#;
let rust_expected = r#"
arr[i] = 42;
"#;
assert!(c_code.contains("arr[i] = 42"));
assert!(rust_expected.contains("arr[i] = 42"));
}
#[test]
fn test_array_subscript_constant() {
let c_code = r#"
int first = arr[0];
int last = arr[9];
"#;
let rust_expected = r#"
let first = arr[0];
let last = arr[9];
"#;
assert!(c_code.contains("arr[0]"));
assert!(c_code.contains("arr[9]"));
assert!(rust_expected.contains("arr[0]"));
assert!(rust_expected.contains("arr[9]"));
}
#[test]
fn test_array_subscript_in_expression() {
let c_code = r#"
int sum = arr[i] + arr[j];
"#;
let rust_expected = r#"
let sum = arr[i] + arr[j];
"#;
assert!(c_code.contains("arr[i] + arr[j]"));
assert!(rust_expected.contains("arr[i] + arr[j]"));
}
#[test]
fn test_multidimensional_array() {
let c_code = r#"
int val = matrix[i][j];
matrix[i][j] = 42;
"#;
let rust_expected = r#"
let val = matrix[i][j];
matrix[i][j] = 42;
"#;
assert!(c_code.contains("matrix[i][j]"));
assert!(rust_expected.contains("matrix[i][j]"));
}
#[test]
fn test_array_subscript_expression_index() {
let c_code = r#"
int x = arr[i + 1];
int y = arr[i * 2];
"#;
let rust_expected = r#"
let x = arr[i + 1];
let y = arr[i * 2];
"#;
assert!(c_code.contains("arr[i + 1]"));
assert!(c_code.contains("arr[i * 2]"));
assert!(rust_expected.contains("arr[i + 1]"));
assert!(rust_expected.contains("arr[i * 2]"));
}
#[test]
fn test_array_subscript_in_loop() {
let c_code = r#"
for (int i = 0; i < n; i++) {
sum += arr[i];
}
"#;
let rust_expected = r#"
for i in 0..n {
sum += arr[i];
}
"#;
assert!(c_code.contains("arr[i]"));
assert!(rust_expected.contains("arr[i]"));
}
#[test]
fn test_pointer_subscript() {
let c_code = r#"
int* p = arr;
int x = p[i];
"#;
let _rust_expected = r#"
let p = &arr[0];
let x = arr[i]; // Or use slice
"#;
assert!(c_code.contains("p[i]"));
}
#[test]
fn test_safe_array_access() {
let c_code = r#"
if (i >= 0 && i < len) {
x = arr[i];
}
"#;
let rust_expected = r#"
if let Some(&x) = arr.get(i) {
// Use x safely
}
"#;
assert!(c_code.contains("i < len"));
assert!(rust_expected.contains("arr.get(i)"));
}
#[test]
fn test_array_slicing() {
let c_note = "C has no direct slice syntax, use pointers";
let rust_code = r#"
let slice = &arr[2..5]; // Elements [2, 3, 4]
let slice_from = &arr[2..]; // From index 2 to end
let slice_to = &arr[..5]; // From start to index 5 (exclusive)
"#;
assert!(c_note.contains("no direct"));
assert!(rust_code.contains("&arr[2..5]"));
assert!(rust_code.contains("&arr[2..]"));
assert!(rust_code.contains("&arr[..5]"));
}
#[test]
fn test_array_subscript_modulo() {
let c_code = r#"
int x = arr[i % size];
"#;
let rust_expected = r#"
let x = arr[i % size];
"#;
assert!(c_code.contains("arr[i % size]"));
assert!(rust_expected.contains("arr[i % size]"));
}
#[test]
fn test_nested_array_different_indices() {
let c_code = r#"
int val = table[row][col];
"#;
let rust_expected = r#"
let val = table[row][col];
"#;
assert!(c_code.contains("table[row][col]"));
assert!(rust_expected.contains("table[row][col]"));
}
#[test]
fn test_array_subscript_with_increment() {
let c_code = r#"
int x = arr[i++];
"#;
let rust_expected = r#"
let x = arr[i];
i += 1;
"#;
assert!(c_code.contains("arr[i++]"));
assert!(rust_expected.contains("arr[i]"));
assert!(rust_expected.contains("i += 1"));
}
#[test]
fn test_array_bounds_checking() {
let c_note = "C: No bounds checking, undefined behavior";
let rust_note = r#"
// Rust: Bounds checked in debug mode
let arr = [1, 2, 3];
// let x = arr[10]; // PANIC in debug, UB in release
let x = arr.get(10); // Returns None (safe)
"#;
assert!(c_note.contains("No bounds"));
assert!(rust_note.contains("PANIC in debug"));
assert!(rust_note.contains("get(10)"));
}
#[test]
fn test_array_in_struct() {
let c_code = r#"
struct Data {
int values[10];
};
struct Data d;
int x = d.values[i];
"#;
let rust_expected = r#"
struct Data {
values: [i32; 10],
}
let d = Data { values: [0; 10] };
let x = d.values[i];
"#;
assert!(c_code.contains("d.values[i]"));
assert!(rust_expected.contains("d.values[i]"));
}
#[test]
fn test_array_subscripting_summary() {
let c_code = r#"
// Rule 1: Simple subscript (same)
int x = arr[i];
// Rule 2: Assignment (same)
arr[i] = 42;
// Rule 3: Constant index (same)
int first = arr[0];
// Rule 4: In expression (same)
int sum = arr[i] + arr[j];
// Rule 5: Multi-dimensional (same)
int val = matrix[i][j];
// Rule 6: Expression index (same)
int x = arr[i + 1];
// Rule 7: In loop (same)
for (int i = 0; i < n; i++) { sum += arr[i]; }
// Rule 8: Pointer subscript (same syntax)
int* p = arr; int x = p[i];
// Rule 9: Manual bounds check
if (i < len) { x = arr[i]; }
// Rule 10: No slice syntax in C
// Rule 11: Modulo (same)
int x = arr[i % size];
// Rule 12: 2D different indices (same)
int val = table[row][col];
// Rule 13: Post-increment in subscript
int x = arr[i++];
"#;
let rust_expected = r#"
// Rule 1: Same
let x = arr[i];
// Rule 2: Same
arr[i] = 42;
// Rule 3: Same
let first = arr[0];
// Rule 4: Same
let sum = arr[i] + arr[j];
// Rule 5: Same
let val = matrix[i][j];
// Rule 6: Same
let x = arr[i + 1];
// Rule 7: Same pattern
for i in 0..n { sum += arr[i]; }
// Rule 8: Prefer array/slice
let p = &arr[..]; let x = p[i];
// Rule 9: Use get() method
if let Some(&x) = arr.get(i) { }
// Rule 10: Slice syntax
let slice = &arr[2..5];
// Rule 11: Same
let x = arr[i % size];
// Rule 12: Same
let val = table[row][col];
// Rule 13: Separate statements
let x = arr[i]; i += 1;
"#;
assert!(c_code.contains("arr[i]"));
assert!(rust_expected.contains("arr[i]"));
assert!(c_code.contains("matrix[i][j]"));
assert!(rust_expected.contains("matrix[i][j]"));
assert!(c_code.contains("arr[i++]"));
assert!(rust_expected.contains("let x = arr[i]; i += 1"));
assert!(rust_expected.contains("arr.get(i)"));
assert!(rust_expected.contains("&arr[2..5]"));
}
}