use super::{
fmt::Format,
iter::{ReadAll, ReadAllIn},
};
use crate::{
ext::{Pattern, PatternError},
stream::{error::StreamError, ext::Any, traits::BufReadExtWithFormat},
BufReadExt, ReadError,
};
use std::any::type_name;
pub type ReadOneFromError<T> = ReadError<<T as ReadOneFrom>::ParseError>;
pub trait ReadOneFrom: Sized {
type ParseError: std::error::Error;
fn parse(s: &str) -> Result<Self, ReadError<Self::ParseError>>;
#[inline]
fn accept() -> impl Pattern<Item = char> {
Any::new()
}
#[inline]
fn try_read_one_from<F: Format, S: BufReadExt>(
stream: &mut S,
format: F,
) -> Result<Self, ReadError<Self::ParseError>> {
let s = stream
.try_get_string_some(format.skip(), Self::accept())
.map_err(|error| match error {
PatternError::Extra(StreamError::IOError(e)) => ReadError::IOError(e),
PatternError::Extra(StreamError::Eof) => ReadError::EOF,
PatternError::Extra(StreamError::Eol) => ReadError::EOL,
PatternError::UnexpectedChar(c) => {
ReadError::UnexpectedChar(c, type_name::<Self>())
} })?;
Self::parse(s)
}
#[inline]
fn try_read_in_char_from<F: Format, S: BufReadExt>(
stream: &mut S,
format: F,
) -> Result<Self, ReadError<Self::ParseError>> {
let s = stream.try_get_non_skipped(format.skip())?;
Self::parse(s.encode_utf8(&mut [0; 4]))
}
#[inline]
fn try_read_in_line_trimmed_from<F: Format, S: BufReadExt>(
stream: &mut S,
format: F,
) -> Result<Self, ReadError<Self::ParseError>> {
let s = stream.try_get_line_trimmed(format.skip())?.trim_start();
Self::parse(s)
}
#[inline]
fn try_read_in_line_some_trimmed_from<F: Format, S: BufReadExt>(
stream: &mut S,
format: F,
) -> Result<Self, ReadError<Self::ParseError>> {
let s = stream
.try_get_line_some_trimmed(format.skip())?
.trim_start();
Self::parse(s)
}
#[inline]
fn try_read_all_from<F: Format, S: BufReadExt>(
stream: &mut S,
format: F,
) -> Result<Vec<Self>, ReadError<Self::ParseError>> {
ReadAll::<F, S, Self>::new(stream, format).collect()
}
#[inline]
fn try_read_any_in_line_from<F: Format, S: BufReadExt>(
stream: &mut S,
format: F,
) -> Result<Vec<Self>, ReadError<Self::ParseError>> {
ReadAllIn::<F, Self>::new(stream.try_get_line_trimmed(format.skip())?, format).collect()
}
#[inline]
fn try_read_some_in_line_from<F: Format, S: BufReadExt>(
stream: &mut S,
format: F,
) -> Result<Vec<Self>, ReadError<Self::ParseError>> {
ReadAllIn::<F, Self>::new(stream.try_get_line_some_trimmed(format.skip())?, format)
.collect()
}
}