aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe-semver/src/intervals.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/shirabe-semver/src/intervals.rs')
-rw-r--r--crates/shirabe-semver/src/intervals.rs249
1 files changed, 114 insertions, 135 deletions
diff --git a/crates/shirabe-semver/src/intervals.rs b/crates/shirabe-semver/src/intervals.rs
index 72231b6..68b23bf 100644
--- a/crates/shirabe-semver/src/intervals.rs
+++ b/crates/shirabe-semver/src/intervals.rs
@@ -3,11 +3,11 @@
use std::collections::HashMap;
use std::sync::{Mutex, OnceLock};
-use crate::constraint::Constraint;
-use crate::constraint::ConstraintInterface;
+use crate::constraint::AnyConstraint;
use crate::constraint::MatchAllConstraint;
use crate::constraint::MatchNoneConstraint;
use crate::constraint::MultiConstraint;
+use crate::constraint::SimpleConstraint;
use crate::interval::{DevConstraintSet, Interval};
use shirabe_php_shim as php;
@@ -42,31 +42,19 @@ impl Intervals {
}
pub fn is_subset_of(
- candidate: &dyn ConstraintInterface,
- constraint: &dyn ConstraintInterface,
+ candidate: &AnyConstraint,
+ constraint: &AnyConstraint,
) -> anyhow::Result<bool> {
- if constraint
- .as_any()
- .downcast_ref::<MatchAllConstraint>()
- .is_some()
- {
+ if constraint.is_match_all() {
return Ok(true);
}
- if candidate
- .as_any()
- .downcast_ref::<MatchNoneConstraint>()
- .is_some()
- || constraint
- .as_any()
- .downcast_ref::<MatchNoneConstraint>()
- .is_some()
- {
+ if candidate.is_match_none() || constraint.is_match_none() {
return Ok(false);
}
- // Phase B: ConstraintInterface needs clone_box() to create owned copies from references.
- let multi = MultiConstraint::new(vec![candidate.clone_box(), constraint.clone_box()], true);
+ let multi =
+ MultiConstraint::new(vec![candidate.clone(), constraint.clone()], true, None).into();
let intersection_intervals = Self::get(&multi)?;
let candidate_intervals = Self::get(candidate)?;
@@ -79,14 +67,14 @@ impl Intervals {
return Ok(false);
}
- if candidate_intervals.numeric[index].get_start().__to_string()
- != interval.get_start().__to_string()
+ if candidate_intervals.numeric[index].get_start().to_string()
+ != interval.get_start().to_string()
{
return Ok(false);
}
- if candidate_intervals.numeric[index].get_end().__to_string()
- != interval.get_end().__to_string()
+ if candidate_intervals.numeric[index].get_end().to_string()
+ != interval.get_end().to_string()
{
return Ok(false);
}
@@ -107,24 +95,16 @@ impl Intervals {
Ok(true)
}
- pub fn have_intersections(
- a: &dyn ConstraintInterface,
- b: &dyn ConstraintInterface,
- ) -> anyhow::Result<bool> {
- if a.as_any().downcast_ref::<MatchAllConstraint>().is_some()
- || b.as_any().downcast_ref::<MatchAllConstraint>().is_some()
- {
+ pub fn have_intersections(a: &AnyConstraint, b: &AnyConstraint) -> anyhow::Result<bool> {
+ if a.is_match_all() || b.is_match_all() {
return Ok(true);
}
- if a.as_any().downcast_ref::<MatchNoneConstraint>().is_some()
- || b.as_any().downcast_ref::<MatchNoneConstraint>().is_some()
- {
+ if a.is_match_none() || b.is_match_none() {
return Ok(false);
}
- // Phase B: ConstraintInterface needs clone_box().
- let multi = MultiConstraint::new(vec![a.clone_box(), b.clone_box()], true);
+ let multi = MultiConstraint::new(vec![a.clone(), b.clone()], true, None).into();
let intersection_intervals = Self::generate_intervals(&multi, true)?;
Ok(!intersection_intervals.numeric.is_empty()
@@ -132,30 +112,24 @@ impl Intervals {
|| !intersection_intervals.branches.names.is_empty())
}
- pub fn compact_constraint(
- constraint: &dyn ConstraintInterface,
- ) -> anyhow::Result<Box<dyn ConstraintInterface>> {
- if constraint
- .as_any()
- .downcast_ref::<MultiConstraint>()
- .is_none()
- {
- return Ok(constraint.clone_box());
+ pub fn compact_constraint(constraint: &AnyConstraint) -> anyhow::Result<AnyConstraint> {
+ if constraint.as_multi_constraint().is_none() {
+ return Ok(constraint.clone());
}
let intervals = Self::generate_intervals(constraint, false)?;
- let mut constraints: Vec<Box<dyn ConstraintInterface>> = Vec::new();
+ let mut constraints: Vec<AnyConstraint> = Vec::new();
let mut has_numeric_match_all = false;
if intervals.numeric.len() == 1
- && intervals.numeric[0].get_start().__to_string() == Interval::from_zero().__to_string()
- && intervals.numeric[0].get_end().__to_string()
- == Interval::until_positive_infinity().__to_string()
+ && intervals.numeric[0].get_start().to_string() == Interval::from_zero().to_string()
+ && intervals.numeric[0].get_end().to_string()
+ == Interval::until_positive_infinity().to_string()
{
- constraints.push(Box::new(intervals.numeric[0].get_start().clone()));
+ constraints.push(intervals.numeric[0].get_start().clone().into());
has_numeric_match_all = true;
} else {
- let mut un_equal_constraints: Vec<Box<dyn ConstraintInterface>> = Vec::new();
+ let mut un_equal_constraints: Vec<AnyConstraint> = Vec::new();
let count = intervals.numeric.len();
let mut i = 0;
while i < count {
@@ -176,15 +150,18 @@ impl Intervals {
// unEqualConstraints currently contains [>=M, !=N] already and we only
// want to add !=P right now
if un_equal_constraints.is_empty()
- && interval.get_start().__to_string()
- != Interval::from_zero().__to_string()
+ && interval.get_start().to_string() != Interval::from_zero().to_string()
{
- un_equal_constraints.push(Box::new(interval.get_start().clone()));
+ un_equal_constraints.push(interval.get_start().clone().into());
}
- un_equal_constraints.push(Box::new(Constraint::new(
- "!=".to_string(),
- interval.get_end().get_version().to_string(),
- )));
+ un_equal_constraints.push(
+ SimpleConstraint::new(
+ "!=".to_string(),
+ interval.get_end().get_version().to_string(),
+ None,
+ )
+ .into(),
+ );
i += 1;
continue;
}
@@ -192,16 +169,16 @@ impl Intervals {
if !un_equal_constraints.is_empty() {
// this is where the end of the following interval of a != constraint is added
- if interval.get_end().__to_string()
- != Interval::until_positive_infinity().__to_string()
+ if interval.get_end().to_string()
+ != Interval::until_positive_infinity().to_string()
{
- un_equal_constraints.push(Box::new(interval.get_end().clone()));
+ un_equal_constraints.push(interval.get_end().clone().into());
}
// count is 1 if entire constraint is just one != expression
if un_equal_constraints.len() > 1 {
constraints
- .push(Box::new(MultiConstraint::new(un_equal_constraints, true)));
+ .push(MultiConstraint::new(un_equal_constraints, true, None).into());
} else {
constraints.push(un_equal_constraints.into_iter().next().unwrap());
}
@@ -216,55 +193,59 @@ impl Intervals {
&& interval.get_start().get_operator() == ">="
&& interval.get_end().get_operator() == "<="
{
- constraints.push(Box::new(Constraint::new(
- "==".to_string(),
- interval.get_start().get_version().to_string(),
- )));
+ constraints.push(
+ SimpleConstraint::new(
+ "==".to_string(),
+ interval.get_start().get_version().to_string(),
+ None,
+ )
+ .into(),
+ );
i += 1;
continue;
}
- if interval.get_start().__to_string() == Interval::from_zero().__to_string() {
- constraints.push(Box::new(interval.get_end().clone()));
- } else if interval.get_end().__to_string()
- == Interval::until_positive_infinity().__to_string()
+ if interval.get_start().to_string() == Interval::from_zero().to_string() {
+ constraints.push(interval.get_end().clone().into());
+ } else if interval.get_end().to_string()
+ == Interval::until_positive_infinity().to_string()
{
- constraints.push(Box::new(interval.get_start().clone()));
+ constraints.push(interval.get_start().clone().into());
} else {
- constraints.push(Box::new(MultiConstraint::new(
- vec![
- Box::new(interval.get_start().clone()),
- Box::new(interval.get_end().clone()),
- ],
- true,
- )));
+ constraints.push(
+ MultiConstraint::new(
+ vec![
+ AnyConstraint::Simple(interval.get_start().clone()),
+ AnyConstraint::Simple(interval.get_end().clone()),
+ ],
+ true,
+ None,
+ )
+ .into(),
+ );
}
i += 1;
}
}
- let mut dev_constraints: Vec<Box<dyn ConstraintInterface>> = Vec::new();
+ let mut dev_constraints: Vec<AnyConstraint> = Vec::new();
if intervals.branches.names.is_empty() {
if intervals.branches.exclude && has_numeric_match_all {
- return Ok(Box::new(MatchAllConstraint {
- pretty_string: None,
- }));
+ return Ok(MatchAllConstraint::new(None).into());
// otherwise constraint should contain a != operator and already cover this
}
} else {
for branch_name in &intervals.branches.names {
if intervals.branches.exclude {
- dev_constraints.push(Box::new(Constraint::new(
- "!=".to_string(),
- branch_name.clone(),
- )));
+ dev_constraints.push(
+ SimpleConstraint::new("!=".to_string(), branch_name.clone(), None).into(),
+ );
} else {
- dev_constraints.push(Box::new(Constraint::new(
- "==".to_string(),
- branch_name.clone(),
- )));
+ dev_constraints.push(
+ SimpleConstraint::new("==".to_string(), branch_name.clone(), None).into(),
+ );
}
}
@@ -272,26 +253,25 @@ impl Intervals {
// > 2.0 != dev-foo must return a conjunctive constraint
if intervals.branches.exclude {
if constraints.len() > 1 {
- let merged: Vec<Box<dyn ConstraintInterface>> =
- std::iter::once(Box::new(MultiConstraint::new(constraints, false))
- as Box<dyn ConstraintInterface>)
- .chain(dev_constraints)
- .collect();
- return Ok(Box::new(MultiConstraint::new(merged, true)));
+ let merged: Vec<AnyConstraint> =
+ std::iter::once(MultiConstraint::new(constraints, false, None).into())
+ .chain(dev_constraints)
+ .collect();
+ return Ok(MultiConstraint::new(merged, true, None).into());
}
if constraints.len() == 1
- && constraints[0].__to_string() == Interval::from_zero().__to_string()
+ && constraints[0].to_string() == Interval::from_zero().to_string()
{
if dev_constraints.len() > 1 {
- return Ok(Box::new(MultiConstraint::new(dev_constraints, true)));
+ return Ok(MultiConstraint::new(dev_constraints, true, None).into());
}
return Ok(dev_constraints.into_iter().next().unwrap());
}
- let merged: Vec<Box<dyn ConstraintInterface>> =
+ let merged: Vec<AnyConstraint> =
constraints.into_iter().chain(dev_constraints).collect();
- return Ok(Box::new(MultiConstraint::new(merged, true)));
+ return Ok(MultiConstraint::new(merged, true, None).into());
}
// otherwise devConstraints contains a list of == operators for branches which are
@@ -300,20 +280,18 @@ impl Intervals {
}
if constraints.len() > 1 {
- return Ok(Box::new(MultiConstraint::new(constraints, false)));
+ return Ok(MultiConstraint::new(constraints, false, None).into());
}
if constraints.len() == 1 {
return Ok(constraints.into_iter().next().unwrap());
}
- Ok(Box::new(MatchNoneConstraint {
- pretty_string: None,
- }))
+ Ok(MatchNoneConstraint::new(None).into())
}
- pub fn get(constraint: &dyn ConstraintInterface) -> anyhow::Result<IntervalCollection> {
- let key = constraint.__to_string();
+ pub fn get(constraint: &AnyConstraint) -> anyhow::Result<IntervalCollection> {
+ let key = constraint.to_string();
{
let cache = intervals_cache().lock().unwrap();
@@ -333,14 +311,10 @@ impl Intervals {
}
fn generate_intervals(
- constraint: &dyn ConstraintInterface,
+ constraint: &AnyConstraint,
stop_on_first_valid_interval: bool,
) -> anyhow::Result<IntervalCollection> {
- if constraint
- .as_any()
- .downcast_ref::<MatchAllConstraint>()
- .is_some()
- {
+ if constraint.is_match_all() {
return Ok(IntervalCollection {
numeric: vec![Interval::new(
Interval::from_zero().clone(),
@@ -350,37 +324,30 @@ impl Intervals {
});
}
- if constraint
- .as_any()
- .downcast_ref::<MatchNoneConstraint>()
- .is_some()
- {
+ if constraint.is_match_none() {
return Ok(IntervalCollection {
numeric: vec![],
branches: Interval::no_dev(),
});
}
- if let Some(c) = constraint.as_any().downcast_ref::<Constraint>() {
+ if let Some(c) = constraint.as_constraint() {
return Self::generate_single_constraint_intervals(c);
}
- let multi = constraint
- .as_any()
- .downcast_ref::<MultiConstraint>()
- .ok_or_else(|| {
- anyhow::anyhow!(
- "The constraint passed in should be an MatchAllConstraint, Constraint or \
+ let multi = constraint.as_multi_constraint().ok_or_else(|| {
+ anyhow::anyhow!(
+ "The constraint passed in should be an MatchAllConstraint, Constraint or \
MultiConstraint instance, got an unknown type."
- )
- })?;
+ )
+ })?;
let sub_constraints = multi.get_constraints();
let mut numeric_groups: Vec<Vec<Interval>> = Vec::new();
let mut constraint_branches: Vec<DevConstraintSet> = Vec::new();
for c in sub_constraints {
- let res = Self::get(c.as_ref())?;
+ let res = Self::get(c)?;
numeric_groups.push(res.numeric);
constraint_branches.push(res.branches);
}
@@ -494,7 +461,7 @@ impl Intervals {
} else {
1
};
- let mut start: Option<Constraint> = None;
+ let mut start: Option<SimpleConstraint> = None;
for (version, operator, is_start) in &borders {
if *is_start {
@@ -504,7 +471,11 @@ impl Intervals {
}
if start.is_none() && active_intervals >= activation_threshold {
- start = Some(Constraint::new(operator.clone(), version.clone()));
+ start = Some(SimpleConstraint::new(
+ operator.clone(),
+ version.clone(),
+ None,
+ ));
} else if start.is_some() && active_intervals < activation_threshold {
let start_c = start.take().unwrap();
// filter out invalid intervals like > x - <= x, or >= x - < x
@@ -516,7 +487,7 @@ impl Intervals {
} else {
intervals.push(Interval::new(
start_c,
- Constraint::new(operator.clone(), version.clone()),
+ SimpleConstraint::new(operator.clone(), version.clone(), None),
));
if stop_on_first_valid_interval {
@@ -533,7 +504,7 @@ impl Intervals {
}
fn generate_single_constraint_intervals(
- constraint: &Constraint,
+ constraint: &SimpleConstraint,
) -> anyhow::Result<IntervalCollection> {
let op = constraint.get_operator();
@@ -589,10 +560,18 @@ impl Intervals {
numeric: vec![
Interval::new(
Interval::from_zero().clone(),
- Constraint::new("<".to_string(), constraint.get_version().to_string()),
+ SimpleConstraint::new(
+ "<".to_string(),
+ constraint.get_version().to_string(),
+ None,
+ ),
),
Interval::new(
- Constraint::new(">".to_string(), constraint.get_version().to_string()),
+ SimpleConstraint::new(
+ ">".to_string(),
+ constraint.get_version().to_string(),
+ None,
+ ),
Interval::until_positive_infinity().clone(),
),
],
@@ -603,8 +582,8 @@ impl Intervals {
// convert ==x to an interval of >=x - <=x
Ok(IntervalCollection {
numeric: vec![Interval::new(
- Constraint::new(">=".to_string(), constraint.get_version().to_string()),
- Constraint::new("<=".to_string(), constraint.get_version().to_string()),
+ SimpleConstraint::new(">=".to_string(), constraint.get_version().to_string(), None),
+ SimpleConstraint::new("<=".to_string(), constraint.get_version().to_string(), None),
)],
branches: Interval::no_dev(),
})