From 36e367ffe00328c8d6271c8e218186d7a286bfa6 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Fri, 15 May 2026 00:43:57 +0900 Subject: feat(port): port RuleSetIterator.php --- .../src/dependency_resolver/rule_set_iterator.rs | 93 ++++++++++++++++++++++ 1 file changed, 93 insertions(+) (limited to 'crates/shirabe/src') diff --git a/crates/shirabe/src/dependency_resolver/rule_set_iterator.rs b/crates/shirabe/src/dependency_resolver/rule_set_iterator.rs index 6012876..e2b67f4 100644 --- a/crates/shirabe/src/dependency_resolver/rule_set_iterator.rs +++ b/crates/shirabe/src/dependency_resolver/rule_set_iterator.rs @@ -1 +1,94 @@ //! ref: composer/src/Composer/DependencyResolver/RuleSetIterator.php + +use indexmap::IndexMap; +use crate::dependency_resolver::rule::Rule; + +/// Implements PHP \Iterator over a grouped rule set. +#[derive(Debug)] +pub struct RuleSetIterator { + pub(crate) rules: IndexMap>, + pub(crate) types: Vec, + pub(crate) current_offset: i64, + pub(crate) current_type: i64, + pub(crate) current_type_offset: i64, +} + +impl RuleSetIterator { + pub fn new(rules: IndexMap>) -> Self { + let mut types: Vec = rules.keys().copied().collect(); + types.sort(); + let mut iter = Self { + rules, + types, + current_offset: 0, + current_type: -1, + current_type_offset: 0, + }; + iter.rewind(); + iter + } + + pub fn current(&self) -> &Rule { + &self.rules[&self.current_type][self.current_offset as usize] + } + + pub fn key(&self) -> i64 { + self.current_type + } + + pub fn next(&mut self) { + self.current_offset += 1; + + if !self.rules.contains_key(&self.current_type) { + return; + } + + if self.current_offset >= self.rules[&self.current_type].len() as i64 { + self.current_offset = 0; + + loop { + self.current_type_offset += 1; + + if self.types.get(self.current_type_offset as usize).is_none() { + self.current_type = -1; + break; + } + + self.current_type = self.types[self.current_type_offset as usize]; + + if self.rules[&self.current_type].len() != 0 { + break; + } + } + } + } + + pub fn rewind(&mut self) { + self.current_offset = 0; + self.current_type_offset = -1; + self.current_type = -1; + + loop { + self.current_type_offset += 1; + + if self.types.get(self.current_type_offset as usize).is_none() { + self.current_type = -1; + break; + } + + self.current_type = self.types[self.current_type_offset as usize]; + + if self.rules[&self.current_type].len() != 0 { + break; + } + } + } + + pub fn valid(&self) -> bool { + if let Some(rules) = self.rules.get(&self.current_type) { + rules.get(self.current_offset as usize).is_some() + } else { + false + } + } +} -- cgit v1.3.1