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