use core::convert::Infallible;
use super::{Query, QueryMut};
use crate::{
desc::{
field::{ParsedField, RawField},
misc::{False, ReuseAdvice},
},
parse::{ParseWithIssues, PartialParse, PartialParseResult},
};
use pipe_trait::Pipe;
#[derive(Debug, Clone, Copy)]
pub struct ForgetfulQuerier<'a>(&'a str);
impl<'a> ForgetfulQuerier<'a> {
pub const fn new(text: &'a str) -> Self {
ForgetfulQuerier(text)
}
}
impl<'a> Query<'a> for ForgetfulQuerier<'a> {
fn query_raw_text(&self, field: ParsedField) -> Option<&'a str> {
let mut lines_with_end_offset = self.0.lines().map(|line| {
(
line,
line.as_ptr() as usize + line.len() - self.0.as_ptr() as usize,
)
});
let (_, value_start_offset) = lines_with_end_offset.find(|(line, _)| {
line.trim()
.pipe(RawField::try_from)
.ok()
.map(|x| x.name_str() == field.name_str())
.unwrap_or(false)
})?;
let (_, value_end_offset) = lines_with_end_offset
.take_while(|(line, _)| RawField::try_from(line.trim()).is_err())
.last()?;
let value = self.0[value_start_offset..value_end_offset].trim();
if value.is_empty() { None } else { Some(value) }
}
}
impl<'a> QueryMut<'a> for ForgetfulQuerier<'a> {
fn query_raw_text_mut(&mut self, field: ParsedField) -> Option<&'a str> {
self.query_raw_text(field)
}
}
impl ReuseAdvice for ForgetfulQuerier<'_> {
type ShouldReuse = False;
}
impl<'a> From<&'a str> for ForgetfulQuerier<'a> {
fn from(value: &'a str) -> Self {
ForgetfulQuerier::new(value)
}
}
impl<'a> PartialParse<&'a str> for ForgetfulQuerier<'a> {
type Error = Infallible;
fn partial_parse(text: &'a str) -> PartialParseResult<Self, Self::Error> {
ForgetfulQuerier::parse_with_issues(text, ())
}
}
impl<'a, HandleIssue, Error> ParseWithIssues<&'a str, HandleIssue, Error> for ForgetfulQuerier<'a> {
fn parse_with_issues(text: &'a str, _: HandleIssue) -> PartialParseResult<Self, Error> {
text.pipe(ForgetfulQuerier::new)
.pipe(PartialParseResult::new_complete)
}
}