Skip to content

Commit

Permalink
Implement PyMemory::get_range_as_ints(). (#147)
Browse files Browse the repository at this point in the history
  • Loading branch information
azteca1998 authored Nov 17, 2022
1 parent de9cb2b commit 29704a5
Showing 1 changed file with 115 additions and 1 deletion.
116 changes: 115 additions & 1 deletion src/memory.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
use crate::{
relocatable::{PyMaybeRelocatable, PyRelocatable},
utils::to_py_error,
vm_core::PyVM,
};
use cairo_rs::{
types::relocatable::{MaybeRelocatable, Relocatable},
vm::vm_core::VirtualMachine,
};
use num_bigint::BigInt;
use pyo3::{
exceptions::{PyTypeError, PyValueError},
prelude::*,
};
use std::{cell::RefCell, rc::Rc};
use std::{borrow::Cow, cell::RefCell, rc::Rc};

const MEMORY_GET_ERROR_MSG: &str = "Failed to get value from Cairo memory";
const MEMORY_SET_ERROR_MSG: &str = "Failed to set value to Cairo memory";
Expand Down Expand Up @@ -69,6 +71,18 @@ impl PyMemory {
.collect::<Vec<PyMaybeRelocatable>>()
.to_object(py))
}

/// Return a continuous section of memory as a vector of integers.
pub fn get_range_as_ints(&self, addr: PyRelocatable, size: usize) -> PyResult<Vec<BigInt>> {
Ok(self
.vm
.borrow()
.get_integer_range(&Relocatable::from(&addr), size)
.map_err(to_py_error)?
.into_iter()
.map(Cow::into_owned)
.collect())
}
}

#[cfg(test)]
Expand Down Expand Up @@ -282,4 +296,104 @@ assert memory[ap] == fp
assert_eq!(range.unwrap_err(), expected_error);
});
}

// Test that get_range_as_ints() works as intended.
#[test]
fn get_range_as_ints() {
let vm = PyVM::new(
BigInt::new(Sign::Plus, vec![1, 0, 0, 0, 0, 0, 17, 134217728]),
false,
);
let memory = PyMemory::new(&vm);

let addr = {
let mut vm = vm.vm.borrow_mut();
let addr = vm.add_memory_segment();

vm.load_data(
&MaybeRelocatable::from(&addr),
vec![
bigint!(1).into(),
bigint!(2).into(),
bigint!(3).into(),
bigint!(4).into(),
],
)
.expect("memory insertion failed");

addr
};

assert_eq!(
memory
.get_range_as_ints(addr.into(), 4)
.expect("get_range_as_ints() failed"),
vec![bigint!(1), bigint!(2), bigint!(3), bigint!(4)],
);
}

// Test that get_range_as_ints() fails when not all values are integers.
#[test]
fn get_range_as_ints_mixed() {
let vm = PyVM::new(
BigInt::new(Sign::Plus, vec![1, 0, 0, 0, 0, 0, 17, 134217728]),
false,
);
let memory = PyMemory::new(&vm);

let addr = {
let mut vm = vm.vm.borrow_mut();
let addr = vm.add_memory_segment();

vm.load_data(
&MaybeRelocatable::from(&addr),
vec![
bigint!(1).into(),
bigint!(2).into(),
MaybeRelocatable::RelocatableValue((1, 2).into()),
bigint!(4).into(),
],
)
.expect("memory insertion failed");

addr
};

memory
.get_range_as_ints(addr.into(), 4)
.expect_err("get_range_as_ints() succeeded (should have failed)");
}

// Test that get_range_as_ints() fails when the requested range is larger than the available
// segments.
#[test]
fn get_range_as_ints_incomplete() {
let vm = PyVM::new(
BigInt::new(Sign::Plus, vec![1, 0, 0, 0, 0, 0, 17, 134217728]),
false,
);
let memory = PyMemory::new(&vm);

let addr = {
let mut vm = vm.vm.borrow_mut();
let addr = vm.add_memory_segment();

vm.load_data(
&MaybeRelocatable::from(&addr),
vec![
bigint!(1).into(),
bigint!(2).into(),
bigint!(3).into(),
bigint!(4).into(),
],
)
.expect("memory insertion failed");

addr
};

memory
.get_range_as_ints(addr.into(), 8)
.expect_err("get_range_as_ints() succeeded (should have failed)");
}
}

0 comments on commit 29704a5

Please sign in to comment.