1use crate::{srcinfo::field::FieldName, value};
2use iter_scan::IterScan;
3use pipe_trait::Pipe;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7pub enum Section<'a> {
8 Base,
10 Derivative(value::Name<'a>),
12}
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
16pub struct QueryItem<'a, Value, Architecture> {
17 pub value: Value,
19 pub section: Section<'a>,
21 pub architecture: Architecture,
23}
24
25impl<'a, Value, Architecture> QueryItem<'a, Value, Architecture> {
26 pub fn from_tuple3((value, section, architecture): (Value, Section<'a>, Architecture)) -> Self {
28 QueryItem {
29 value,
30 section,
31 architecture,
32 }
33 }
34
35 pub fn into_tuple3(self) -> (Value, Section<'a>, Architecture) {
37 (self.value, self.section, self.architecture)
38 }
39
40 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 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 pub fn from_tuple2((value, section): (Value, Section<'a>)) -> Self {
63 QueryItem::from_tuple3((value, section, ()))
64 }
65
66 pub fn into_tuple2(self) -> (Value, Section<'a>) {
68 let (value, section, ()) = self.into_tuple3();
69 (value, section)
70 }
71}
72
73pub type QueryRawTextItem<'a> = QueryItem<'a, &'a str, Option<value::Architecture<'a>>>;
75
76impl<'a> QueryRawTextItem<'a> {
77 fn single_base_value(query_iter: impl Iterator<Item = Self>) -> Option<&'a str> {
79 Self::multi_base_values(query_iter).next()
80 }
81
82 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 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 if section == Some(item.section) {
99 (section, None)
100 } else {
101 (Some(item.section), Some(item))
102 }
103 })
104 .flatten()
105 }
106
107 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
115pub 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 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 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 source, source_mut = Source -> Source;
251
252 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 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
272pub trait Checksums<'a>: ChecksumsMut<'a> {
274 fn checksums(&self) -> impl Iterator<Item = QueryChecksumItem<'a>>;
275}
276
277pub 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;