use indexmap::{Equivalent, IndexMap};
use rattler_conda_types::{MatchSpec, NamelessMatchSpec, PackageName};
use std::hash::Hash;
#[derive(Default, Debug, Clone)]
pub struct Dependencies {
map: IndexMap<PackageName, Vec<NamelessMatchSpec>>,
}
impl From<IndexMap<PackageName, Vec<NamelessMatchSpec>>> for Dependencies {
fn from(map: IndexMap<PackageName, Vec<NamelessMatchSpec>>) -> Self {
Self { map }
}
}
impl From<IndexMap<PackageName, NamelessMatchSpec>> for Dependencies {
fn from(map: IndexMap<PackageName, NamelessMatchSpec>) -> Self {
Self {
map: map.into_iter().map(|(k, v)| (k, vec![v])).collect(),
}
}
}
impl Dependencies {
pub fn insert(&mut self, name: PackageName, spec: NamelessMatchSpec) {
self.map.entry(name).or_default().push(spec);
}
pub fn extend(&mut self, iter: impl IntoIterator<Item = (PackageName, NamelessMatchSpec)>) {
for (name, spec) in iter {
self.insert(name, spec);
}
}
pub fn extend_overwrite(
&mut self,
iter: impl IntoIterator<Item = (PackageName, NamelessMatchSpec)>,
) {
for (name, spec) in iter {
*self.map.entry(name).or_default() = vec![spec];
}
}
pub fn remove<Q: ?Sized>(&mut self, name: &Q) -> Option<(PackageName, Vec<NamelessMatchSpec>)>
where
Q: Hash + Equivalent<PackageName>,
{
self.map.shift_remove_entry(name)
}
pub fn union(&self, other: &Self) -> Self {
let mut map = self.map.clone();
for (name, specs) in other.map.iter() {
map.entry(name.clone()).or_default().extend(specs.clone());
}
Self { map }
}
pub fn overwrite(&self, other: &Self) -> Self {
let mut map = self.map.clone();
for (name, specs) in other.map.iter() {
map.insert(name.clone(), specs.clone());
}
Self { map }
}
pub fn iter(
&self,
) -> impl Iterator<Item = (&PackageName, &Vec<NamelessMatchSpec>)> + DoubleEndedIterator + '_
{
self.map.iter()
}
pub fn iter_specs(
&self,
) -> impl Iterator<Item = (&PackageName, &NamelessMatchSpec)> + DoubleEndedIterator + '_ {
self.map
.iter()
.flat_map(|(name, specs)| specs.iter().map(move |spec| (name, spec)))
}
pub fn names(
&self,
) -> impl Iterator<Item = &PackageName> + DoubleEndedIterator + ExactSizeIterator + '_ {
self.map.keys()
}
pub fn into_specs(
self,
) -> impl Iterator<Item = (PackageName, NamelessMatchSpec)> + DoubleEndedIterator {
self.map
.into_iter()
.flat_map(|(name, specs)| specs.into_iter().map(move |spec| (name.clone(), spec)))
}
pub fn into_match_specs(self) -> impl Iterator<Item = MatchSpec> + DoubleEndedIterator {
self.map.into_iter().flat_map(|(name, specs)| {
specs
.into_iter()
.map(move |spec| MatchSpec::from_nameless(spec, Some(name.clone())))
})
}
}
impl IntoIterator for Dependencies {
type Item = (PackageName, Vec<NamelessMatchSpec>);
type IntoIter = indexmap::map::IntoIter<PackageName, Vec<NamelessMatchSpec>>;
fn into_iter(self) -> Self::IntoIter {
self.map.into_iter()
}
}