use num_bigint_dig::BigInt;
use std::fmt::{Display, Formatter};
pub enum TypeInvalidAccess{
MissingInputs(String),
MissingInputTags(String),
NoInitializedComponent,
NoInitializedSignal
}
pub enum TypeAssignmentError{
MultipleAssignments,
AssignmentOutput
}
pub enum MemoryError {
OutOfBoundsError,
AssignmentError(TypeAssignmentError),
InvalidAccess(TypeInvalidAccess),
UnknownSizeDimension,
MismatchedDimensions(usize, usize),
MismatchedDimensionsWeak(usize, usize),
AssignmentMissingTags(String),
AssignmentTagAfterInit,
AssignmentTagTwice,
AssignmentTagInput,
TagValueNotInitializedAccess,
MissingInputs(String)
}
pub type SliceCapacity = usize;
pub type SimpleSlice = MemorySlice<BigInt>;
#[derive(Eq, PartialEq)]
pub struct MemorySlice<C> {
route: Vec<SliceCapacity>,
values: Vec<C>,
}
impl<C: Clone> Clone for MemorySlice<C> {
fn clone(&self) -> Self {
MemorySlice { route: self.route.clone(), values: self.values.clone() }
}
}
impl<C: Default + Clone + Display + Eq> Display for MemorySlice<C> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
if self.values.is_empty() {
f.write_str("[]")
} else if self.values.len() == 1 {
f.write_str(&format!("{}", self.values[0]))
} else {
let mut msg = format!("[{}", self.values[0]);
for i in 1..self.values.len() {
msg.push_str(&format!(",{}", self.values[i]));
}
msg.push_str("]");
f.write_str(&msg)
}
}
}
impl<C: Clone> MemorySlice<C> {
fn get_initial_cell(
memory_slice: &MemorySlice<C>,
access: &[SliceCapacity],
) -> Result<SliceCapacity, MemoryError> {
if access.len() > memory_slice.route.len() {
return Result::Err(MemoryError::OutOfBoundsError);
}
let mut cell = 0;
let mut cell_jump = memory_slice.values.len();
let mut i: SliceCapacity = 0;
while i < access.len() {
if access[i] >= memory_slice.route[i] {
return Result::Err(MemoryError::OutOfBoundsError);
}
cell_jump /= memory_slice.route[i];
cell += cell_jump * access[i];
i += 1;
}
Result::Ok(cell)
}
pub fn check_correct_dims(
memory_slice: &MemorySlice<C>,
access: &[SliceCapacity],
new_values: &MemorySlice<C>,
is_strict: bool,
) -> Result<(), MemoryError> {
if access.len() + new_values.route.len() > memory_slice.route.len() {
return Result::Err(MemoryError::OutOfBoundsError);
}
let mut i: SliceCapacity = 0;
while i < access.len() {
if access[i] >= memory_slice.route[i] {
return Result::Err(MemoryError::OutOfBoundsError);
}
i += 1;
}
let initial_index_new: SliceCapacity = i;
i = 0;
while i < new_values.route.len() {
if new_values.route[i] < memory_slice.route[initial_index_new + i] {
if is_strict{ return Result::Err(MemoryError::MismatchedDimensions(new_values.route[i], memory_slice.route[initial_index_new + i]));
} else{ return Result::Err(MemoryError::MismatchedDimensionsWeak(new_values.route[i], memory_slice.route[initial_index_new + i]));
}
}
if new_values.route[i] > memory_slice.route[initial_index_new + i] {
return Result::Err(MemoryError::MismatchedDimensions(new_values.route[i], memory_slice.route[initial_index_new + i]));
}
i += 1;
}
Result::Ok(())
}
fn generate_new_route_from_access(
memory_slice: &MemorySlice<C>,
access: &[SliceCapacity],
) -> Result<(Vec<SliceCapacity>, SliceCapacity), MemoryError> {
if access.len() > memory_slice.route.len() {
return Result::Err(MemoryError::OutOfBoundsError);
}
let mut size = Vec::new();
let mut number_of_cells = 1;
for i in access.len()..memory_slice.route.len() {
number_of_cells *= memory_slice.route[i];
size.push(memory_slice.route[i]);
}
Result::Ok((size, number_of_cells))
}
fn generate_slice_from_access(
memory_slice: &MemorySlice<C>,
access: &[SliceCapacity],
) -> Result<MemorySlice<C>, MemoryError> {
if access.is_empty() {
return Result::Ok(memory_slice.clone());
}
let (size, number_of_cells) =
MemorySlice::generate_new_route_from_access(memory_slice, access)?;
let mut values = Vec::with_capacity(number_of_cells);
let initial_cell = MemorySlice::get_initial_cell(memory_slice, access)?;
let mut offset = 0;
while offset < number_of_cells {
let new_value = memory_slice.values[initial_cell + offset].clone();
values.push(new_value);
offset += 1;
}
Result::Ok(MemorySlice { route: size, values })
}
pub fn new(initial_value: &C) -> MemorySlice<C> {
MemorySlice::new_with_route(&[], initial_value)
}
pub fn new_array(route: Vec<SliceCapacity>, values: Vec<C>) -> MemorySlice<C> {
MemorySlice { route, values }
}
pub fn new_with_route(route: &[SliceCapacity], initial_value: &C) -> MemorySlice<C> {
let mut length = 1;
for i in route {
length *= *i;
}
let mut values = Vec::with_capacity(length);
for _i in 0..length {
values.push(initial_value.clone());
}
MemorySlice { route: route.to_vec(), values }
}
pub fn insert_values(
memory_slice: &mut MemorySlice<C>,
access: &[SliceCapacity],
new_values: &MemorySlice<C>,
is_strict:bool,
) -> Result<(), MemoryError> {
match MemorySlice::check_correct_dims(memory_slice, access, new_values, is_strict){
Result::Ok(_) => {
let mut cell = MemorySlice::get_initial_cell(memory_slice, access)?;
for value in new_values.values.iter() {
memory_slice.values[cell] = value.clone();
cell += 1;
}
Result::Ok(())
},
Result::Err(MemoryError::MismatchedDimensionsWeak(dim_1, dim_2)) => {
let mut cell = MemorySlice::get_initial_cell(memory_slice, access)?;
for value in new_values.values.iter() {
memory_slice.values[cell] = value.clone();
cell += 1;
}
Result::Err(MemoryError::MismatchedDimensionsWeak(dim_1, dim_2))
},
Result::Err(error) => return Err(error),
}
}
pub fn insert_value_by_index(
memory_slice: &mut MemorySlice<C>,
index: usize,
new_value: C,
)-> Result<(), MemoryError> {
if index > MemorySlice::get_number_of_cells(memory_slice) {
return Result::Err(MemoryError::OutOfBoundsError);
}
memory_slice.values[index] = new_value;
return Result::Ok(());
}
pub fn get_access_index(
memory_slice: &MemorySlice<C>,
index: usize,
) -> Result<Vec<SliceCapacity>, MemoryError>{
let mut number_cells = MemorySlice::get_number_of_cells(memory_slice);
if index > number_cells {
return Result::Err(MemoryError::OutOfBoundsError);
}
else{
let mut access = vec![];
let mut index_aux = index;
for pos in &memory_slice.route{
number_cells = number_cells/pos;
access.push(index_aux / number_cells);
index_aux = index_aux % number_cells;
}
return Result::Ok(access);
}
}
pub fn access_values(
memory_slice: &MemorySlice<C>,
access: &[SliceCapacity],
) -> Result<MemorySlice<C>, MemoryError> {
MemorySlice::generate_slice_from_access(memory_slice, access)
}
pub fn access_value_by_index(
memory_slice: &MemorySlice<C>,
index: usize,
)-> Result<C, MemoryError> {
if index > MemorySlice::get_number_of_cells(memory_slice) {
return Result::Err(MemoryError::OutOfBoundsError);
}
return Result::Ok(memory_slice.values[index].clone());
}
pub fn get_reference_to_single_value<'a>(
memory_slice: &'a MemorySlice<C>,
access: &[SliceCapacity],
) -> Result<&'a C, MemoryError> {
assert_eq!(memory_slice.route.len(), access.len());
let cell = MemorySlice::get_initial_cell(memory_slice, access)?;
Result::Ok(&memory_slice.values[cell])
}
pub fn get_reference_to_single_value_by_index<'a>(
memory_slice: &'a MemorySlice<C>,
index: usize,
) -> Result<&'a C, MemoryError> {
if index > MemorySlice::get_number_of_cells(memory_slice) {
return Result::Err(MemoryError::OutOfBoundsError);
}
Result::Ok(&memory_slice.values[index])
}
pub fn get_reference_to_single_value_by_index_or_break<'a>(
memory_slice: &'a MemorySlice<C>,
index: usize,
) -> &'a C {
if index > MemorySlice::get_number_of_cells(memory_slice) {
unreachable!("The index is too big for the slice");
}
&memory_slice.values[index]
}
pub fn get_mut_reference_to_single_value<'a>(
memory_slice: &'a mut MemorySlice<C>,
access: &[SliceCapacity],
) -> Result<&'a mut C, MemoryError> {
assert_eq!(memory_slice.route.len(), access.len());
let cell = MemorySlice::get_initial_cell(memory_slice, access)?;
Result::Ok(&mut memory_slice.values[cell])
}
pub fn get_number_of_cells(memory_slice: &MemorySlice<C>) -> SliceCapacity {
memory_slice.values.len()
}
pub fn route(&self) -> &[SliceCapacity] {
&self.route
}
pub fn is_single(&self) -> bool {
self.route.is_empty()
}
pub fn unwrap_to_single(memory_slice: MemorySlice<C>) -> C {
assert!(memory_slice.is_single());
let mut memory_slice = memory_slice;
memory_slice.values.pop().unwrap()
}
pub fn destruct(self) -> (Vec<SliceCapacity>, Vec<C>) {
(self.route, self.values)
}
}
#[cfg(test)]
mod tests {
use super::*;
type U32Slice = MemorySlice<u32>;
#[test]
fn memory_slice_vector_initialization() {
let route = vec![3, 4];
let slice = U32Slice::new_with_route(&route, &0);
assert_eq!(U32Slice::get_number_of_cells(&slice), 12);
for (dim_0, dim_1) in slice.route.iter().zip(&route) {
assert_eq!(*dim_0, *dim_1);
}
for f in 0..3 {
for c in 0..4 {
let result = U32Slice::get_reference_to_single_value(&slice, &[f, c]);
if let Result::Ok(v) = result {
assert_eq!(*v, 0);
} else {
assert!(false);
}
}
}
}
#[test]
fn memory_slice_single_initialization() {
let slice = U32Slice::new(&4);
assert_eq!(U32Slice::get_number_of_cells(&slice), 1);
let memory_response = U32Slice::get_reference_to_single_value(&slice, &[]);
if let Result::Ok(val) = memory_response {
assert_eq!(*val, 4);
} else {
assert!(false);
}
}
#[test]
fn memory_slice_multiple_insertion() {
let route = vec![3, 4];
let mut slice = U32Slice::new_with_route(&route, &0);
let new_row = U32Slice::new_with_route(&[4], &4);
let res = U32Slice::insert_values(&mut slice, &[2], &new_row);
if let Result::Ok(_) = res {
for c in 0..4 {
let memory_result = U32Slice::get_reference_to_single_value(&slice, &[2, c]);
if let Result::Ok(val) = memory_result {
assert_eq!(*val, 4);
} else {
assert!(false);
}
}
} else {
assert!(false);
}
}
}