aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/dependency_resolver/generic_rule.rs
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-05-14 20:01:10 +0900
committernsfisis <nsfisis@gmail.com>2026-05-14 20:01:10 +0900
commitf76b2a6e62c8cb8f330864d3f062cf0933d023cb (patch)
tree8cda0f87c2be5c3093c04cb3bf2384ac1e31ce96 /crates/shirabe/src/dependency_resolver/generic_rule.rs
parent44ce5a41afaea0038bb2b48c82c3a9a8dc9ab206 (diff)
downloadphp-shirabe-f76b2a6e62c8cb8f330864d3f062cf0933d023cb.tar.gz
php-shirabe-f76b2a6e62c8cb8f330864d3f062cf0933d023cb.tar.zst
php-shirabe-f76b2a6e62c8cb8f330864d3f062cf0933d023cb.zip
feat(port): port GenericRule.php
Diffstat (limited to 'crates/shirabe/src/dependency_resolver/generic_rule.rs')
-rw-r--r--crates/shirabe/src/dependency_resolver/generic_rule.rs75
1 files changed, 75 insertions, 0 deletions
diff --git a/crates/shirabe/src/dependency_resolver/generic_rule.rs b/crates/shirabe/src/dependency_resolver/generic_rule.rs
index 2d46346..8e294c1 100644
--- a/crates/shirabe/src/dependency_resolver/generic_rule.rs
+++ b/crates/shirabe/src/dependency_resolver/generic_rule.rs
@@ -1 +1,76 @@
//! ref: composer/src/Composer/DependencyResolver/GenericRule.php
+
+use anyhow::Result;
+use shirabe_php_shim::{hash_raw, implode, unpack, RuntimeException, PHP_VERSION_ID};
+use crate::dependency_resolver::rule::Rule;
+
+pub struct GenericRule {
+ inner: Rule,
+ pub(crate) literals: Vec<i64>,
+}
+
+impl GenericRule {
+ pub fn new(mut literals: Vec<i64>, reason: shirabe_php_shim::PhpMixed, reason_data: shirabe_php_shim::PhpMixed) -> Self {
+ let inner = Rule::new(reason, reason_data);
+ literals.sort();
+ Self { inner, literals }
+ }
+
+ pub fn get_literals(&self) -> &Vec<i64> {
+ &self.literals
+ }
+
+ pub fn get_hash(&self) -> Result<i64> {
+ let joined = self.literals.iter().map(|l| l.to_string()).collect::<Vec<_>>().join(",");
+ let algo = if PHP_VERSION_ID > 80100 { "xxh3" } else { "sha1" };
+ let binary = hash_raw(algo, &joined);
+ let data = unpack("ihash", &binary);
+ match data {
+ Some(map) => {
+ if let Some(val) = map.get("hash") {
+ Ok(val.as_int().unwrap_or(0))
+ } else {
+ Err(RuntimeException {
+ message: format!("Failed unpacking: {}", joined),
+ code: 0,
+ }.into())
+ }
+ }
+ None => Err(RuntimeException {
+ message: format!("Failed unpacking: {}", joined),
+ code: 0,
+ }.into()),
+ }
+ }
+
+ pub fn equals(&self, rule: &dyn RuleLiterals) -> bool {
+ self.literals == *rule.get_literals()
+ }
+
+ pub fn is_assertion(&self) -> bool {
+ self.literals.len() == 1
+ }
+
+ pub fn to_string(&self) -> String {
+ let prefix = if self.inner.is_disabled() { "disabled(" } else { "(" };
+ let mut result = prefix.to_string();
+ for (i, literal) in self.literals.iter().enumerate() {
+ if i != 0 {
+ result.push('|');
+ }
+ result.push_str(&literal.to_string());
+ }
+ result.push(')');
+ result
+ }
+}
+
+pub trait RuleLiterals {
+ fn get_literals(&self) -> &Vec<i64>;
+}
+
+impl RuleLiterals for GenericRule {
+ fn get_literals(&self) -> &Vec<i64> {
+ &self.literals
+ }
+}