use core::{
iter::{DoubleEndedIterator, FusedIterator},
num::{IntErrorKind, ParseIntError},
str::Split,
};
use derive_more::{AsRef, Deref, Display};
use parse_hex::ParseHex;
macro_rules! impl_str {
($container:ident) => {
impl<'a> $container<'a> {
pub fn new(text: &'a str) -> Self {
$container(text)
}
pub fn as_str(&self) -> &'a str {
&self.0.as_ref()
}
}
};
}
macro_rules! impl_hex {
($container:ident, $size:literal) => {
impl<'a> $container<'a> {
pub fn u8_array(self) -> Option<[u8; $size]> {
let (invalid, array) = ParseHex::parse_hex(self.0);
invalid.is_empty().then_some(array)
}
}
impl<'a> ParseArray for $container<'a> {
type Array = [u8; $size];
type Error = ();
fn parse_array(&self) -> Result<Self::Array, Self::Error> {
self.u8_array().ok_or(())
}
}
};
}
macro_rules! impl_srcinfo_checksum {
($container:ident, $size:literal) => {
impl<'a> $container<'a> {
pub fn u8_array(self) -> Option<SkipOrArray<$size>> {
if self.as_str() == "SKIP" {
return Some(SkipOrArray::Skip);
}
let (invalid, array) = ParseHex::parse_hex(self.0);
invalid.is_empty().then_some(SkipOrArray::Array(array))
}
}
impl<'a> ParseArray for $container<'a> {
type Array = SkipOrArray<$size>;
type Error = ();
fn parse_array(&self) -> Result<Self::Array, Self::Error> {
self.u8_array().ok_or(())
}
}
};
}
macro_rules! impl_num {
($container:ident, $num:ty) => {
impl_str!($container);
impl<'a> $container<'a> {
pub fn parse(&self) -> Result<$num, ParseIntError> {
let handle_error = |error: ParseIntError| match error.kind() {
IntErrorKind::Empty | IntErrorKind::Zero => Ok(0),
_ => Err(error),
};
self.as_str().parse().or_else(handle_error)
}
}
};
}
macro_rules! def_str_wrappers {
($(
$(#[$attrs:meta])*
$name:ident;
)*) => {$(
$(#[$attrs])*
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, AsRef, Deref)]
pub struct $name<'a>(pub &'a str);
impl_str!($name);
)*};
}
macro_rules! def_structured_wrappers {
($(
$(#[$attrs:meta])*
$name:ident;
)*) => {$(
$(#[$attrs])*
#[derive(Debug, Display, Clone, Copy, AsRef, Deref)]
pub struct $name<'a>(pub &'a str);
impl_str!($name);
)*};
}
macro_rules! def_hex_wrappers {
($(
$(#[$attrs:meta])*
$name:ident {
size = $size:literal;
}
)*) => {$(
$(#[$attrs])*
#[derive(Debug, Display, Clone, Copy, AsRef, Deref)]
pub struct $name<'a>(pub &'a str);
impl_str!($name);
impl_hex!($name, $size);
)*};
}
macro_rules! def_srcinfo_checksum_wrappers {
($(
$(#[$attrs:meta])*
$name:ident {
size = $size:literal;
}
)*) => {$(
$(#[$attrs])*
#[derive(Debug, Display, Clone, Copy, AsRef, Deref)]
pub struct $name<'a>(pub &'a str);
impl_str!($name);
impl_srcinfo_checksum!($name, $size);
)*};
}
macro_rules! def_b64_wrappers {
($(
$(#[$attrs:meta])*
$name:ident;
)*) => {$(
$(#[$attrs])*
#[derive(Debug, Display, Clone, Copy, AsRef, Deref)]
pub struct $name<'a>(pub &'a str);
impl_str!($name);
)*};
}
macro_rules! def_num_wrappers {
($(
$(#[$attrs:meta])*
$name:ident = $num:ty;
)*) => {$(
$(#[$attrs])*
#[derive(Debug, Display, Clone, Copy, AsRef, Deref)]
pub struct $name<'a>(&'a str);
impl_num!($name, $num);
)*};
}
macro_rules! def_list_wrappers {
($(
$(#[$container_attrs:meta])*
$container_name:ident {
$(#[$iter_attrs:meta])*
Iter = $iter_name:ident;
$(#[$item_attrs:meta])*
Item = $item_name:ident;
}
)*) => {$(
$(#[$container_attrs])*
#[derive(Debug, Clone, Copy)]
pub struct $container_name<'a>(&'a str);
impl<'a> $container_name<'a> {
pub fn new(text: &'a str) -> Self {
$container_name(text)
}
pub fn iter(&self) -> $iter_name<'_> {
self.into_iter()
}
}
impl<'a> IntoIterator for $container_name<'a> {
type IntoIter = $iter_name<'a>;
type Item = $item_name<'a>;
fn into_iter(self) -> Self::IntoIter {
$iter_name(self.0.split('\n'))
}
}
$(#[$iter_attrs])*
#[derive(Debug, Clone)]
pub struct $iter_name<'a>(Split<'a, char>);
impl<'a> Iterator for $iter_name<'a> {
type Item = $item_name<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map($item_name)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
impl<'a> DoubleEndedIterator for $iter_name<'a> {
fn next_back(&mut self) -> Option<Self::Item> {
self.0.next_back().map($item_name)
}
}
impl<'a> FusedIterator for $iter_name<'a> {}
$(#[$item_attrs])*
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, AsRef, Deref)]
pub struct $item_name<'a>(pub &'a str);
impl_str!($item_name);
)*};
}
def_str_wrappers! {
FileName;
Name;
Base;
Description;
Url;
Packager;
ChangeLog;
FilePath;
Source;
}
def_structured_wrappers! {
Version;
UpstreamVersion;
BuildOption;
PgpKey;
}
def_hex_wrappers! {
Hex128 {
size = 16;
}
Hex256 {
size = 32;
}
}
def_srcinfo_checksum_wrappers! {
SkipOrHex128 {
size = 16;
}
SkipOrHex160 {
size = 20;
}
SkipOrHex224 {
size = 28;
}
SkipOrHex256 {
size = 32;
}
SkipOrHex384 {
size = 48;
}
SkipOrHex512 {
size = 64;
}
}
def_b64_wrappers! {
PgpSignature;
}
def_num_wrappers! {
Size = u64;
Timestamp = u64;
Epoch = u64;
Release = u64; }
def_list_wrappers! {
GroupList {
Iter = GroupIterator;
Item = Group;
}
LicenseList {
Iter = LicenseIterator;
Item = License;
}
ArchitectureList {
Iter = ArchitectureIterator;
Item = Architecture;
}
DependencyList {
Iter = DependencyIterator;
Item = Dependency;
}
DependencyAndReasonList {
Iter = DependencyAndReasonIterator;
Item = DependencyAndReason;
}
}
def_str_wrappers! {
DependencyName;
DependencyReason;
DependencySpecification;
}
mod dependency;
mod dependency_and_reason;
mod dependency_name;
mod dependency_specification;
mod dependency_specification_operator;
mod hex128;
mod parse_array;
mod parse_hex;
mod skip_or_array;
mod upstream_version;
mod version;
pub use dependency_specification_operator::DependencySpecificationOperator;
pub use parse_array::ParseArray;
pub use skip_or_array::SkipOrArray;
pub use upstream_version::{
UpstreamVersionComponent, UpstreamVersionComponentIter, ValidUpstreamVersion,
ValidateUpstreamVersionError,
};
pub use version::{ParseVersionError, ParsedVersion, SplitVersionError};