use super::{
ChecksumValue, Checksums, ChecksumsMut, Query, QueryChecksumItem, QueryMut, QueryRawTextItem,
Section,
utils::{non_blank_trimmed_lines, parse_line},
};
use crate::{
parse::{ParseWithIssues, PartialParse, PartialParseResult},
srcinfo::{
field::{FieldName, ParsedField, RawField},
misc::{False, ReuseAdvice},
},
value::{Architecture, Name},
};
use core::convert::Infallible;
use iter_scan::IterScan;
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)
}
fn all_known_items(
&self,
) -> impl Iterator<Item = (Section<'a>, (ParsedField<&'a str>, &'a str))> {
self.0
.pipe(non_blank_trimmed_lines)
.map_while(parse_line)
.filter_map(known_field)
.filter(|(_, value)| !value.is_empty())
.scan_state_copy(Section::Base, scan_section)
}
}
impl<'a> Query<'a> for ForgetfulQuerier<'a> {
fn query_raw_text(&self, field_name: FieldName) -> impl Iterator<Item = QueryRawTextItem<'a>> {
self.all_known_items()
.filter(move |(_, (field, _))| *field.name() == field_name)
.map(|(section, (field, value))| {
QueryRawTextItem::from_tuple3((
value,
section,
field.architecture_str().map(Architecture::new),
))
})
}
}
impl<'a> QueryMut<'a> for ForgetfulQuerier<'a> {
fn query_raw_text_mut(
&mut self,
field_name: FieldName,
) -> impl Iterator<Item = QueryRawTextItem<'a>> {
self.query_raw_text(field_name)
}
}
impl<'a> Checksums<'a> for ForgetfulQuerier<'a> {
fn checksums(&self) -> impl Iterator<Item = QueryChecksumItem<'a>> {
self.all_known_items()
.filter_map(|(section, (field, value))| {
ChecksumValue::try_from_field_name(*field.name(), value)
.map(|value| (value, section, field.architecture_str().map(Architecture)))
})
.map(QueryChecksumItem::from_tuple3)
}
}
impl<'a> ChecksumsMut<'a> for ForgetfulQuerier<'a> {
fn checksums_mut(&mut self) -> impl Iterator<Item = QueryChecksumItem<'a>> {
self.checksums()
}
}
fn known_field<'a, Architecture, Acquaintance>(
(field, acquaintance): (RawField<'a>, Acquaintance),
) -> Option<(ParsedField<Architecture>, Acquaintance)>
where
&'a str: TryInto<Architecture>,
{
field
.to_parsed::<FieldName, Architecture>()
.map(|field| (field, acquaintance))
.ok()
}
fn scan_section<'a>(
section: Section<'a>,
(field, value): (ParsedField<&'a str>, &'a str),
) -> (Section<'a>, (ParsedField<&'a str>, &'a str)) {
match field.name() {
FieldName::Name => (Section::Derivative(Name(value)), (field, value)),
_ => (section, (field, value)),
}
}
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)
}
}