diff options
Diffstat (limited to 'crates/shirabe-semver/src/constraint/constraint.rs')
| -rw-r--r-- | crates/shirabe-semver/src/constraint/constraint.rs | 409 |
1 files changed, 0 insertions, 409 deletions
diff --git a/crates/shirabe-semver/src/constraint/constraint.rs b/crates/shirabe-semver/src/constraint/constraint.rs deleted file mode 100644 index 3ac633d..0000000 --- a/crates/shirabe-semver/src/constraint/constraint.rs +++ /dev/null @@ -1,409 +0,0 @@ -//! ref: composer/vendor/composer/semver/src/Constraint/Constraint.php - -use std::sync::Mutex; - -use anyhow::bail; -use shirabe_php_shim as php; - -use crate::constraint::Bound; -use crate::constraint::ConstraintInterface; - -#[derive(Debug)] -pub struct Constraint { - pub(crate) operator: i64, - pub(crate) version: String, - pub(crate) pretty_string: Option<String>, - pub(crate) lower_bound: Mutex<Option<Bound>>, - pub(crate) upper_bound: Mutex<Option<Bound>>, -} - -impl Constraint { - pub const OP_EQ: i64 = 0; - pub const OP_LT: i64 = 1; - pub const OP_LE: i64 = 2; - pub const OP_GT: i64 = 3; - pub const OP_GE: i64 = 4; - pub const OP_NE: i64 = 5; - - pub const STR_OP_EQ: &'static str = "=="; - pub const STR_OP_EQ_ALT: &'static str = "="; - pub const STR_OP_LT: &'static str = "<"; - pub const STR_OP_LE: &'static str = "<="; - pub const STR_OP_GT: &'static str = ">"; - pub const STR_OP_GE: &'static str = ">="; - pub const STR_OP_NE: &'static str = "!="; - pub const STR_OP_NE_ALT: &'static str = "<>"; - - fn trans_op_str(op: &str) -> Option<i64> { - match op { - "=" => Some(Self::OP_EQ), - "==" => Some(Self::OP_EQ), - "<" => Some(Self::OP_LT), - "<=" => Some(Self::OP_LE), - ">" => Some(Self::OP_GT), - ">=" => Some(Self::OP_GE), - "<>" => Some(Self::OP_NE), - "!=" => Some(Self::OP_NE), - _ => None, - } - } - - fn trans_op_int(op: i64) -> &'static str { - match op { - Self::OP_EQ => "==", - Self::OP_LT => "<", - Self::OP_LE => "<=", - Self::OP_GT => ">", - Self::OP_GE => ">=", - Self::OP_NE => "!=", - _ => panic!("unknown operator: {}", op), - } - } - - pub fn new(operator: impl Into<String>, version: impl Into<String>) -> Self { - let operator: String = operator.into(); - let op_int = Self::trans_op_str(&operator).unwrap_or_else(|| { - // PHP raises InvalidArgumentException; in the Rust port keep that as a panic - // because invalid operators are programmer errors caught during porting. - panic!( - "Invalid operator \"{}\" given, expected one of: {}", - operator, - Self::get_supported_operators().join(", ") - ) - }); - - Self { - operator: op_int, - version: version.into(), - pretty_string: None, - lower_bound: Mutex::new(None), - upper_bound: Mutex::new(None), - } - } - - pub fn get_version(&self) -> &str { - &self.version - } - - pub fn get_operator(&self) -> &'static str { - Self::trans_op_int(self.operator) - } - - pub fn get_supported_operators() -> Vec<&'static str> { - vec!["=", "==", "<", "<=", ">", ">=", "<>", "!="] - } - - pub fn get_operator_constant(operator: &str) -> i64 { - Self::trans_op_str(operator).expect("valid operator") - } - - pub fn version_compare( - &self, - a: &str, - b: &str, - operator: &str, - compare_branches: bool, - ) -> anyhow::Result<bool> { - if Self::trans_op_str(operator).is_none() { - bail!( - "Invalid operator \"{}\" given, expected one of: {}", - operator, - Self::get_supported_operators().join(", ") - ); - } - - let a_is_branch = a.starts_with("dev-"); - let b_is_branch = b.starts_with("dev-"); - - if operator == "!=" && (a_is_branch || b_is_branch) { - return Ok(a != b); - } - - if a_is_branch && b_is_branch { - return Ok(operator == "==" && a == b); - } - - if !compare_branches && (a_is_branch || b_is_branch) { - return Ok(false); - } - - Ok(php::version_compare(a, b, operator)) - } - - pub fn compile_constraint(&self, other_operator: i64) -> String { - if self.version.starts_with("dev-") { - if Self::OP_EQ == self.operator { - if Self::OP_EQ == other_operator { - return format!("$b && $v === {}", php::var_export_str(&self.version, true)); - } - if Self::OP_NE == other_operator { - return format!("!$b || $v !== {}", php::var_export_str(&self.version, true)); - } - return "false".to_string(); - } - - if Self::OP_NE == self.operator { - if Self::OP_EQ == other_operator { - return format!("!$b || $v !== {}", php::var_export_str(&self.version, true)); - } - if Self::OP_NE == other_operator { - return "true".to_string(); - } - return "!$b".to_string(); - } - - return "false".to_string(); - } - - if Self::OP_EQ == self.operator { - if Self::OP_EQ == other_operator { - return format!( - "\\version_compare($v, {}, '==')", - php::var_export_str(&self.version, true) - ); - } - if Self::OP_NE == other_operator { - return format!( - "$b || \\version_compare($v, {}, '!=')", - php::var_export_str(&self.version, true) - ); - } - return format!( - "!$b && \\version_compare({}, $v, '{}')", - php::var_export_str(&self.version, true), - Self::trans_op_int(other_operator) - ); - } - - if Self::OP_NE == self.operator { - if Self::OP_EQ == other_operator { - return format!( - "$b || (!$b && \\version_compare($v, {}, '!='))", - php::var_export_str(&self.version, true) - ); - } - if Self::OP_NE == other_operator { - return "true".to_string(); - } - return "!$b".to_string(); - } - - if Self::OP_LT == self.operator || Self::OP_LE == self.operator { - if Self::OP_LT == other_operator || Self::OP_LE == other_operator { - return "!$b".to_string(); - } - } else if Self::OP_GT == other_operator || Self::OP_GE == other_operator { - return "!$b".to_string(); - } - - if Self::OP_NE == other_operator { - return "true".to_string(); - } - - let code_comparison = format!( - "\\version_compare($v, {}, '{}')", - php::var_export_str(&self.version, true), - Self::trans_op_int(self.operator) - ); - - if self.operator == Self::OP_LE && other_operator == Self::OP_GT { - return format!( - "!$b && \\version_compare($v, {}, '!=') && {}", - php::var_export_str(&self.version, true), - code_comparison - ); - } - - if self.operator == Self::OP_GE && other_operator == Self::OP_LT { - return format!( - "!$b && \\version_compare($v, {}, '!=') && {}", - php::var_export_str(&self.version, true), - code_comparison - ); - } - - format!("!$b && {}", code_comparison) - } - - pub fn match_specific(&self, provider: &Constraint, compare_branches: bool) -> bool { - let no_equal_op = Self::trans_op_int(self.operator).replace('=', ""); - let provider_no_equal_op = Self::trans_op_int(provider.operator).replace('=', ""); - - let is_equal_op = Self::OP_EQ == self.operator; - let is_non_equal_op = Self::OP_NE == self.operator; - let is_provider_equal_op = Self::OP_EQ == provider.operator; - let is_provider_non_equal_op = Self::OP_NE == provider.operator; - - if is_non_equal_op || is_provider_non_equal_op { - if is_non_equal_op - && !is_provider_non_equal_op - && !is_provider_equal_op - && provider.version.starts_with("dev-") - { - return false; - } - - if is_provider_non_equal_op - && !is_non_equal_op - && !is_equal_op - && self.version.starts_with("dev-") - { - return false; - } - - if !is_equal_op && !is_provider_equal_op { - return true; - } - return self - .version_compare(&provider.version, &self.version, "!=", compare_branches) - .expect("valid operator"); - } - - if self.operator != Self::OP_EQ && no_equal_op == provider_no_equal_op { - return !(self.version.starts_with("dev-") || provider.version.starts_with("dev-")); - } - - let (version1, version2, operator) = if is_equal_op { - (&self.version, &provider.version, provider.operator) - } else { - (&provider.version, &self.version, self.operator) - }; - - if self - .version_compare( - version1, - version2, - Self::trans_op_int(operator), - compare_branches, - ) - .expect("valid operator") - { - return !(Self::trans_op_int(provider.operator) == provider_no_equal_op - && Self::trans_op_int(self.operator) != no_equal_op - && php::version_compare(&provider.version, &self.version, "==")); - } - - false - } - - fn extract_bounds(&self) { - if self.lower_bound.lock().unwrap().is_some() { - return; - } - - if self.version.starts_with("dev-") { - *self.lower_bound.lock().unwrap() = Some(Bound::zero()); - *self.upper_bound.lock().unwrap() = Some(Bound::positive_infinity()); - return; - } - - let (lower, upper) = match self.operator { - Self::OP_EQ => ( - Bound::new(self.version.clone(), true), - Bound::new(self.version.clone(), true), - ), - Self::OP_LT => (Bound::zero(), Bound::new(self.version.clone(), false)), - Self::OP_LE => (Bound::zero(), Bound::new(self.version.clone(), true)), - Self::OP_GT => ( - Bound::new(self.version.clone(), false), - Bound::positive_infinity(), - ), - Self::OP_GE => ( - Bound::new(self.version.clone(), true), - Bound::positive_infinity(), - ), - Self::OP_NE => (Bound::zero(), Bound::positive_infinity()), - _ => panic!("unknown operator: {}", self.operator), - }; - - *self.lower_bound.lock().unwrap() = Some(lower); - *self.upper_bound.lock().unwrap() = Some(upper); - } -} - -impl Clone for Constraint { - fn clone(&self) -> Self { - Self { - operator: self.operator, - version: self.version.clone(), - pretty_string: self.pretty_string.clone(), - lower_bound: Mutex::new(self.lower_bound.lock().unwrap().clone()), - upper_bound: Mutex::new(self.upper_bound.lock().unwrap().clone()), - } - } -} - -impl ConstraintInterface for Constraint { - fn matches(&self, provider: &dyn ConstraintInterface) -> bool { - if let Some(p) = provider.as_any().downcast_ref::<Constraint>() { - return self.match_specific(p, false); - } - provider.matches(self) - } - - fn compile(&self, other_operator: i64) -> String { - self.compile_constraint(other_operator) - } - - fn set_pretty_string(&mut self, pretty_string: Option<String>) { - self.pretty_string = pretty_string; - } - - fn get_pretty_string(&self) -> String { - if let Some(ref s) = self.pretty_string - && !s.is_empty() - { - return s.clone(); - } - self.__to_string() - } - - fn __to_string(&self) -> String { - format!("{} {}", Self::trans_op_int(self.operator), self.version) - } - - fn get_lower_bound(&self) -> Bound { - self.extract_bounds(); - self.lower_bound - .lock() - .unwrap() - .clone() - .expect("extract_bounds should have set lower_bound") - } - - fn get_upper_bound(&self) -> Bound { - self.extract_bounds(); - self.upper_bound - .lock() - .unwrap() - .clone() - .expect("extract_bounds should have set upper_bound") - } - - fn clone_box(&self) -> Box<dyn ConstraintInterface> { - Box::new(self.clone()) - } - - fn as_any(&self) -> &dyn std::any::Any { - self - } - - fn is_constraint(&self) -> bool { - true - } - - fn get_operator(&self) -> &'static str { - Self::trans_op_int(self.operator) - } - - fn get_version(&self) -> &str { - &self.version - } -} - -impl std::fmt::Display for Constraint { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - use crate::constraint::ConstraintInterface; - write!(f, "{}", ConstraintInterface::__to_string(self)) - } -} |
