arch_pkg_text/desc/query/
forgetful.rs

1use super::{Query, QueryMut};
2use crate::desc::{
3    field::{ParsedField, RawField},
4    misc::{False, ReuseAdvice},
5};
6use pipe_trait::Pipe;
7
8/// [Query] without a cache.
9#[derive(Debug, Clone, Copy)]
10pub struct ForgetfulQuerier<'a>(&'a str);
11
12impl<'a> ForgetfulQuerier<'a> {
13    /// Query the `text` without cache.
14    pub const fn new(text: &'a str) -> Self {
15        ForgetfulQuerier(text)
16    }
17}
18
19impl<'a> Query<'a> for ForgetfulQuerier<'a> {
20    fn query_raw_text(&self, field: ParsedField) -> Option<&'a str> {
21        let mut lines_with_end_offset = self.0.lines().map(|line| {
22            (
23                line,
24                line.as_ptr() as usize + line.len() - self.0.as_ptr() as usize,
25            )
26        });
27
28        let (_, value_start_offset) = lines_with_end_offset.find(|(line, _)| {
29            line.trim()
30                .pipe(RawField::try_from)
31                .ok()
32                .map(|x| x.name_str() == field.name_str())
33                .unwrap_or(false)
34        })?;
35
36        let (_, value_end_offset) = lines_with_end_offset
37            .take_while(|(line, _)| RawField::try_from(line.trim()).is_err())
38            .last()?; // no last means empty iterator, which means no content
39
40        let value = self.0[value_start_offset..value_end_offset].trim_matches(['\n', '\r']);
41
42        if value.is_empty() { None } else { Some(value) }
43    }
44}
45
46impl<'a> QueryMut<'a> for ForgetfulQuerier<'a> {
47    fn query_raw_text_mut(&mut self, field: ParsedField) -> Option<&'a str> {
48        self.query_raw_text(field)
49    }
50}
51
52impl ReuseAdvice for ForgetfulQuerier<'_> {
53    /// Whilst [`ForgetfulQuerier`] costs nothing to construct, performing a
54    /// lookup on it costs O(n) time complexity (n being text length).
55    ///
56    /// This struct is best used to lookup once.
57    type ShouldReuse = False;
58}