arch_pkg_text/srcinfo/query/
forgetful.rs

1use super::{
2    ChecksumValue, Checksums, ChecksumsMut, Query, QueryChecksumItem, QueryMut, QueryRawTextItem,
3    Section,
4    utils::{non_blank_trimmed_lines, parse_line},
5};
6use crate::{
7    srcinfo::{
8        field::{FieldName, ParsedField, RawField},
9        misc::{False, ReuseAdvice},
10    },
11    value::{Architecture, Name},
12};
13use iter_scan::IterScan;
14use pipe_trait::Pipe;
15
16/// [Query] without a cache.
17#[derive(Debug, Clone, Copy)]
18pub struct ForgetfulQuerier<'a>(&'a str);
19
20impl<'a> ForgetfulQuerier<'a> {
21    /// Query the `text` without cache.
22    pub const fn new(text: &'a str) -> Self {
23        ForgetfulQuerier(text)
24    }
25
26    /// List all items of known fields.
27    fn all_known_items(
28        &self,
29    ) -> impl Iterator<Item = (Section<'a>, (ParsedField<&'a str>, &'a str))> {
30        self.0
31            .pipe(non_blank_trimmed_lines)
32            .map_while(parse_line)
33            .filter_map(known_field)
34            .filter(|(_, value)| !value.is_empty())
35            .scan_state_copy(Section::Base, scan_section)
36    }
37}
38
39impl<'a> Query<'a> for ForgetfulQuerier<'a> {
40    fn query_raw_text(&self, field_name: FieldName) -> impl Iterator<Item = QueryRawTextItem<'a>> {
41        self.all_known_items()
42            .filter(move |(_, (field, _))| *field.name() == field_name)
43            .map(|(section, (field, value))| {
44                QueryRawTextItem::from_tuple3((
45                    value,
46                    section,
47                    field.architecture_str().map(Architecture::new),
48                ))
49            })
50    }
51}
52
53impl<'a> QueryMut<'a> for ForgetfulQuerier<'a> {
54    fn query_raw_text_mut(
55        &mut self,
56        field_name: FieldName,
57    ) -> impl Iterator<Item = QueryRawTextItem<'a>> {
58        self.query_raw_text(field_name)
59    }
60}
61
62impl<'a> Checksums<'a> for ForgetfulQuerier<'a> {
63    fn checksums(&self) -> impl Iterator<Item = QueryChecksumItem<'a>> {
64        self.all_known_items()
65            .filter_map(|(section, (field, value))| {
66                ChecksumValue::try_from_field_name(*field.name(), value)
67                    .map(|value| (value, section, field.architecture_str().map(Architecture)))
68            })
69            .map(QueryChecksumItem::from_tuple3)
70    }
71}
72
73impl<'a> ChecksumsMut<'a> for ForgetfulQuerier<'a> {
74    fn checksums_mut(&mut self) -> impl Iterator<Item = QueryChecksumItem<'a>> {
75        self.checksums()
76    }
77}
78
79/// Callback function to pass to `.filter_map` to filter out unknown fields.
80fn known_field<'a, Architecture, Acquaintance>(
81    (field, acquaintance): (RawField<'a>, Acquaintance),
82) -> Option<(ParsedField<Architecture>, Acquaintance)>
83where
84    &'a str: TryInto<Architecture>,
85{
86    field
87        .to_parsed::<FieldName, Architecture>()
88        .map(|field| (field, acquaintance))
89        .ok()
90}
91
92/// Callback function to pass to `.scan_state_*` to attach sections to items.
93fn scan_section<'a>(
94    section: Section<'a>,
95    (field, value): (ParsedField<&'a str>, &'a str),
96) -> (Section<'a>, (ParsedField<&'a str>, &'a str)) {
97    match field.name() {
98        FieldName::Name => (Section::Derivative(Name(value)), (field, value)),
99        _ => (section, (field, value)),
100    }
101}
102
103impl ReuseAdvice for ForgetfulQuerier<'_> {
104    /// Whilst [`ForgetfulQuerier`] costs nothing to construct, performing a
105    /// lookup on it costs O(n) time complexity (n being text length).
106    ///
107    /// This struct is best used to lookup once.
108    type ShouldReuse = False;
109}