From 93a7671c98a9f022d757781f8fe583a2d55df07b Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sun, 17 May 2026 11:52:08 +0900 Subject: refactor(shirabe): convert PHP abstract classes to Rust traits PHP abstract classes are represented as traits to better align with Rust's type system. --- crates/shirabe/src/dependency_resolver/rule.rs | 98 ++++++++------------------ 1 file changed, 29 insertions(+), 69 deletions(-) (limited to 'crates/shirabe/src/dependency_resolver') diff --git a/crates/shirabe/src/dependency_resolver/rule.rs b/crates/shirabe/src/dependency_resolver/rule.rs index 1ba1dd7..bc2c68e 100644 --- a/crates/shirabe/src/dependency_resolver/rule.rs +++ b/crates/shirabe/src/dependency_resolver/rule.rs @@ -39,19 +39,7 @@ pub enum ReasonData { }, } -/// @phpstan-type ReasonData Link|BasePackage|string|int|array{packageName: string, constraint: ConstraintInterface}|array{package: BasePackage} -#[derive(Debug)] -pub struct Rule { - /// @var int - pub(crate) bitfield: i64, - /// @var Request - pub(crate) request: Option, - /// @var Link|BasePackage|ConstraintInterface|string - /// @phpstan-var ReasonData - pub(crate) reason_data: ReasonData, -} - -impl Rule { +pub trait Rule: std::fmt::Display { // reason constants and // their reason data contents pub const RULE_ROOT_REQUIRE: i64 = 2; pub const RULE_FIXED: i64 = 3; @@ -67,11 +55,24 @@ impl Rule { const BITFIELD_REASON: i64 = 8; const BITFIELD_DISABLED: i64 = 16; + fn bitfield(&self) -> i64; + fn bitfield_mut(&mut self) -> &mut i64; + fn request(&self) -> Option<&Request>; + fn request_mut(&mut self) -> Option<&mut Request>; + fn reason_data(&self) -> Option<&ReasonData>; + fn reason_data_mut(&mut self) -> Option<&mut ReasonData>; + + fn get_literals(&self) -> Vec; + fn get_hash(&self) -> PhpMixed; + fn to_string(&self) -> String; + fn equals(&self, rule: &dyn Rule) -> bool; + fn is_assertion(&self) -> bool; + /// @param self::RULE_* $reason A RULE_* constant describing the reason for generating this rule /// @param mixed $reasonData /// /// @phpstan-param ReasonData $reasonData - pub fn new(reason: i64, reason_data: ReasonData) -> Self { + fn new(reason: i64, reason_data: ReasonData) -> Self { let bitfield = (0i64 << Self::BITFIELD_DISABLED) | (reason << Self::BITFIELD_REASON) | (255i64 << Self::BITFIELD_TYPE); @@ -83,16 +84,16 @@ impl Rule { } /// @return self::RULE_* - pub fn get_reason(&self) -> i64 { + fn get_reason(&self) -> i64 { (self.bitfield & (255 << Self::BITFIELD_REASON)) >> Self::BITFIELD_REASON } /// @phpstan-return ReasonData - pub fn get_reason_data(&self) -> &ReasonData { + fn get_reason_data(&self) -> &ReasonData { &self.reason_data } - pub fn get_required_package(&self) -> Option { + fn get_required_package(&self) -> Option { match self.get_reason() { r if r == Self::RULE_ROOT_REQUIRE => match self.get_reason_data() { ReasonData::RootRequire { package_name, .. } => Some(package_name.clone()), @@ -111,33 +112,33 @@ impl Rule { } /// @param RuleSet::TYPE_* $type - pub fn set_type(&mut self, r#type: i64) { + fn set_type(&mut self, r#type: i64) { self.bitfield = (self.bitfield & !(255i64 << Self::BITFIELD_TYPE)) | ((255 & r#type) << Self::BITFIELD_TYPE); } - pub fn get_type(&self) -> i64 { + fn get_type(&self) -> i64 { (self.bitfield & (255 << Self::BITFIELD_TYPE)) >> Self::BITFIELD_TYPE } - pub fn disable(&mut self) { + fn disable(&mut self) { self.bitfield = (self.bitfield & !(255i64 << Self::BITFIELD_DISABLED)) | (1i64 << Self::BITFIELD_DISABLED); } - pub fn enable(&mut self) { + fn enable(&mut self) { self.bitfield &= !(255i64 << Self::BITFIELD_DISABLED); } - pub fn is_disabled(&self) -> bool { + fn is_disabled(&self) -> bool { 0 != ((self.bitfield & (255 << Self::BITFIELD_DISABLED)) >> Self::BITFIELD_DISABLED) } - pub fn is_enabled(&self) -> bool { + fn is_enabled(&self) -> bool { 0 == ((self.bitfield & (255 << Self::BITFIELD_DISABLED)) >> Self::BITFIELD_DISABLED) } - pub fn is_caused_by_lock( + fn is_caused_by_lock( &self, _repository_set: &RepositorySet, request: &Request, @@ -205,7 +206,7 @@ impl Rule { } /// @internal - pub fn get_source_package(&self, pool: &Pool) -> Result> { + fn get_source_package(&self, pool: &Pool) -> Result> { let literals = self.get_literals(); match self.get_reason() { @@ -244,14 +245,14 @@ impl Rule { /// @param BasePackage[] $installedMap /// @param array $learnedPool - pub fn get_pretty_string( + fn get_pretty_string( &self, repository_set: &RepositorySet, request: &Request, pool: &mut Pool, is_verbose: bool, installed_map: IndexMap>, - _learned_pool: IndexMap>>, + _learned_pool: IndexMap>>, ) -> String { let mut literals = self.get_literals(); @@ -621,7 +622,7 @@ impl Rule { } /// @param array $literalsOrPackages An array containing packages or literals - pub(crate) fn format_packages_unique( + fn format_packages_unique( &self, pool: &Pool, literals_or_packages: Vec>, @@ -677,44 +678,3 @@ impl Rule { package } } - -/// PHP abstract methods on Rule — concrete subclasses must implement. -pub trait RuleTrait: std::any::Any { - /// @return list - fn get_literals(&self) -> Vec; - - /// @return int|string - fn get_hash(&self) -> PhpMixed; - - fn to_string(&self) -> String; - - fn equals(&self, rule: &dyn RuleTrait) -> bool; - - fn is_assertion(&self) -> bool; -} - -// TODO(phase-b): abstract method dispatch — currently Rule has stubs that subclasses override. -impl Rule { - pub fn get_literals(&self) -> Vec { - todo!("abstract: implemented by subclass") - } - - pub fn get_hash(&self) -> PhpMixed { - todo!("abstract: implemented by subclass") - } - - pub fn equals(&self, _rule: &Rule) -> bool { - todo!("abstract: implemented by subclass") - } - - pub fn is_assertion(&self) -> bool { - todo!("abstract: implemented by subclass") - } -} - -impl std::fmt::Display for Rule { - fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - // TODO(phase-b): abstract; subclasses provide __toString - todo!("abstract: implemented by subclass") - } -} -- cgit v1.3.1