use super::{fmt::Format, read_one_from::ReadOneFrom};
use crate::{array::array_try_from_fn, mat::Mat, BufReadExt, ReadError};
pub type ReadFromError<T> = ReadError<<T as ReadFrom>::ParseError>;
pub trait ReadFrom: Sized {
type ParseError: std::error::Error;
fn try_read_from<F: Format, S: BufReadExt>(
stream: &mut S,
format: F,
) -> Result<Self, ReadFromError<Self>>;
#[inline]
fn try_read_n_from<F: Format, S: BufReadExt>(
stream: &mut S,
n: usize,
format: F,
) -> Result<Vec<Self>, ReadFromError<Self>> {
let mut res = Vec::with_capacity(n);
for _ in 0..n {
res.push(Self::try_read_from(stream, format)?);
}
Ok(res)
}
#[inline]
fn try_read_m_n_from<F: Format, S: BufReadExt>(
stream: &mut S,
m: usize,
n: usize,
format: F,
) -> Result<Mat<Self>, ReadFromError<Self>> {
let mut res = Mat::with_capacity(m);
for _ in 0..m {
res.push(Self::try_read_n_from(stream, n, format)?);
}
Ok(res)
}
}
impl<T: ReadOneFrom> ReadFrom for T {
type ParseError = <Self as ReadOneFrom>::ParseError;
#[inline]
fn try_read_from<F: Format, S: BufReadExt>(
stream: &mut S,
format: F,
) -> Result<T, ReadFromError<Self>> {
Self::try_read_one_from(stream, format)
}
}
impl<T: ReadFrom, const N: usize> ReadFrom for [T; N] {
type ParseError = <T as ReadFrom>::ParseError;
#[inline]
fn try_read_from<F: Format, S: BufReadExt>(
stream: &mut S,
format: F,
) -> Result<Self, ReadFromError<Self>> {
array_try_from_fn(|| T::try_read_from(stream, format))
}
}
impl<T: ReadFrom, const N: usize> ReadFrom for Box<[T; N]> {
type ParseError = <T as ReadFrom>::ParseError;
#[inline]
fn try_read_from<F: Format, S: BufReadExt>(
stream: &mut S,
format: F,
) -> Result<Box<[T; N]>, ReadFromError<Self>> {
let res = T::try_read_n_from(stream, N, format)?
.into_boxed_slice()
.try_into();
let res = unsafe { res.unwrap_unchecked() };
Ok(res)
}
}
impl<T: ReadOneFrom> ReadFrom for Vec<T> {
type ParseError = <T as ReadOneFrom>::ParseError;
#[inline]
fn try_read_from<F: Format, S: BufReadExt>(
stream: &mut S,
format: F,
) -> Result<Vec<T>, ReadFromError<Self>> {
T::try_read_some_in_line_from(stream, format)
}
}