arch_pkg_text/
value.rs

1//! Value types returned by the various queries on the different structured text formats.
2
3use core::{
4    iter::{DoubleEndedIterator, FusedIterator},
5    num::{IntErrorKind, ParseIntError},
6    str::Split,
7};
8use derive_more::{AsRef, Deref, Display};
9use parse_hex::ParseHex;
10
11macro_rules! impl_str {
12    ($container:ident) => {
13        impl<'a> $container<'a> {
14            /// Create the wrapper.
15            pub fn new(text: &'a str) -> Self {
16                $container(text)
17            }
18
19            /// Get an immutable reference to the raw string underneath.
20            pub fn as_str(&self) -> &'a str {
21                &self.0.as_ref()
22            }
23        }
24    };
25}
26
27macro_rules! impl_hex {
28    ($container:ident, $size:literal) => {
29        impl<'a> $container<'a> {
30            /// Convert the hex string into an array of 8-bit unsigned integers.
31            pub fn u8_array(self) -> Option<[u8; $size]> {
32                let (invalid, array) = ParseHex::parse_hex(self.0);
33                invalid.is_empty().then_some(array)
34            }
35        }
36
37        impl<'a> ParseArray for $container<'a> {
38            type Array = [u8; $size];
39            type Error = ();
40            fn parse_array(&self) -> Result<Self::Array, Self::Error> {
41                self.u8_array().ok_or(())
42            }
43        }
44    };
45}
46
47macro_rules! impl_srcinfo_checksum {
48    ($container:ident, $size:literal) => {
49        impl<'a> $container<'a> {
50            /// Convert the hex string into an array of 8-bit unsigned integers.
51            pub fn u8_array(self) -> Option<SkipOrArray<$size>> {
52                if self.as_str() == "SKIP" {
53                    return Some(SkipOrArray::Skip);
54                }
55                let (invalid, array) = ParseHex::parse_hex(self.0);
56                invalid.is_empty().then_some(SkipOrArray::Array(array))
57            }
58        }
59
60        impl<'a> ParseArray for $container<'a> {
61            type Array = SkipOrArray<$size>;
62            type Error = ();
63            fn parse_array(&self) -> Result<Self::Array, Self::Error> {
64                self.u8_array().ok_or(())
65            }
66        }
67    };
68}
69
70macro_rules! impl_num {
71    ($container:ident, $num:ty) => {
72        impl_str!($container);
73        impl<'a> $container<'a> {
74            /// Extract numeric value.
75            pub fn parse(&self) -> Result<$num, ParseIntError> {
76                let handle_error = |error: ParseIntError| match error.kind() {
77                    IntErrorKind::Empty | IntErrorKind::Zero => Ok(0),
78                    _ => Err(error),
79                };
80                self.as_str().parse().or_else(handle_error)
81            }
82        }
83    };
84}
85
86macro_rules! def_str_wrappers {
87    ($(
88        $(#[$attrs:meta])*
89        $name:ident;
90    )*) => {$(
91        $(#[$attrs])*
92        #[derive(Debug, Display, Clone, Copy, PartialEq, Eq, Hash, AsRef, Deref)]
93        pub struct $name<'a>(pub &'a str);
94        impl_str!($name);
95    )*};
96}
97
98macro_rules! def_hex_wrappers {
99    ($(
100        $(#[$attrs:meta])*
101        $name:ident {
102            size = $size:literal;
103        }
104    )*) => {$(
105        $(#[$attrs])*
106        #[derive(Debug, Display, Clone, Copy, AsRef, Deref)]
107        pub struct $name<'a>(pub &'a str);
108        impl_str!($name);
109        impl_hex!($name, $size);
110    )*};
111}
112
113macro_rules! def_srcinfo_checksum_wrappers {
114    ($(
115        $(#[$attrs:meta])*
116        $name:ident {
117            size = $size:literal;
118        }
119    )*) => {$(
120        $(#[$attrs])*
121        #[derive(Debug, Display, Clone, Copy, AsRef, Deref)]
122        pub struct $name<'a>(pub &'a str);
123        impl_str!($name);
124        impl_srcinfo_checksum!($name, $size);
125    )*};
126}
127
128macro_rules! def_b64_wrappers {
129    ($(
130        $(#[$attrs:meta])*
131        $name:ident;
132    )*) => {$(
133        $(#[$attrs])*
134        #[derive(Debug, Display, Clone, Copy, AsRef, Deref)]
135        pub struct $name<'a>(pub &'a str);
136        impl_str!($name);
137    )*};
138}
139
140macro_rules! def_num_wrappers {
141    ($(
142        $(#[$attrs:meta])*
143        $name:ident = $num:ty;
144    )*) => {$(
145        $(#[$attrs])*
146        #[derive(Debug, Display, Clone, Copy, AsRef, Deref)]
147        pub struct $name<'a>(&'a str);
148        impl_num!($name, $num);
149    )*};
150}
151
152macro_rules! def_list_wrappers {
153    ($(
154        $(#[$container_attrs:meta])*
155        $container_name:ident {
156            $(#[$iter_attrs:meta])*
157            Iter = $iter_name:ident;
158            $(#[$item_attrs:meta])*
159            Item = $item_name:ident;
160        }
161    )*) => {$(
162        $(#[$container_attrs])*
163        #[derive(Debug, Clone, Copy)]
164        pub struct $container_name<'a>(&'a str);
165
166        impl<'a> $container_name<'a> {
167            /// Create the wrapper.
168            pub fn new(text: &'a str) -> Self {
169                $container_name(text)
170            }
171
172            /// List the items.
173            pub fn iter(&self) -> $iter_name<'_> {
174                self.into_iter()
175            }
176        }
177
178        impl<'a> IntoIterator for $container_name<'a> {
179            type IntoIter = $iter_name<'a>;
180            type Item = $item_name<'a>;
181            fn into_iter(self) -> Self::IntoIter {
182                $iter_name(self.0.split('\n'))
183            }
184        }
185
186        $(#[$iter_attrs])*
187        #[derive(Debug, Clone)]
188        pub struct $iter_name<'a>(Split<'a, char>);
189
190        impl<'a> Iterator for $iter_name<'a> {
191            type Item = $item_name<'a>;
192            fn next(&mut self) -> Option<Self::Item> {
193                self.0.next().map($item_name)
194            }
195            fn size_hint(&self) -> (usize, Option<usize>) {
196                self.0.size_hint()
197            }
198        }
199
200        impl<'a> DoubleEndedIterator for $iter_name<'a> {
201            fn next_back(&mut self) -> Option<Self::Item> {
202                self.0.next_back().map($item_name)
203            }
204        }
205
206        impl<'a> FusedIterator for $iter_name<'a> {}
207
208        $(#[$item_attrs])*
209        #[derive(Debug, Display, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, AsRef, Deref)]
210        pub struct $item_name<'a>(pub &'a str);
211        impl_str!($item_name);
212    )*};
213}
214
215def_str_wrappers! {
216    /// Type of value of `FILENAME`, `noextract`, and `install`.
217    FileName;
218    /// Type of value of `NAME` and `pkgname`.
219    Name;
220    /// Type of value of `BASE` and `pkgbase`.
221    Base;
222    /// Type of value of `VERSION`.
223    Version;
224    /// Type of value of `pkgver`.
225    UpstreamVersion;
226    /// Type of value of `DESC` and `pkgdesc`.
227    Description;
228    /// Type of value of `URL`.
229    Url;
230    /// Type of value of `PACKAGER`.
231    Packager;
232    /// Type of value of `changelog`.
233    ChangeLog;
234    /// Type of value of `options`.
235    BuildOption;
236    /// Type of value of `backup`.
237    FilePath;
238    /// Type of value of `source`.
239    Source;
240    /// Type of value of `validpgpkeys`.
241    PgpKey;
242}
243
244def_hex_wrappers! {
245    /// Type of value of `MD5SUM`.
246    Hex128 {
247        size = 16;
248    }
249    /// Type of value of `SHA256SUM`.
250    Hex256 {
251        size = 32;
252    }
253}
254
255def_srcinfo_checksum_wrappers! {
256    /// Type of value of `md5sums`.
257    SkipOrHex128 {
258        size = 16;
259    }
260    /// Type of value of `sha1sums`.
261    SkipOrHex160 {
262        size = 20;
263    }
264    /// Type of value of `sha224sums`.
265    SkipOrHex224 {
266        size = 28;
267    }
268    /// Type of value of `sha256sums`.
269    SkipOrHex256 {
270        size = 32;
271    }
272    /// Type of value of `sha384sums`.
273    SkipOrHex384 {
274        size = 48;
275    }
276    /// Type of value of `sha512sums` and `b2sums`.
277    SkipOrHex512 {
278        size = 64;
279    }
280}
281
282def_b64_wrappers! {
283    /// Type of value of `PGPSIG`.
284    PgpSignature;
285}
286
287def_num_wrappers! {
288    /// Type of value of `CSIZE` and `ISIZE`.
289    Size = u64;
290    /// Type of value of `BUILDDATE`.
291    Timestamp = u64;
292    /// Type of value of `epoch`.
293    Epoch = u64;
294    /// Type of value of `pkgrel`.
295    Release = u64; // TODO: change this to allow `a.b` syntax
296}
297
298def_list_wrappers! {
299    /// Type of value of `GROUPS`.
300    GroupList {
301        /// [Iterator] type of [`GroupList`].
302        Iter = GroupIterator;
303        /// Type of [iterator item](Iterator::Item) of [`GroupList`] and value of `groups`.
304        Item = Group;
305    }
306
307    /// Type of value of `LICENSE`.
308    LicenseList {
309        /// [Iterator] type of [`LicenseList`].
310        Iter = LicenseIterator;
311        /// Type of [iterator item](Iterator::Item) of [`LicenseList`] and value of `license`.
312        Item = License;
313    }
314
315    /// Type of value of `ARCH`.
316    ArchitectureList {
317        /// [Iterator] type of [`ArchitectureList`].
318        Iter = ArchitectureIterator;
319        /// Type of [iterator item](Iterator::Item) of [`ArchitectureList`] and value of `arch`.
320        Item = Architecture;
321    }
322
323    /// Type of value of `DEPENDS`, `MAKEDEPENDS`, `CHECKDEPENDS`, `PROVIDES`, `CONFLICTS`, and `REPLACES`.
324    DependencyList {
325        /// [Iterator] type of [`DependencyList`].
326        Iter = DependencyIterator;
327        /// Type of [iterator item](Iterator::Item) of [`DependencyList`].
328        Item = Dependency;
329    }
330
331    /// Type of value of `OPTDEPENDS`.
332    DependencyAndReasonList {
333        /// [Iterator] type of [`DependencyAndReasonList`].
334        Iter = DependencyAndReasonIterator;
335        /// Type of [iterator item](Iterator::Item) of [`DependencyAndReasonList`].
336        Item = DependencyAndReason;
337    }
338}
339
340def_str_wrappers! {
341    /// Name of a [dependency](Dependency). It could either be a [package name](Name) or a soname of a library.
342    DependencyName;
343    /// Reason for installing a [dependency](DependencyAndReason).
344    DependencyReason;
345    /// Specification of a [dependency](DependencyName).
346    DependencySpecification;
347}
348
349mod dependency;
350mod dependency_and_reason;
351mod dependency_name;
352mod dependency_specification;
353mod dependency_specification_operator;
354mod hex128;
355mod parse_array;
356mod parse_hex;
357mod skip_or_array;
358mod upstream_version;
359mod version;
360
361pub use dependency_specification_operator::DependencySpecificationOperator;
362pub use parse_array::ParseArray;
363pub use skip_or_array::SkipOrArray;
364pub use upstream_version::{
365    UpstreamVersionComponent, UpstreamVersionComponentIter, ValidUpstreamVersion,
366    ValidateUpstreamVersionError,
367};
368pub use version::{ParseVersionError, ParsedVersion, SplitVersionError};