arch_pkg_text/desc/query/
forgetful.rs

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