Skip to content

Commit

Permalink
add the basic setup for having multiple conditionals in a clause
Browse files Browse the repository at this point in the history
  • Loading branch information
prsabahrami committed Feb 3, 2025
1 parent cd3c9a3 commit 3d055c8
Show file tree
Hide file tree
Showing 4 changed files with 306 additions and 127 deletions.
17 changes: 17 additions & 0 deletions src/internal/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,23 @@ impl ArenaId for NameId {
}
}

/// The id associated to an extra
#[repr(transparent)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(transparent))]
pub struct ExtraId(pub u32);

impl ArenaId for ExtraId {
fn from_usize(x: usize) -> Self {
Self(x as u32)
}

fn to_usize(self) -> usize {
self.0 as usize
}
}

/// The id associated with a generic string
#[repr(transparent)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Ord, PartialOrd)]
Expand Down
39 changes: 23 additions & 16 deletions src/requirement.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
use crate::{Interner, VersionSetId, VersionSetUnionId};
use crate::{Interner, StringId, VersionSetId, VersionSetUnionId};
use itertools::Itertools;
use std::fmt::Display;

/// Specifies a conditional requirement, where the requirement is only active when the condition is met.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Condition {
VersionSetId(VersionSetId),
Extra(StringId),
}

/// Specifies a conditional requirement, where the requirement is only active when the condition is met.
#[derive(Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ConditionalRequirement {
/// The condition that must be met for the requirement to be active.
pub condition: Option<VersionSetId>,
/// The conditions that must be met for the requirement to be active.
pub conditions: Vec<Condition>,
/// The requirement that is only active when the condition is met.
pub requirement: Requirement,
}

impl ConditionalRequirement {
/// Creates a new conditional requirement.
pub fn new(condition: Option<VersionSetId>, requirement: Requirement) -> Self {
pub fn new(conditions: Vec<Condition>, requirement: Requirement) -> Self {
Self {
condition,
conditions,
requirement,
}
}
Expand All @@ -32,22 +39,22 @@ impl ConditionalRequirement {
pub fn version_sets_with_condition<'i>(
&'i self,
interner: &'i impl Interner,
) -> impl Iterator<Item = (VersionSetId, Option<VersionSetId>)> + 'i {
) -> impl Iterator<Item = (VersionSetId, Vec<Condition>)> + 'i {
self.requirement
.version_sets(interner)
.map(move |vs| (vs, self.condition))
.map(move |vs| (vs, self.conditions.clone()))
}

/// Returns the condition and requirement.
pub fn into_condition_and_requirement(self) -> (Option<VersionSetId>, Requirement) {
(self.condition, self.requirement)
pub fn into_condition_and_requirement(self) -> (Vec<Condition>, Requirement) {
(self.conditions, self.requirement)
}
}

impl From<Requirement> for ConditionalRequirement {
fn from(value: Requirement) -> Self {
Self {
condition: None,
conditions: vec![],
requirement: value,
}
}
Expand All @@ -56,7 +63,7 @@ impl From<Requirement> for ConditionalRequirement {
impl From<VersionSetId> for ConditionalRequirement {
fn from(value: VersionSetId) -> Self {
Self {
condition: None,
conditions: vec![],
requirement: value.into(),
}
}
Expand All @@ -65,16 +72,16 @@ impl From<VersionSetId> for ConditionalRequirement {
impl From<VersionSetUnionId> for ConditionalRequirement {
fn from(value: VersionSetUnionId) -> Self {
Self {
condition: None,
conditions: vec![],
requirement: value.into(),
}
}
}

impl From<(VersionSetId, Option<VersionSetId>)> for ConditionalRequirement {
fn from((requirement, condition): (VersionSetId, Option<VersionSetId>)) -> Self {
impl From<(VersionSetId, Vec<Condition>)> for ConditionalRequirement {
fn from((requirement, conditions): (VersionSetId, Vec<Condition>)) -> Self {
Self {
condition,
conditions,
requirement: requirement.into(),
}
}
Expand Down
45 changes: 44 additions & 1 deletion src/utils/pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::{
use crate::internal::{
arena::Arena,
frozen_copy_map::FrozenCopyMap,
id::{NameId, SolvableId, StringId, VersionSetId, VersionSetUnionId},
id::{ExtraId, NameId, SolvableId, StringId, VersionSetId, VersionSetUnionId},
small_vec::SmallVec,
};

Expand Down Expand Up @@ -43,6 +43,12 @@ pub struct Pool<VS: VersionSet, N: PackageName = String> {
/// Map from package names to the id of their interned counterpart
pub(crate) string_to_ids: FrozenCopyMap<String, StringId, ahash::RandomState>,

/// Interned extras
extras: Arena<ExtraId, (NameId, String)>,

/// Map from package names and their extras to the id of their interned counterpart
pub(crate) extra_to_ids: FrozenCopyMap<(NameId, String), ExtraId, ahash::RandomState>,

/// Interned match specs
pub(crate) version_sets: Arena<VersionSetId, (NameId, VS)>,

Expand All @@ -62,6 +68,8 @@ impl<VS: VersionSet, N: PackageName> Default for Pool<VS, N> {
package_names: Arena::new(),
strings: Arena::new(),
string_to_ids: Default::default(),
extras: Arena::new(),
extra_to_ids: Default::default(),
version_set_to_id: Default::default(),
version_sets: Arena::new(),
version_set_unions: Arena::new(),
Expand Down Expand Up @@ -116,13 +124,48 @@ impl<VS: VersionSet, N: PackageName> Pool<VS, N> {
next_id
}

/// Interns an extra into the [`Pool`], returning its [`StringId`]. Extras
/// are deduplicated. If the same extra is inserted twice the same
/// [`StringId`] will be returned.
///
/// The original extra can be resolved using the
/// [`Self::resolve_extra`] function.
pub fn intern_extra(
&self,
package_id: NameId,
extra_name: impl Into<String> + AsRef<str>,
) -> ExtraId {
if let Some(id) = self
.extra_to_ids
.get_copy(&(package_id, extra_name.as_ref().to_string()))
{
return id;
}

let extra = extra_name.into();
let id = self.extras.alloc((package_id, extra));
self.extra_to_ids.insert_copy((package_id, extra), id);
id
}

pub fn resolve_extra(&self, extra_id: ExtraId) -> &(NameId, String) {

Check failure on line 151 in src/utils/pool.rs

View workflow job for this annotation

GitHub Actions / Check intra-doc links

missing documentation for a method
&self.extras[extra_id]
}

/// Returns the package name associated with the provided [`NameId`].
///
/// Panics if the package name is not found in the pool.
pub fn resolve_package_name(&self, name_id: NameId) -> &N {
&self.package_names[name_id]
}

/// Returns the extra associated with the provided [`StringId`].
///
/// Panics if the extra is not found in the pool.
// pub fn resolve_extra(&self, package_id: NameId, extra_id: StringId) -> &str {
// &self.strings[self.extra_to_ids.get_copy(&(package_id, extra_id)).unwrap()]
// }

/// Returns the [`NameId`] associated with the specified name or `None` if
/// the name has not previously been interned using
/// [`Self::intern_package_name`].
Expand Down
Loading

0 comments on commit 3d055c8

Please sign in to comment.