use std::{
fs::File,
io::{BufReader, BufWriter},
path::Path,
};
use crate::matrix::Matrix;
pub fn to_file<N, P>(m: &Matrix<N>, path: P)
where
N: std::fmt::Debug,
P: AsRef<Path> + std::fmt::Debug,
{
use std::io::Write;
let file =
File::create(&path).unwrap_or_else(|_| panic!("Error[matrix::serde::to_file]: Failed to create file ({path:?})."));
let mut writer = BufWriter::new(file);
let data = m
.linear_iter()
.map(|e| format!("{e:?}"))
.collect::<Vec<_>>()
.join(",");
writer
.write_all(data.as_bytes())
.expect("Error[matrix::serde::to_file]: Failed to write the matrix to the file.");
}
pub fn from_file<N, P>(row: usize, column: usize, path: P) -> Option<Matrix<N>>
where
N: Clone + std::str::FromStr,
P: AsRef<Path> + std::fmt::Debug,
{
use std::io::Read;
let file =
File::open(&path).unwrap_or_else(|_| panic!("Error[matrix::serde::from_file]: Failed to create file ({path:?})."));
let mut reader = BufReader::new(file);
let mut data = String::new();
reader
.read_to_string(&mut data)
.expect("Error[matrix::serde::from_file]: Failed to read the file content into the string.");
let inner = data
.split(",")
.map(|s| s.trim())
.filter(|s| !s.is_empty())
.map(|s| {
s.parse::<N>()
.ok()
.unwrap_or_else(|| panic!("Error[matrix::serde::from_file]: Failed to parse ({s}) from the string."))
})
.collect::<Vec<N>>();
Matrix::of(row, column, &inner)
}
pub fn from_stdin<N>() -> Matrix<N>
where
N: std::str::FromStr,
{
let stdin = std::io::stdin();
let mut buffer = String::new();
println!("Please eneter the matrix shape (two integers separated by a space or a comma):");
stdin
.read_line(&mut buffer)
.expect("Error[matrix::serde::from_stdin]: Failed to read shape from 'stdin'.");
let shape = buffer
.trim()
.split(|c: char| c.is_whitespace() || c == ',')
.filter(|s| !s.is_empty())
.take(2)
.map(|s| {
s.parse::<usize>()
.unwrap_or_else(|_| panic!("Error[matrix::serde::from_file]: Failed to parse ({s}) from the string."))
})
.collect::<Vec<usize>>();
let row = shape[0];
let column = shape[1];
let mut inner = Vec::with_capacity(row * column);
println!("Please enter the matrix elements ({row}, {column}):");
while inner.len() < row * column {
stdin
.read_line(&mut buffer)
.expect("Error[matrix::serde::from_stdin]: Failed to read data from 'stdin'.");
buffer
.trim()
.split(|c: char| c.is_whitespace() || c == ',')
.filter(|s| !s.is_empty())
.for_each(|s| {
let e = s
.parse::<N>()
.ok()
.unwrap_or_else(|| panic!("Error[matrix::serde::from_file]: Failed to parse ({s}) from the string."));
inner.push(e);
});
buffer.clear();
}
Matrix { inner, row, column }
}