use std::ops::Deref;
#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ArchVecs {
pub(crate) vecs: Vec<ArchVec>,
}
impl Deref for ArchVecs {
type Target = [ArchVec];
fn deref(&self) -> &Self::Target {
&self.vecs
}
}
impl<'a> IntoIterator for &'a ArchVecs {
type IntoIter = <&'a Vec<ArchVec> as IntoIterator>::IntoIter;
type Item = &'a ArchVec;
fn into_iter(self) -> Self::IntoIter {
self.vecs.iter()
}
}
impl From<Vec<ArchVec>> for ArchVecs {
fn from(vecs: Vec<ArchVec>) -> Self {
ArchVecs { vecs }
}
}
impl ArchVecs {
pub fn new() -> Self {
Self::default()
}
pub fn get_any(&self) -> Option<&ArchVec> {
self.vecs
.iter()
.find(|v| v.arch() == None)
}
pub fn get<S: AsRef<str>>(&self, arch: Option<S>) -> Option<&ArchVec> {
self.vecs
.iter()
.find(|v| v.arch() == arch.as_ref().map(|a| a.as_ref()))
}
pub fn arch<S: AsRef<str>>(&self, arch: S) -> impl Iterator<Item = &str> {
self.vecs
.iter()
.filter(move |v| v.supports(arch.as_ref()))
.flatten()
}
pub fn all(&self) -> impl Iterator<Item = &str> {
self.vecs.iter().flatten()
}
pub fn any(&self) -> impl Iterator<Item = &str> {
self.get_any()
.map(|v| v.iter())
.unwrap_or_default()
}
}
#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ArchVec {
pub(crate) arch: Option<String>,
pub(crate) values: Vec<String>,
}
impl Default for &ArchVec {
fn default() -> Self {
static EMPTY: ArchVec = ArchVec { arch: None, values: Vec::new() };
&EMPTY
}
}
#[derive(Clone, Debug, Default)]
pub struct ArchVecIter<'a>(std::slice::Iter<'a, String>);
impl<'a> Iterator for ArchVecIter<'a> {
type Item = &'a str;
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(String::as_str)
}
}
impl<'a> IntoIterator for &'a ArchVec {
type IntoIter = ArchVecIter<'a>;
type Item = &'a str;
fn into_iter(self) -> Self::IntoIter {
ArchVecIter(self.values.iter())
}
}
impl From<String> for ArchVec {
fn from(value: String) -> Self {
ArchVec::new(Some(value))
}
}
impl From<&str> for ArchVec {
fn from(value: &str) -> Self {
ArchVec::new(Some(value))
}
}
impl From<Option<String>> for ArchVec {
fn from(value: Option<String>) -> Self {
ArchVec::new(value)
}
}
impl From<Option<&str>> for ArchVec {
fn from(value: Option<&str>) -> Self {
ArchVec::new(value)
}
}
impl ArchVec {
pub fn new<S: Into<String>>(arch: Option<S>) -> ArchVec {
let arch = arch.map(|x| x.into());
ArchVec {
arch,
values: Vec::new(),
}
}
pub fn with_values<S: Into<String>>(arch: Option<S>, values: Vec<String>) -> ArchVec {
let arch = arch.map(|x| x.into());
ArchVec { arch, values }
}
pub fn iter(&self) -> ArchVecIter<'_> {
self.into_iter()
}
pub fn values(&self) -> &[String] {
&self.values
}
pub fn arch(&self) -> Option<&str> {
self.arch.as_deref()
}
pub fn supports<S: AsRef<str>>(&self, s: S) -> bool {
self.arch().is_none_or(|a| a == s.as_ref())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Srcinfo;
#[test]
fn test_archvec() {
let av = ArchVec::from("x86_64");
assert!(av.supports("x86_64"));
let av = ArchVec::default();
assert!(av.supports("x86_64"));
let av = ArchVec::from("i686");
assert!(!av.supports("x86_64"));
let srcinfo: Srcinfo = include_str!("../tests/srcinfo/libc++").parse().unwrap();
let depends = srcinfo.makedepends().arch("x86_64").collect::<Vec<_>>();
let expected = vec!["clang", "cmake", "ninja", "python", "libunwind"];
assert_eq!(expected, depends);
}
}