#![allow(dead_code)]
use super::util;
use std::cell::Cell;
use std::fmt::Debug;
use std::str::FromStr;
pub trait GridMeta {
fn get_dimensions(&self) -> &[usize];
}
#[derive(Default, Clone, Debug)]
pub struct GridDataType<CellDataType: Clone + util::Encodeable> {
pub data: Vec<util::NanoVec<CellDataType>>,
pub dimensions: Vec<usize>,
}
#[derive(Clone)]
pub struct NeighborType<'a, CellDataType: Clone + util::Encodeable> {
pub data: Vec<&'a util::NanoVec<CellDataType>>,
pub dimensions: &'a [usize],
}
pub type TransitionFunc<CellDataType, MetaDataType > =
dyn Fn(&mut util::NanoVec<CellDataType>, &NeighborType<CellDataType>, &MetaDataType) -> ();
pub type NeighborFuncParser<CellDataType, MetaDataType > =
dyn for<'a> Fn(
&'a GridDataType<CellDataType>,
&'a MetaDataType,
usize,
) -> NeighborType<'a, CellDataType>;
pub type HaltFunc<CellType> = Fn(&GridDataType<CellType>) -> bool;
#[derive(Debug)]
pub struct Grid<
CellDataType: 'static + Clone + util::Newable + util::Parseable + util::Encodeable + Debug,
MetaDataType: 'static + Clone + util::Newable + util::Parseable + GridMeta,
> {
direction: Cell<bool>,
data_a: GridDataType<CellDataType>,
data_b: GridDataType<CellDataType>,
meta: MetaDataType,
pub dimensions: Vec<usize>,
}
impl<
CellDataType: 'static + Clone + util::Newable + util::Parseable + util::Encodeable + Debug,
MetaDataType: 'static + Clone + util::Newable + util::Parseable + GridMeta,
> Default for Grid<CellDataType, MetaDataType>
{
fn default() -> Self {
Self::new()
}
}
impl<
CellDataType: 'static + Clone + util::Newable + util::Parseable + util::Encodeable + Debug,
MetaDataType: 'static + Clone + util::Newable + util::Parseable + GridMeta,
> Grid<CellDataType, MetaDataType>
{
pub fn new() -> Self {
let temp_grid_data: GridDataType<CellDataType> = GridDataType {
data: Vec::new(),
dimensions: Vec::new(),
};
Self {
data_a: temp_grid_data.clone(),
data_b: temp_grid_data.clone(),
direction: Cell::new(true),
meta: util::Newable::new(),
dimensions: Vec::new(),
}
}
pub fn get_data_read(&self) -> &GridDataType<CellDataType> {
if self.direction.get() {
&self.data_a
} else {
&self.data_b
}
}
pub fn get_data_mut(&mut self) -> &mut GridDataType<CellDataType> {
if self.direction.get() {
&mut self.data_b
} else {
&mut self.data_a
}
}
pub fn get_data_tuple(
&mut self,
) -> (&mut GridDataType<CellDataType>, &GridDataType<CellDataType>) {
if self.direction.get() {
(&mut self.data_b, &self.data_a)
} else {
(&mut self.data_a, &self.data_b)
}
}
pub fn get_meta(&self) -> &MetaDataType {
&self.meta
}
pub fn read_from_str(&mut self, data: &str) {
*self = Self::decode(data);
}
pub fn decode(input: &str) -> Self {
let split: Vec<String> = util::parse_table_sections(input); if split.len() != 2 {
println!("ERROR - malformed input file.");
panic!("ERROR - malformed input file.");
}
let meta_data_str: &str = &split[0];
let meta_data: MetaDataType = util::Parseable::parse(meta_data_str);
let dimensions_vec = meta_data.get_dimensions().to_vec();
let data: Vec<util::NanoVec<CellDataType>> = {
let tmp = util::split_str(&split[1], ';');
let mut to_return: Vec<util::NanoVec<CellDataType>> = Vec::new();
for item in tmp {
let split = util::parse_csv_list(item, ',');
to_return.push(util::NanoVec::from_slice(split.as_slice()));
}
to_return
};
let generated_data: GridDataType<CellDataType> =
GridDataType::from_data(&data, &dimensions_vec);
Self {
data_a: generated_data.clone(),
data_b: generated_data.clone(),
direction: Cell::new(false),
meta: meta_data,
dimensions: dimensions_vec,
}
}
#[inline]
pub fn apply(
&mut self,
transition: &TransitionFunc<CellDataType, MetaDataType>,
neighbor_parser: &NeighborFuncParser<CellDataType, MetaDataType>,
meta: &MetaDataType,
) {
let (active_data, to_read) = self.get_data_tuple();
let to_modify_data = active_data.get_data_mut_ref();
for (j, item) in to_modify_data.iter_mut().enumerate() {
transition(item, &neighbor_parser(to_read, meta, j), meta);
}
self.direction.set(!self.direction.get());
}
}
pub struct ParseGridError {}
impl<
CellDataType: 'static + Clone + util::Newable + util::Parseable + util::Encodeable + Debug,
MetaDataType: 'static + Clone + util::Newable + util::Parseable + GridMeta,
> FromStr for Grid<CellDataType, MetaDataType>
{
type Err = ParseGridError;
fn from_str(data: &str) -> Result<Self, Self::Err> {
let mut temp = Self::new();
temp.read_from_str(data);
Ok(temp)
}
}
impl<CellDataType: Clone + util::Encodeable> std::fmt::Display for GridDataType<CellDataType> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let dimensions = &self.dimensions;
if dimensions.len() == 2 {
let mut the_str = String::new();
let mut old_len = self.data.len();
let sizes = dimensions
.iter()
.map(|&x| {
old_len /= x;
old_len
})
.collect::<Vec<usize>>();
for (j, item) in self.data.iter().enumerate() {
if j % sizes[1] == 0 {
the_str += "\n";
the_str += &util::Encodeable::encode(item);
if j != self.data.len() - 1 {
the_str += ",";
}
} else {
the_str += &util::Encodeable::encode(item);
the_str += ",";
}
}
write!(f, "{}", the_str)
} else {
let mut the_str = String::new();
for (j, item) in self.data.iter().enumerate() {
if j == self.data.len() - 1 {
the_str += &util::Encodeable::encode(item);
} else {
the_str += &util::Encodeable::encode(item);
the_str += ",";
}
}
write!(f, "{}", the_str)
}
}
}
impl<CellDataType: Clone + util::Encodeable> GridDataType<CellDataType> {
pub fn new() -> Self {
Self {
data: Vec::new(),
dimensions: Vec::new(),
}
}
pub fn from_data(data: &[util::NanoVec<CellDataType>], dims: &[usize]) -> Self {
Self {
data: data.to_vec(),
dimensions: dims.to_vec(),
}
}
pub fn get_data_ref(&self) -> &Vec<util::NanoVec<CellDataType>> {
&self.data
}
pub fn get_data_mut_ref(&mut self) -> &mut Vec<util::NanoVec<CellDataType>> {
&mut self.data
}
pub fn get_data_mut_slice(&mut self) -> &mut [util::NanoVec<CellDataType>] {
self.data.as_mut_slice()
}
pub fn get_data_copy(&self) -> Vec<util::NanoVec<CellDataType>> {
self.data.clone()
}
pub fn get_mut_references(
&mut self,
num_chunks: usize,
) -> Vec<Option<&mut [util::NanoVec<CellDataType>]>> {
let mut to_return: Vec<Option<&mut [util::NanoVec<CellDataType>]>> = Vec::new();
let data_length = self.get_data_ref().len();
let chunk_size = data_length / num_chunks;
let mut previous = self.get_data_mut_ref().as_mut_slice();
for _ in 0..num_chunks - 1 {
let cut = previous.split_at_mut(chunk_size);
to_return.push(Some(cut.0));
previous = cut.1;
}
to_return.push(Some(previous));
to_return
}
}
impl<'a, CellDataType: Clone + util::Encodeable> NeighborType<'a, CellDataType> {
pub fn new(
data: Vec<&'a util::NanoVec<CellDataType>>,
dimensions: &'a [usize],
) -> NeighborType<'a, CellDataType> {
NeighborType { data, dimensions }
}
pub fn get_data(&self) -> Vec<&'a util::NanoVec<CellDataType>> {
self.data.clone()
}
pub fn get_data_ref(&self) -> &Vec<&'a util::NanoVec<CellDataType>> {
&self.data
}
}