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, PartialOrd, Ord, Hash, AsRef, Deref)]
93        pub struct $name<'a>(pub &'a str);
94        impl_str!($name);
95    )*};
96}
97
98macro_rules! def_structured_wrappers {
99    ($(
100        $(#[$attrs:meta])*
101        $name:ident;
102    )*) => {$(
103        $(#[$attrs])*
104        #[derive(Debug, Display, Clone, Copy, AsRef, Deref)]
105        pub struct $name<'a>(pub &'a str);
106        impl_str!($name);
107    )*};
108}
109
110macro_rules! def_hex_wrappers {
111    ($(
112        $(#[$attrs:meta])*
113        $name:ident {
114            size = $size:literal;
115        }
116    )*) => {$(
117        $(#[$attrs])*
118        #[derive(Debug, Display, Clone, Copy, AsRef, Deref)]
119        pub struct $name<'a>(pub &'a str);
120        impl_str!($name);
121        impl_hex!($name, $size);
122    )*};
123}
124
125macro_rules! def_srcinfo_checksum_wrappers {
126    ($(
127        $(#[$attrs:meta])*
128        $name:ident {
129            size = $size:literal;
130        }
131    )*) => {$(
132        $(#[$attrs])*
133        #[derive(Debug, Display, Clone, Copy, AsRef, Deref)]
134        pub struct $name<'a>(pub &'a str);
135        impl_str!($name);
136        impl_srcinfo_checksum!($name, $size);
137    )*};
138}
139
140macro_rules! def_b64_wrappers {
141    ($(
142        $(#[$attrs:meta])*
143        $name:ident;
144    )*) => {$(
145        $(#[$attrs])*
146        #[derive(Debug, Display, Clone, Copy, AsRef, Deref)]
147        pub struct $name<'a>(pub &'a str);
148        impl_str!($name);
149    )*};
150}
151
152macro_rules! def_num_wrappers {
153    ($(
154        $(#[$attrs:meta])*
155        $name:ident = $num:ty;
156    )*) => {$(
157        $(#[$attrs])*
158        #[derive(Debug, Display, Clone, Copy, AsRef, Deref)]
159        pub struct $name<'a>(&'a str);
160        impl_num!($name, $num);
161    )*};
162}
163
164macro_rules! def_list_wrappers {
165    ($(
166        $(#[$container_attrs:meta])*
167        $container_name:ident {
168            $(#[$iter_attrs:meta])*
169            Iter = $iter_name:ident;
170            $(#[$item_attrs:meta])*
171            Item = $item_name:ident;
172        }
173    )*) => {$(
174        $(#[$container_attrs])*
175        #[derive(Debug, Clone, Copy)]
176        pub struct $container_name<'a>(&'a str);
177
178        impl<'a> $container_name<'a> {
179            /// Create the wrapper.
180            pub fn new(text: &'a str) -> Self {
181                $container_name(text)
182            }
183
184            /// List the items.
185            pub fn iter(&self) -> $iter_name<'_> {
186                self.into_iter()
187            }
188        }
189
190        impl<'a> IntoIterator for $container_name<'a> {
191            type IntoIter = $iter_name<'a>;
192            type Item = $item_name<'a>;
193            fn into_iter(self) -> Self::IntoIter {
194                $iter_name(self.0.split('\n'))
195            }
196        }
197
198        $(#[$iter_attrs])*
199        #[derive(Debug, Clone)]
200        pub struct $iter_name<'a>(Split<'a, char>);
201
202        impl<'a> Iterator for $iter_name<'a> {
203            type Item = $item_name<'a>;
204            fn next(&mut self) -> Option<Self::Item> {
205                self.0.next().map($item_name)
206            }
207            fn size_hint(&self) -> (usize, Option<usize>) {
208                self.0.size_hint()
209            }
210        }
211
212        impl<'a> DoubleEndedIterator for $iter_name<'a> {
213            fn next_back(&mut self) -> Option<Self::Item> {
214                self.0.next_back().map($item_name)
215            }
216        }
217
218        impl<'a> FusedIterator for $iter_name<'a> {}
219
220        $(#[$item_attrs])*
221        #[derive(Debug, Display, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, AsRef, Deref)]
222        pub struct $item_name<'a>(pub &'a str);
223        impl_str!($item_name);
224    )*};
225}
226
227def_str_wrappers! {
228    /// Type of value of `FILENAME`, `noextract`, and `install`.
229    FileName;
230    /// Type of value of `NAME` and `pkgname`.
231    Name;
232    /// Type of value of `BASE` and `pkgbase`.
233    Base;
234    /// Type of value of `DESC` and `pkgdesc`.
235    Description;
236    /// Type of value of `URL`.
237    Url;
238    /// Type of value of `PACKAGER`.
239    Packager;
240    /// Type of value of `changelog`.
241    ChangeLog;
242    /// Type of value of `backup`.
243    FilePath;
244    /// Type of value of `source`.
245    Source;
246}
247
248def_structured_wrappers! {
249    /// Type of value of `VERSION`.
250    Version;
251    /// Type of value of `pkgver`.
252    UpstreamVersion;
253    /// Type of value of `options`.
254    BuildOption;
255    /// Type of value of `validpgpkeys`.
256    PgpKey;
257}
258
259def_hex_wrappers! {
260    /// Type of value of `MD5SUM`.
261    Hex128 {
262        size = 16;
263    }
264    /// Type of value of `SHA256SUM`.
265    Hex256 {
266        size = 32;
267    }
268}
269
270def_srcinfo_checksum_wrappers! {
271    /// Type of value of `md5sums`.
272    SkipOrHex128 {
273        size = 16;
274    }
275    /// Type of value of `sha1sums`.
276    SkipOrHex160 {
277        size = 20;
278    }
279    /// Type of value of `sha224sums`.
280    SkipOrHex224 {
281        size = 28;
282    }
283    /// Type of value of `sha256sums`.
284    SkipOrHex256 {
285        size = 32;
286    }
287    /// Type of value of `sha384sums`.
288    SkipOrHex384 {
289        size = 48;
290    }
291    /// Type of value of `sha512sums` and `b2sums`.
292    SkipOrHex512 {
293        size = 64;
294    }
295}
296
297def_b64_wrappers! {
298    /// Type of value of `PGPSIG`.
299    PgpSignature;
300}
301
302def_num_wrappers! {
303    /// Type of value of `CSIZE` and `ISIZE`.
304    Size = u64;
305    /// Type of value of `BUILDDATE`.
306    Timestamp = u64;
307    /// Type of value of `epoch`.
308    Epoch = u64;
309    /// Type of value of `pkgrel`.
310    Release = u64; // TODO: change this to allow `a.b` syntax
311}
312
313def_list_wrappers! {
314    /// Type of value of `GROUPS`.
315    GroupList {
316        /// [Iterator] type of [`GroupList`].
317        Iter = GroupIterator;
318        /// Type of [iterator item](Iterator::Item) of [`GroupList`] and value of `groups`.
319        Item = Group;
320    }
321
322    /// Type of value of `LICENSE`.
323    LicenseList {
324        /// [Iterator] type of [`LicenseList`].
325        Iter = LicenseIterator;
326        /// Type of [iterator item](Iterator::Item) of [`LicenseList`] and value of `license`.
327        Item = License;
328    }
329
330    /// Type of value of `ARCH`.
331    ArchitectureList {
332        /// [Iterator] type of [`ArchitectureList`].
333        Iter = ArchitectureIterator;
334        /// Type of [iterator item](Iterator::Item) of [`ArchitectureList`] and value of `arch`.
335        Item = Architecture;
336    }
337
338    /// Type of value of `DEPENDS`, `MAKEDEPENDS`, `CHECKDEPENDS`, `PROVIDES`, `CONFLICTS`, and `REPLACES`.
339    DependencyList {
340        /// [Iterator] type of [`DependencyList`].
341        Iter = DependencyIterator;
342        /// Type of [iterator item](Iterator::Item) of [`DependencyList`].
343        Item = Dependency;
344    }
345
346    /// Type of value of `OPTDEPENDS`.
347    DependencyAndReasonList {
348        /// [Iterator] type of [`DependencyAndReasonList`].
349        Iter = DependencyAndReasonIterator;
350        /// Type of [iterator item](Iterator::Item) of [`DependencyAndReasonList`].
351        Item = DependencyAndReason;
352    }
353}
354
355def_str_wrappers! {
356    /// Name of a [dependency](Dependency). It could either be a [package name](Name) or a soname of a library.
357    DependencyName;
358    /// Reason for installing a [dependency](DependencyAndReason).
359    DependencyReason;
360    /// Specification of a [dependency](DependencyName).
361    DependencySpecification;
362}
363
364mod dependency;
365mod dependency_and_reason;
366mod dependency_name;
367mod dependency_specification;
368mod dependency_specification_operator;
369mod hex128;
370mod parse_array;
371mod parse_hex;
372mod skip_or_array;
373mod upstream_version;
374mod version;
375
376pub use dependency_specification_operator::DependencySpecificationOperator;
377pub use parse_array::ParseArray;
378pub use skip_or_array::SkipOrArray;
379pub use upstream_version::{
380    UpstreamVersionComponent, UpstreamVersionComponentIter, ValidUpstreamVersion,
381    ValidateUpstreamVersionError,
382};
383pub use version::{ParseVersionError, ParsedVersion, SplitVersionError};