#![deny(missing_docs)]
#![deny(unnameable_types)]
mod conditional_requirement;
pub mod conflict;
pub(crate) mod internal;
mod requirement;
pub mod runtime;
pub mod snapshot;
mod solver;
pub mod utils;
use std::{
any::Any,
fmt::{Debug, Display},
};
pub use conditional_requirement::{Condition, ConditionalRequirement, LogicalOperator};
pub use internal::arena::ArenaId;
pub use internal::id::{
ConditionId, NameId, SolvableId, SolvableOrRootId, StringId, VersionSetId, VersionSetUnionId,
};
use itertools::Itertools;
pub use requirement::Requirement;
pub use solver::{Problem, Solver, SolverCache, UnsolvableOrCancelled};
pub use utils::{Mapping, MappingIter};
pub trait Interner {
fn display_solvable(&self, solvable: SolvableId) -> impl Display + '_;
fn display_solvable_name(&self, solvable: SolvableId) -> impl Display + '_ {
self.display_name(self.solvable_name(solvable))
}
fn display_merged_solvables(&self, solvables: &[SolvableId]) -> impl Display + '_ {
if solvables.is_empty() {
return String::new();
}
let versions = solvables
.iter()
.map(|&id| self.display_solvable(id).to_string())
.sorted()
.unique()
.format(" | ");
let name = self.display_solvable_name(solvables[0]);
format!("{name} {versions}")
}
fn display_name(&self, name: NameId) -> impl Display + '_;
fn display_version_set(&self, version_set: VersionSetId) -> impl Display + '_;
fn display_string(&self, string_id: StringId) -> impl Display + '_;
fn version_set_name(&self, version_set: VersionSetId) -> NameId;
fn solvable_name(&self, solvable: SolvableId) -> NameId;
fn version_sets_in_union(
&self,
version_set_union: VersionSetUnionId,
) -> impl Iterator<Item = VersionSetId>;
fn resolve_condition(&self, condition: ConditionId) -> Condition;
}
#[allow(async_fn_in_trait)]
pub trait DependencyProvider: Sized + Interner {
async fn filter_candidates(
&self,
candidates: &[SolvableId],
version_set: VersionSetId,
inverse: bool,
) -> Vec<SolvableId>;
async fn get_candidates(&self, name: NameId) -> Option<Candidates>;
async fn sort_candidates(&self, solver: &SolverCache<Self>, solvables: &mut [SolvableId]);
async fn get_dependencies(&self, solvable: SolvableId) -> Dependencies;
fn should_cancel_with_value(&self) -> Option<Box<dyn Any>> {
None
}
}
#[derive(Default, Clone, Debug)]
pub struct Candidates {
pub candidates: Vec<SolvableId>,
pub favored: Option<SolvableId>,
pub locked: Option<SolvableId>,
pub hint_dependencies_available: HintDependenciesAvailable,
pub excluded: Vec<(SolvableId, StringId)>,
}
#[derive(Default, Clone, Debug)]
pub enum HintDependenciesAvailable {
#[default]
None,
All,
Some(Vec<SolvableId>),
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(untagged))]
pub enum Dependencies {
Known(KnownDependencies),
Unknown(StringId),
}
#[derive(Default, Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct KnownDependencies {
#[cfg_attr(
feature = "serde",
serde(default, skip_serializing_if = "Vec::is_empty")
)]
pub requirements: Vec<ConditionalRequirement>,
#[cfg_attr(
feature = "serde",
serde(default, skip_serializing_if = "Vec::is_empty")
)]
pub constrains: Vec<VersionSetId>,
}