#![deny(missing_docs)]
#![deny(unnameable_types)]
mod conditional_requirement;
pub mod conflict;
pub mod id;
pub(crate) mod internal;
mod requirement;
pub mod runtime;
pub mod snapshot;
mod solver;
pub mod solver_id;
pub mod utils;
use std::{
any::Any,
fmt::{Debug, Display},
};
pub use conditional_requirement::{Condition, ConditionalRequirement, LogicalOperator};
pub use id::{
ConditionId, DenseIndex, NameId, NameTag, SolvableId, SolvableTag, StringId, VariableId,
VersionSetId, VersionSetUnionId,
};
use itertools::Itertools;
pub use requirement::Requirement;
pub use solver::{EmptySolvables, Problem, Solver, SolverCache, UnsolvableOrCancelled};
pub use solver_id::{DenseId, IdMap, IdSet, SolverId, SparseId};
pub use utils::{IndexedSet, Mapping, MappingIter};
pub trait Interner {
type NameId: SolverId;
type SolvableId: SolverId;
fn display_solvable(&self, solvable: Self::SolvableId) -> impl Display + '_;
fn display_solvable_name(&self, solvable: Self::SolvableId) -> impl Display + '_ {
self.display_name(self.solvable_name(solvable))
}
fn display_merged_solvables(&self, solvables: &[Self::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: Self::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) -> Self::NameId;
fn solvable_name(&self, solvable: Self::SolvableId) -> Self::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: &[Self::SolvableId],
version_set: VersionSetId,
inverse: bool,
) -> Vec<Self::SolvableId>;
async fn get_candidates(&self, name: Self::NameId) -> Option<Candidates<Self::SolvableId>>;
async fn sort_candidates(&self, solver: &SolverCache<Self>, solvables: &mut [Self::SolvableId]);
async fn get_dependencies(&self, solvable: Self::SolvableId) -> Dependencies;
fn should_cancel_with_value(&self) -> Option<Box<dyn Any>> {
None
}
}
#[derive(Clone, Debug)]
pub struct Candidates<S = SolvableId> {
pub candidates: Vec<S>,
pub favored: Option<S>,
pub locked: Option<S>,
pub hint_dependencies_available: HintDependenciesAvailable<S>,
pub excluded: Vec<(S, StringId)>,
pub allow_multiple: bool,
}
impl<S> Default for Candidates<S> {
fn default() -> Self {
Self {
candidates: Vec::new(),
favored: None,
locked: None,
hint_dependencies_available: HintDependenciesAvailable::None,
excluded: Vec::new(),
allow_multiple: false,
}
}
}
#[derive(Default, Clone, Debug)]
pub enum HintDependenciesAvailable<S = SolvableId> {
#[default]
None,
All,
Some(Vec<S>),
}
#[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>,
}