use std::fmt;
use std::ops::Add;
pub trait Newable {
fn new() -> Self;
}
pub trait Parseable {
fn parse(_: &str) -> Self;
}
pub trait Encodeable {
fn encode(&self) -> String;
}
pub trait Equalable {
fn equals(&self, _: &Self) -> bool;
}
pub trait Hashable {
fn hash(&self) -> usize;
}
#[macro_export]
macro_rules! debug_passed {
($x:expr) => {
#[cfg(debug_assertions)]
{
println!(
"Program execution passed checkpoint <{}>, in file <{}> line <{}>",
$x,
file!(),
line!()
)
}
};
}
#[macro_export]
macro_rules! debug_val {
($val:expr) => {
#[cfg(debug_assertions)]
{
match $val {
tmp => {
println!(
"<{}> <{}> {} = {:#?}",
file!(),
line!(),
stringify!($val),
&tmp
);
tmp
}
}
}
};
}
#[macro_export]
macro_rules! debug_emit {
($val:expr) => {
#[cfg(debug_assertions)]
{
println!("<{}> <{}>, {}", file!(), line!(), $val)
};
};
}
#[derive(Clone, Copy, Debug)]
pub struct TwoTuple<DataTypeA: Clone, DataTypeB: Clone> {
a: DataTypeA,
b: DataTypeB,
}
impl<DataTypeA: Clone, DataTypeB: Clone> TwoTuple<DataTypeA, DataTypeB> {
pub fn new(input1: DataTypeA, input2: DataTypeB) -> Self {
Self {
a: input1,
b: input2,
}
}
pub fn car(&self) -> DataTypeA {
self.a.clone()
}
pub fn cdr(&self) -> DataTypeB {
self.b.clone()
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct UsizeWrapper {
data: usize,
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct SmallNumberWrapper {
data: u16,
}
#[derive(Clone, Debug, PartialEq)]
pub struct StringWrapper {
data: String,
}
pub const NANO_VEC_BUFFER_SIZE: usize = 16;
#[derive(Clone)]
pub struct NanoVec<T: Clone + Encodeable> {
data: [T; NANO_VEC_BUFFER_SIZE],
len: usize,
}
impl<'a, T: Clone + Encodeable + Newable + fmt::Debug> IntoIterator for &'a NanoVec<T> {
type Item = &'a T;
type IntoIter = NanoVecRefIntoIter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
NanoVecRefIntoIter {
data: &self.data,
index: 0,
len: self.len,
}
}
}
impl<T: Clone + Encodeable + Newable + PartialEq> PartialEq for NanoVec<T> {
fn eq(&self, other: &Self) -> bool {
let mut to_return = true;
if self.len != other.len {
to_return = false;
} else {
for j in 0..self.len {
if self.at(j) != other.at(j) {
to_return = false;
break;
}
}
}
to_return
}
}
impl<T: Clone + Encodeable + Newable> IntoIterator for NanoVec<T> {
type Item = T;
type IntoIter = NanoVecIntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
NanoVecIntoIter {
data: self.data,
index: 0,
len: self.len,
}
}
}
pub struct NanoVecIntoIter<T: Clone + Encodeable + Newable> {
data: [T; NANO_VEC_BUFFER_SIZE],
index: usize,
len: usize,
}
pub struct NanoVecRefIntoIter<'a, T: Clone + Encodeable + Newable> {
data: &'a [T; NANO_VEC_BUFFER_SIZE],
index: usize,
len: usize,
}
impl<T: Clone + Encodeable + Newable> Iterator for NanoVecIntoIter<T> {
type Item = T;
#[inline(always)]
fn next(&mut self) -> Option<T> {
if self.index >= self.len {
None
} else {
self.index += 1;
Some(self.data[self.index - 1].clone())
}
}
}
impl<'a, T: Clone + Encodeable + Newable + fmt::Debug> Iterator for NanoVecRefIntoIter<'a, T> {
type Item = &'a T;
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
if self.index >= self.len {
None
} else {
self.index += 1;
Some(&self.data[self.index - 1])
}
}
}
impl<T: Clone + Encodeable + Newable> NanoVec<T> {
pub fn new(size: usize, init_val: T) -> NanoVec<T> {
if size > NANO_VEC_BUFFER_SIZE {
panic!("NanoVec can only hold up to NANO_VEC_BUFFER_SIZE elements");
}
Self {
data: [
init_val.clone(),
init_val.clone(),
init_val.clone(),
init_val.clone(),
init_val.clone(),
init_val.clone(),
init_val.clone(),
init_val.clone(),
init_val.clone(),
init_val.clone(),
init_val.clone(),
init_val.clone(),
init_val.clone(),
init_val.clone(),
init_val.clone(),
init_val.clone(),
],
len: size,
}
}
pub fn new_default(size: usize) -> NanoVec<T> {
if size > NANO_VEC_BUFFER_SIZE {
panic!("NanoVec can only hold up to NANO_VEC_BUFFER_SIZE elements");
}
Self {
data: [
Newable::new(),
Newable::new(),
Newable::new(),
Newable::new(),
Newable::new(),
Newable::new(),
Newable::new(),
Newable::new(),
Newable::new(),
Newable::new(),
Newable::new(),
Newable::new(),
Newable::new(),
Newable::new(),
Newable::new(),
Newable::new(),
],
len: size,
}
}
#[inline(always)]
pub fn len(&self) -> usize {
self.len
}
#[inline(always)]
pub fn at(&self, idx: usize) -> &T {
if idx < self.len {
&self.data[idx]
} else {
panic!("Index out of bounds");
}
}
#[inline(always)]
pub fn set_at(&mut self, idx: usize, data_1: T) {
if idx < self.len {
self.data[idx] = data_1;
} else {
panic!("Index out of bounds");
}
}
pub fn to_slice(&self) -> &[T] {
&self.data
}
pub fn from_slice(input: &[T]) -> Self {
if input.len() > 16 {
panic!("NanoVec can only hold 16 elements");
}
let mut tmp = [
input[0].clone(),
input[0].clone(),
input[0].clone(),
input[0].clone(),
input[0].clone(),
input[0].clone(),
input[0].clone(),
input[0].clone(),
input[0].clone(),
input[0].clone(),
input[0].clone(),
input[0].clone(),
input[0].clone(),
input[0].clone(),
input[0].clone(),
input[0].clone(),
];
for (j, item) in input.iter().enumerate() {
tmp[j] = item.clone();
}
Self {
data: tmp,
len: input.len(),
}
}
pub fn push(&mut self, elem: T) {
if self.len + 1 >= 16 {
panic!("NanoVec is full");
}
self.len += 1;
self.data[self.len - 1] = elem;
}
}
impl<T: Clone + Encodeable> fmt::Debug for NanoVec<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut temp = String::new();
temp += "NanoVec [";
for j in 0..self.len {
temp += &Encodeable::encode(&self.data[j]);
if j != self.len - 1 {
temp += ", ";
}
}
temp += "]";
write!(f, "{}", temp)
}
}
impl<T: Clone + Encodeable> Encodeable for NanoVec<T> {
fn encode(&self) -> String {
let mut to_return = String::new();
for j in 0..16 {
to_return += &Encodeable::encode(&self.data[j]);
}
to_return
}
}
impl UsizeWrapper {
pub fn from(data_1: usize) -> Self {
Self { data: data_1 }
}
pub fn get_data(&self) -> usize {
self.data
}
}
impl Add for UsizeWrapper {
type Output = UsizeWrapper;
fn add(self, other: UsizeWrapper) -> Self {
Self {
data: self.get_data() + other.get_data(),
}
}
}
impl Add<u16> for UsizeWrapper {
type Output = UsizeWrapper;
fn add(self, other: u16) -> Self {
Self {
data: self.get_data() + (other as usize),
}
}
}
impl Add<u32> for UsizeWrapper {
type Output = UsizeWrapper;
fn add(self, other: u32) -> Self {
Self {
data: self.get_data() + (other as usize),
}
}
}
impl Add<u64> for UsizeWrapper {
type Output = UsizeWrapper;
fn add(self, other: u64) -> Self {
Self {
data: self.get_data() + (other as usize),
}
}
}
impl Newable for UsizeWrapper {
fn new() -> Self {
Self { data: 0 }
}
}
impl Parseable for UsizeWrapper {
fn parse(data: &str) -> Self {
Self {
data: data.parse::<usize>().unwrap(),
}
}
}
impl Encodeable for UsizeWrapper {
fn encode(&self) -> String {
self.data.to_string()
}
}
impl SmallNumberWrapper {
pub fn from(data_1: u16) -> Self {
Self { data: data_1 }
}
pub fn get_data(&self) -> u16 {
self.data
}
}
impl Newable for SmallNumberWrapper {
fn new() -> Self {
Self { data: 0 }
}
}
impl Parseable for SmallNumberWrapper {
fn parse(data: &str) -> Self {
Self {
data: data.parse::<u16>().unwrap(),
}
}
}
impl Encodeable for SmallNumberWrapper {
fn encode(&self) -> String {
self.data.to_string()
}
}
impl Newable for StringWrapper {
fn new() -> Self {
Self {
data: String::new(),
}
}
}
impl Parseable for StringWrapper {
fn parse(data: &str) -> Self {
Self {
data: data.parse::<String>().unwrap(),
}
}
}
impl Encodeable for StringWrapper {
fn encode(&self) -> String {
self.data.clone()
}
}
pub fn parse_csv_list<DataType: Parseable + Clone>(input: &str, character: char) -> Vec<DataType> {
let mut to_return: Vec<DataType> = Vec::new();
for elem in input.split(character) {
to_return.push(Parseable::parse(elem));
}
to_return
}
pub fn parse_csv_list_native<DataType: std::str::FromStr>(
input: &str,
character: char,
) -> Vec<DataType> {
let mut to_return: Vec<DataType> = Vec::new();
for elem in input.split(character) {
to_return.push(if let Ok(a) = elem.parse::<DataType>() {
a
} else {
panic!("Invalid token found");
});
}
to_return
}
pub fn parse_list_multi<DataType: Parseable + Clone>(
input: &str,
vocab: &str,
level: usize,
) -> Vec<DataType> {
if level >= vocab.len() {
panic!("Out of tokens");
}
let token = {
if let Some(a) = vocab.chars().nth(level) {
a
} else {
panic!("Out of tokens");
}
};
let mut to_return: Vec<DataType> = Vec::new();
for elem in input.split(token) {
to_return.push(Parseable::parse(elem));
}
to_return
}
pub fn split_str(input: &str, token: char) -> Vec<&str> {
input.split(token).collect::<Vec<&str>>()
}
pub fn parse_table_sections(input: &str) -> Vec<String> {
let the_string = input.to_string();
let fst = {
if let Some(a) = the_string.split(';').nth(0) {
a
} else {
panic!("Symbol table is invalid");
}
};
let header_len = {
if let Ok(a) = fst.to_string().parse::<usize>() {
a
} else {
panic!("Header length is not an integer");
}
};
let header_start = fst.chars().count() + 1;
let header_end = header_start + header_len;
let body_start = header_end + 1;
let body_end = the_string.chars().count();
let header = (&the_string[header_start..header_end]).to_string();
let body = (&the_string[body_start..body_end]).to_string();
if the_string.chars().collect::<Vec<char>>()[body_start - 1] != ';' {
panic!("Symbol table is invalid");
}
let tokenized_header = {
let mut to_return: Vec<usize> = Vec::new();
let tmp = header.split(',').collect::<Vec<&str>>();
for item in tmp {
if let Ok(a) = item.to_string().parse::<usize>() {
to_return.push(a);
} else {
panic!("Symbol table is invalid");
}
}
to_return
};
let mut to_return: Vec<String> = Vec::new();
let mut old_offset = 0;
for item in tokenized_header {
to_return.push((&body[(old_offset)..(old_offset + item)]).to_string());
old_offset += item + 1;
}
to_return
}
pub fn encode_table_sections(input: &[String]) -> String {
let mut to_return = String::new();
let lengths: Vec<usize> = input.iter().map(|x| x.len()).collect();
let header_length = {
let mut to_ret = 0;
for item in &lengths {
to_ret += item.to_string().len();
to_ret += 1; }
to_ret -= 1; to_ret
};
to_return += &header_length.to_string();
to_return += ";";
for (j, item) in lengths.iter().enumerate() {
to_return += &item.to_string();
to_return += {
if j == lengths.len() - 1 {
";"
} else {
","
}
};
}
for item in input {
to_return += item;
to_return += ",";
}
to_return
}
#[inline(always)]
pub fn addr_normal_to_flattened(coords: &[isize], sizes: &[usize]) -> usize {
let mut addr: usize = 0;
for j in 0..sizes.len() {
addr += (coords[j] * (sizes[j] as isize)) as usize;
}
addr
}
#[inline(always)]
pub fn addr_normal_to_flattened_usize(coords: &[usize], sizes: &[usize]) -> usize {
let mut addr: usize = 0;
for j in 0..sizes.len() {
addr += coords[j] * sizes[j];
}
addr
}
#[inline(always)]
pub fn addr_normal_to_flattened_usize_wrapper_ref(
coords: &[&UsizeWrapper],
sizes: &[usize],
) -> usize {
let mut addr: usize = 0;
for j in 0..sizes.len() {
addr += coords[j].get_data() * sizes[j];
}
addr
}
#[inline(always)]
pub fn compute_sizes(dimensions: &[usize], len: usize) -> Vec<usize> {
let mut old_len = len;
dimensions
.iter()
.map(|&x| {
old_len /= x;
old_len
})
.collect::<Vec<usize>>()
}
#[inline(always)]
pub fn addr_flattened_to_normal(addr: usize, sizes: &[usize]) -> Vec<usize> {
let mut to_return: Vec<usize> = Vec::new();
let mut old: usize = addr;
for item in sizes {
let mut count = 0;
while old >= *item {
old -= *item;
count += 1;
}
to_return.push(count);
}
to_return
}
#[inline(always)]
pub fn access_flattened_vec<'a, T>(
list: &'a [T],
coords: &[isize],
dimensions: &[usize],
offset: usize,
edge_val: &'a T,
) -> &'a T {
if coords.len() != dimensions.len() {
panic!("Dimensions do not match");
}
let sizes = compute_sizes(dimensions, list.len());
let mut addr = addr_normal_to_flattened(&coords, &sizes);
if is_flattened_address_off_grid(offset, coords, &sizes, dimensions) {
return edge_val;
} else {
addr += offset;
}
&list[addr]
}
#[inline(always)]
pub fn is_flattened_address_off_grid(
offset: usize,
coords: &[isize],
sizes: &[usize],
dimensions: &[usize],
) -> bool {
let actual_addr = addr_flattened_to_normal(offset, sizes);
for (j, item) in actual_addr.iter().enumerate() {
let tmp = (*item as isize) + coords[j];
if tmp < 0 || tmp > dimensions[j] as isize {
return true;
}
}
false
}