arch_pkg_text/srcinfo/
query.rs

1use crate::{srcinfo::field::FieldName, value};
2use iter_scan::IterScan;
3use pipe_trait::Pipe;
4
5/// Location of a given [`QueryItem`].
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7pub enum Section<'a> {
8    /// The item belongs to a section under `pkgbase`.
9    Base,
10    /// The item belongs to a section under `pkgname`.
11    Derivative(value::Name<'a>),
12}
13
14/// Return type of methods in [`Query`] and [`QueryMut`].
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
16pub struct QueryItem<'a, Value, Architecture> {
17    /// Value of the item.
18    pub value: Value,
19    /// Location of the item.
20    pub section: Section<'a>,
21    /// Architecture suffix of the corresponding field.
22    pub architecture: Architecture,
23}
24
25impl<'a, Value, Architecture> QueryItem<'a, Value, Architecture> {
26    /// Construct an item from a tuple of `value`, `section`, and `architecture`.
27    pub fn from_tuple3((value, section, architecture): (Value, Section<'a>, Architecture)) -> Self {
28        QueryItem {
29            value,
30            section,
31            architecture,
32        }
33    }
34
35    /// Dissolve the item into a tuple of `value`, `section`, and `architecture`.
36    pub fn into_tuple3(self) -> (Value, Section<'a>, Architecture) {
37        (self.value, self.section, self.architecture)
38    }
39
40    /// Transform `value`.
41    pub(crate) fn map<NewValue>(
42        self,
43        mut f: impl FnMut(Value) -> NewValue + 'static,
44    ) -> QueryItem<'a, NewValue, Architecture> {
45        let (value, section, architecture) = self.into_tuple3();
46        QueryItem::from_tuple3((f(value), section, architecture))
47    }
48}
49
50impl<'a, Value, Architecture> QueryItem<'a, Value, Option<Architecture>> {
51    /// Turns [`Self::architecture`] into `()` if it was `None`.
52    fn into_without_architecture(self) -> Option<QueryItem<'a, Value, ()>> {
53        let (value, section, architecture) = self.into_tuple3();
54        architecture
55            .is_none()
56            .then_some(QueryItem::from_tuple3((value, section, ())))
57    }
58}
59
60impl<'a, Value> QueryItem<'a, Value, ()> {
61    /// Construct an item from a tuple of `value` and `section`.
62    pub fn from_tuple2((value, section): (Value, Section<'a>)) -> Self {
63        QueryItem::from_tuple3((value, section, ()))
64    }
65
66    /// Dissolve the item into a tuple of `value` and `section`.
67    pub fn into_tuple2(self) -> (Value, Section<'a>) {
68        let (value, section, ()) = self.into_tuple3();
69        (value, section)
70    }
71}
72
73/// Return type of [`Query::query_raw_text`] and [`QueryMut::query_raw_text_mut`].
74pub type QueryRawTextItem<'a> = QueryItem<'a, &'a str, Option<value::Architecture<'a>>>;
75
76impl<'a> QueryRawTextItem<'a> {
77    /// Get a single value from the `pkgbase` section.
78    fn single_base_value(query_iter: impl Iterator<Item = Self>) -> Option<&'a str> {
79        Self::multi_base_values(query_iter).next()
80    }
81
82    /// Get all values from the `pkgbase` section.
83    fn multi_base_values(query_iter: impl Iterator<Item = Self>) -> impl Iterator<Item = &'a str> {
84        query_iter
85            .take_while(|item| item.section == Section::Base)
86            .filter(|item| item.architecture.is_none())
87            .map(|item| item.value)
88    }
89
90    /// Get a single value from each section.
91    fn shared_single_values(
92        query_iter: impl Iterator<Item = Self>,
93    ) -> impl Iterator<Item = QueryItem<'a, &'a str, ()>> {
94        query_iter
95            .filter_map(QueryItem::into_without_architecture)
96            .scan_with_tuple(None, move |section, item| {
97                // each section should emit only 1 value
98                if section == Some(item.section) {
99                    (section, None)
100                } else {
101                    (Some(item.section), Some(item))
102                }
103            })
104            .flatten()
105    }
106
107    /// Get all values without architecture from all sections.
108    fn shared_multi_no_arch_values(
109        query_iter: impl Iterator<Item = Self>,
110    ) -> impl Iterator<Item = QueryItem<'a, &'a str, ()>> {
111        query_iter.filter_map(QueryItem::into_without_architecture)
112    }
113}
114
115/// Return type of [`Checksums::checksums`] and [`ChecksumsMut::checksums_mut`].
116pub type QueryChecksumItem<'a> = QueryItem<'a, ChecksumValue<'a>, Option<value::Architecture<'a>>>;
117
118macro_rules! def_traits {
119    (
120        base single {$(
121            $base_single_name:ident, $base_single_name_mut:ident = $base_single_field:ident -> $base_single_type:ident;
122        )*}
123        base multi {$(
124            $base_multi_name:ident, $base_multi_name_mut:ident = $base_multi_field:ident -> $base_multi_type:ident;
125        )*}
126        shared single {$(
127            $shared_single_name:ident, $shared_single_name_mut:ident = $shared_single_field:ident -> $shared_single_type:ident;
128        )*}
129        shared multi no_arch {$(
130            $shared_multi_no_arch_name:ident, $shared_multi_no_arch_name_mut:ident = $shared_multi_no_arch_field:ident -> $shared_multi_no_arch_type:ident;
131        )*}
132        shared multi arch {$(
133            $shared_multi_arch_name:ident, $shared_multi_arch_name_mut:ident = $shared_multi_arch_field:ident -> $shared_multi_arch_type:ident;
134        )*}
135    ) => {
136        /// Get information from a querier of `.SRCINFO`.
137        pub trait Query<'a> {
138            fn query_raw_text(&self, field_name: FieldName) -> impl Iterator<Item = QueryRawTextItem<'a>>;
139
140            $(fn $base_single_name(&self) -> Option<value::$base_single_type<'a>> {
141                self.query_raw_text(FieldName::$base_single_field)
142                    .pipe(QueryRawTextItem::single_base_value)
143                    .map(value::$base_single_type::new)
144            })*
145
146            $(fn $base_multi_name(&self) -> impl Iterator<Item = value::$base_multi_type<'a>> {
147                self.query_raw_text(FieldName::$base_multi_field)
148                    .pipe(QueryRawTextItem::multi_base_values)
149                    .map(value::$base_multi_type::new)
150            })*
151
152            fn derivative_names(&self) -> impl Iterator<Item = value::Name<'a>> {
153                self.query_raw_text(FieldName::Name)
154                    .filter_map(QueryItem::into_without_architecture)
155                    .map(|item| item.value)
156                    .map(value::Name::new)
157            }
158
159            $(fn $shared_single_name(&self) -> impl Iterator<Item = QueryItem<'a, value::$shared_single_type<'a>, ()>> {
160                self.query_raw_text(FieldName::$shared_single_field)
161                    .pipe(QueryRawTextItem::shared_single_values)
162                    .map(|item| item.map(value::$shared_single_type::new))
163            })*
164
165            $(fn $shared_multi_no_arch_name(&self) -> impl Iterator<Item = QueryItem<'a, value::$shared_multi_no_arch_type<'a>, ()>> {
166                self.query_raw_text(FieldName::$shared_multi_no_arch_field)
167                    .pipe(QueryRawTextItem::shared_multi_no_arch_values)
168                    .map(|item| item.map(value::$shared_multi_no_arch_type::new))
169            })*
170
171            $(fn $shared_multi_arch_name(
172                &self,
173            ) -> impl Iterator<Item = QueryItem<'a, value::$shared_multi_arch_type<'a>, Option<value::Architecture<'a>>>> {
174                self.query_raw_text(FieldName::$shared_multi_arch_field)
175                    .map(|item| item.map(value::$shared_multi_arch_type::new))
176            })*
177        }
178
179        /// Get information from a querier of `.SRCINFO`, mutability required.
180        pub trait QueryMut<'a> {
181            fn query_raw_text_mut(&mut self, field_name: FieldName) -> impl Iterator<Item = QueryRawTextItem<'a>>;
182
183            $(fn $base_single_name_mut(&mut self) -> Option<value::$base_single_type<'a>> {
184                self.query_raw_text_mut(FieldName::$base_single_field)
185                    .pipe(QueryRawTextItem::single_base_value)
186                    .map(value::$base_single_type::new)
187            })*
188
189            $(fn $base_multi_name_mut(&mut self) -> impl Iterator<Item = value::$base_multi_type<'a>> {
190                self.query_raw_text_mut(FieldName::$base_multi_field)
191                    .pipe(QueryRawTextItem::multi_base_values)
192                    .map(value::$base_multi_type::new)
193            })*
194
195            fn derivative_names_mut(&mut self) -> impl Iterator<Item = value::Name<'a>> {
196                self.query_raw_text_mut(FieldName::Name)
197                    .filter_map(QueryItem::into_without_architecture)
198                    .map(|item| item.value)
199                    .map(value::Name::new)
200            }
201
202            $(fn $shared_single_name_mut(&mut self) -> impl Iterator<Item = QueryItem<'a, value::$shared_single_type<'a>, ()>> {
203                self.query_raw_text_mut(FieldName::$shared_single_field)
204                    .pipe(QueryRawTextItem::shared_single_values)
205                    .map(|item| item.map(value::$shared_single_type::new))
206            })*
207
208            $(fn $shared_multi_no_arch_name_mut(&mut self) -> impl Iterator<Item = QueryItem<'a, value::$shared_multi_no_arch_type<'a>,()>> {
209                self.query_raw_text_mut(FieldName::$shared_multi_no_arch_field)
210                    .pipe(QueryRawTextItem::shared_multi_no_arch_values)
211                    .map(|item| item.map(value::$shared_multi_no_arch_type::new))
212            })*
213
214            $(fn $shared_multi_arch_name_mut(
215                &mut self,
216            ) -> impl Iterator<Item = QueryItem<'a, value::$shared_multi_arch_type<'a>, Option<value::Architecture<'a>>>> {
217                self.query_raw_text_mut(FieldName::$shared_multi_arch_field)
218                    .map(|item| item.map(value::$shared_multi_arch_type::new))
219            })*
220        }
221    };
222}
223
224def_traits! {
225    base single {
226        base_name, base_name_mut = Base -> Base;
227        epoch, epoch_mut = Epoch -> Epoch;
228        release, release_mut = Release -> Release;
229        version, version_mut = Version -> UpstreamVersion;
230    }
231    base multi {
232        valid_pgp_keys, valid_pgp_keys_mut = ValidPgpKeys -> PgpKey;
233    }
234    shared single {
235        description, description_mut = Description -> Description;
236        change_log, change_log_mut = ChangeLog -> ChangeLog;
237        install_script, install_script_mut = InstallScript -> FileName;
238        url, url_mut = Url -> Url;
239    }
240    shared multi no_arch {
241        architecture, architecture_mut = Architecture -> Architecture;
242        backup, backup_mut = Backup -> FilePath;
243        groups, groups_mut = Groups -> Group;
244        license, license_mut = License -> License;
245        no_extract, no_extract_mut = NoExtract -> FileName;
246        options, options_mut = Options -> BuildOption;
247    }
248    shared multi arch {
249        /* MISC */
250        source, source_mut = Source -> Source;
251
252        /* DEPENDENCIES */
253        dependencies, dependencies_mut = Dependencies -> Dependency;
254        make_dependencies, make_dependencies_mut = MakeDependencies -> Dependency;
255        check_dependencies, check_dependencies_mut = CheckDependencies -> Dependency;
256        opt_dependencies, opt_dependencies_mut = OptionalDependencies -> DependencyAndReason;
257        provides, provides_mut = Provides -> Dependency;
258        conflicts, conflicts_mut = Conflicts -> Dependency;
259        replaces, replaces_mut = Replaces -> Dependency;
260
261        /* CHECKSUMS */
262        md5_checksums, md5_checksums_mut = Md5Checksums -> SkipOrHex128;
263        sha1_checksums, sha1_checksums_mut = Sha1Checksums -> SkipOrHex160;
264        sha224_checksums, sha224_checksums_mut = Sha224Checksums -> SkipOrHex224;
265        sha256_checksums, sha256_checksums_mut = Sha256Checksums -> SkipOrHex256;
266        sha384_checksums, sha384_checksums_mut = Sha384Checksums -> SkipOrHex384;
267        sha512_checksums, sha512_checksums_mut = Sha512Checksums -> SkipOrHex512;
268        blake2b_checksums, blake2b_checksums_mut = Blake2bChecksums -> SkipOrHex512;
269    }
270}
271
272/// Get checksums information from a querier of `.SRCINFO`.
273pub trait Checksums<'a>: ChecksumsMut<'a> {
274    fn checksums(&self) -> impl Iterator<Item = QueryChecksumItem<'a>>;
275}
276
277/// Get checksums information from a querier of `.SRCINFO`, mutability required.
278pub trait ChecksumsMut<'a> {
279    fn checksums_mut(&mut self) -> impl Iterator<Item = QueryChecksumItem<'a>>;
280}
281
282pub(crate) mod utils;
283
284mod generic;
285
286mod checksums;
287pub use checksums::*;
288
289mod forgetful;
290pub use forgetful::*;
291
292#[cfg(feature = "std")]
293mod memo;
294#[cfg(feature = "std")]
295pub use memo::*;
296
297#[cfg(feature = "std")]
298pub use crate::parse::ParsedSrcinfo as EagerQuerier;