pub trait AsArray1D<'a, U: 'a> {
fn size(&self) -> usize;
fn at(&self, i: usize) -> U;
}
impl<'a, U: 'a> AsArray1D<'a, U> for Vec<U>
where
U: 'a + Copy,
{
fn size(&self) -> usize {
self.len()
}
fn at(&self, i: usize) -> U {
self[i]
}
}
impl<'a, U> AsArray1D<'a, U> for &'a [U]
where
U: 'a + Copy,
{
fn size(&self) -> usize {
self.len()
}
fn at(&self, i: usize) -> U {
self[i]
}
}
impl<'a, U, const M: usize> AsArray1D<'a, U> for [U; M]
where
U: 'a + Copy,
{
fn size(&self) -> usize {
self.len()
}
fn at(&self, i: usize) -> U {
self[i]
}
}
pub trait AsArray2D<'a, U: 'a> {
fn size(&self) -> (usize, usize);
fn at(&self, i: usize, j: usize) -> U;
fn row(&self, i: usize) -> &[U];
}
impl<'a, U: 'a> AsArray2D<'a, U> for Vec<Vec<U>>
where
U: 'a + Copy,
{
fn size(&self) -> (usize, usize) {
(self.len(), self[0].len())
}
fn at(&self, i: usize, j: usize) -> U {
self[i][j]
}
fn row(&self, i: usize) -> &[U] {
&self[i]
}
}
impl<'a, U> AsArray2D<'a, U> for &'a [&'a [U]]
where
U: 'a + Copy,
{
fn size(&self) -> (usize, usize) {
(self.len(), self[0].len())
}
fn at(&self, i: usize, j: usize) -> U {
self[i][j]
}
fn row(&self, i: usize) -> &[U] {
&self[i]
}
}
impl<'a, U, const M: usize, const N: usize> AsArray2D<'a, U> for [[U; N]; M]
where
U: 'a + Copy,
{
fn size(&self) -> (usize, usize) {
(self.len(), self[0].len())
}
fn at(&self, i: usize, j: usize) -> U {
self[i][j]
}
fn row(&self, i: usize) -> &[U] {
&self[i]
}
}
#[cfg(test)]
mod tests {
use super::{AsArray1D, AsArray2D};
use std::fmt::Write;
fn array_1d_str<'a, T, U>(array: &'a T) -> String
where
T: AsArray1D<'a, U>,
U: 'a + std::fmt::Display,
{
let mut buf = String::new();
let m = array.size();
for i in 0..m {
write!(&mut buf, "{},", array.at(i)).unwrap();
}
write!(&mut buf, "\n").unwrap();
buf
}
fn array_2d_str<'a, T, U>(array: &'a T) -> String
where
T: AsArray2D<'a, U>,
U: 'a + std::fmt::Display,
{
let mut buf = String::new();
let (m, n) = array.size();
for i in 0..m {
for j in 0..n {
write!(&mut buf, "{},", array.at(i, j)).unwrap();
}
write!(&mut buf, "\n").unwrap();
}
buf
}
fn array_2d_str_row<'a, T, U>(array: &'a T, i: usize) -> String
where
T: AsArray2D<'a, U>,
U: 'a + std::fmt::Debug,
{
format!("{:?}", array.row(i))
}
#[test]
fn as_array_1d_works() {
let x_data = vec![1.0, 2.0, 3.0];
assert_eq!(array_1d_str(&x_data), "1,2,3,\n");
let y_data: &[f64] = &[10.0, 20.0, 30.0];
assert_eq!(array_1d_str(&y_data), "10,20,30,\n");
let z_data = [100.0, 200.0, 300.0];
assert_eq!(array_1d_str(&z_data), "100,200,300,\n");
}
#[test]
fn as_array_2d_works() {
const IGNORED: f64 = 123.456;
let a_data = vec![
vec![1.0, 2.0],
vec![3.0, 4.0, IGNORED, IGNORED, IGNORED],
vec![5.0, 6.0],
];
assert_eq!(
array_2d_str(&a_data),
"1,2,\n\
3,4,\n\
5,6,\n"
);
assert_eq!(array_2d_str_row(&a_data, 1), "[3.0, 4.0, 123.456, 123.456, 123.456]");
let b_data: &[&[f64]] = &[&[10.0, 20.0], &[30.0, 40.0, IGNORED], &[50.0, 60.0, IGNORED, IGNORED]];
assert_eq!(
array_2d_str(&b_data),
"10,20,\n\
30,40,\n\
50,60,\n"
);
assert_eq!(array_2d_str_row(&b_data, 0), "[10.0, 20.0]");
let c_data = [[100.0, 200.0], [300.0, 400.0], [500.0, 600.0]];
assert_eq!(
array_2d_str(&c_data),
"100,200,\n\
300,400,\n\
500,600,\n"
);
assert_eq!(array_2d_str_row(&c_data, 2), "[500.0, 600.0]");
}
}