aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe-external-packages
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-08-09 11:13:06 +0900
committernsfisis <nsfisis@gmail.com>2026-08-09 11:13:06 +0900
commit880ba0fd1d05faf98588cc326b3d9fbe625ebf2b (patch)
tree055341e80b6297c59cfb267863e0a21419aa6ac3 /crates/shirabe-external-packages
parent66c3eba15ba6302d43de057a9063f7feee8c6fb3 (diff)
downloadphp-shirabe-880ba0fd1d05faf98588cc326b3d9fbe625ebf2b.tar.gz
php-shirabe-880ba0fd1d05faf98588cc326b3d9fbe625ebf2b.tar.zst
php-shirabe-880ba0fd1d05faf98588cc326b3d9fbe625ebf2b.zip
refactor(symfony-string): extract symfony/string into the shirabe-symfony-string crate
Move `Symfony\Component\String` out of shirabe-external-packages and into its own crate, so the path is `shirabe_symfony_string::ByteString` instead of `shirabe_external_packages::symfony::string::ByteString`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe-external-packages')
-rw-r--r--crates/shirabe-external-packages/Cargo.toml1
-rw-r--r--crates/shirabe-external-packages/src/symfony.rs1
-rw-r--r--crates/shirabe-external-packages/src/symfony/console/formatter/output_formatter.rs2
-rw-r--r--crates/shirabe-external-packages/src/symfony/console/helper/helper.rs2
-rw-r--r--crates/shirabe-external-packages/src/symfony/console/helper/question_helper.rs2
-rw-r--r--crates/shirabe-external-packages/src/symfony/string.rs17
-rw-r--r--crates/shirabe-external-packages/src/symfony/string/byte_string.rs45
-rw-r--r--crates/shirabe-external-packages/src/symfony/string/code_point_string.rs93
-rw-r--r--crates/shirabe-external-packages/src/symfony/string/unicode_string.rs56
9 files changed, 4 insertions, 215 deletions
diff --git a/crates/shirabe-external-packages/Cargo.toml b/crates/shirabe-external-packages/Cargo.toml
index 331efcb7..c1e70046 100644
--- a/crates/shirabe-external-packages/Cargo.toml
+++ b/crates/shirabe-external-packages/Cargo.toml
@@ -7,6 +7,7 @@ edition.workspace = true
shirabe-pcre.workspace = true
shirabe-php-shim.workspace = true
shirabe-semver.workspace = true
+shirabe-symfony-string.workspace = true
anyhow.workspace = true
chrono.workspace = true
indexmap.workspace = true
diff --git a/crates/shirabe-external-packages/src/symfony.rs b/crates/shirabe-external-packages/src/symfony.rs
index 9c572b26..e0d9e4fe 100644
--- a/crates/shirabe-external-packages/src/symfony.rs
+++ b/crates/shirabe-external-packages/src/symfony.rs
@@ -2,4 +2,3 @@ pub mod console;
pub mod filesystem;
pub mod finder;
pub mod process;
-pub mod string;
diff --git a/crates/shirabe-external-packages/src/symfony/console/formatter/output_formatter.rs b/crates/shirabe-external-packages/src/symfony/console/formatter/output_formatter.rs
index a0562aef..08079a7c 100644
--- a/crates/shirabe-external-packages/src/symfony/console/formatter/output_formatter.rs
+++ b/crates/shirabe-external-packages/src/symfony/console/formatter/output_formatter.rs
@@ -6,8 +6,8 @@ use crate::symfony::console::formatter::output_formatter_style::OutputFormatterS
use crate::symfony::console::formatter::output_formatter_style_interface::OutputFormatterStyleInterface;
use crate::symfony::console::formatter::output_formatter_style_stack::OutputFormatterStyleStack;
use crate::symfony::console::formatter::wrappable_output_formatter_interface::WrappableOutputFormatterInterface;
-use crate::symfony::string::b;
use shirabe_php_shim::php_regex;
+use shirabe_symfony_string::b;
/// Formatter class for console output.
#[derive(Debug)]
diff --git a/crates/shirabe-external-packages/src/symfony/console/helper/helper.rs b/crates/shirabe-external-packages/src/symfony/console/helper/helper.rs
index 20103df8..471a8d8a 100644
--- a/crates/shirabe-external-packages/src/symfony/console/helper/helper.rs
+++ b/crates/shirabe-external-packages/src/symfony/console/helper/helper.rs
@@ -2,8 +2,8 @@
use crate::symfony::console::formatter::output_formatter_interface::OutputFormatterInterface;
use crate::symfony::console::helper::helper_set::HelperSet;
-use crate::symfony::string::unicode_string::UnicodeString;
use shirabe_php_shim::php_regex;
+use shirabe_symfony_string::unicode_string::UnicodeString;
/// Helper is the base class for all helper classes.
#[derive(Debug, Default)]
diff --git a/crates/shirabe-external-packages/src/symfony/console/helper/question_helper.rs b/crates/shirabe-external-packages/src/symfony/console/helper/question_helper.rs
index 8ec8d15c..91fb5bf0 100644
--- a/crates/shirabe-external-packages/src/symfony/console/helper/question_helper.rs
+++ b/crates/shirabe-external-packages/src/symfony/console/helper/question_helper.rs
@@ -18,8 +18,8 @@ use crate::symfony::console::output::output_interface::OutputInterface;
use crate::symfony::console::question::ChoiceQuestion;
use crate::symfony::console::question::QuestionInterface;
use crate::symfony::console::terminal::Terminal;
-use crate::symfony::string::s;
use shirabe_php_shim::PhpMixed;
+use shirabe_symfony_string::s;
/// The QuestionHelper class provides helpers to interact with the user.
#[derive(Debug, Default)]
diff --git a/crates/shirabe-external-packages/src/symfony/string.rs b/crates/shirabe-external-packages/src/symfony/string.rs
deleted file mode 100644
index 139d726f..00000000
--- a/crates/shirabe-external-packages/src/symfony/string.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-pub mod byte_string;
-pub mod code_point_string;
-pub mod unicode_string;
-
-pub use byte_string::*;
-pub use code_point_string::*;
-pub use unicode_string::*;
-
-/// Mirror of Symfony's `b()` helper function.
-pub fn b(string: &str) -> ByteString {
- ByteString::new(string)
-}
-
-/// Mirror of Symfony's `u()` helper function.
-pub fn s(string: &str) -> UnicodeString {
- UnicodeString::new(string)
-}
diff --git a/crates/shirabe-external-packages/src/symfony/string/byte_string.rs b/crates/shirabe-external-packages/src/symfony/string/byte_string.rs
deleted file mode 100644
index 8ad183e3..00000000
--- a/crates/shirabe-external-packages/src/symfony/string/byte_string.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-//! ref: composer/vendor/symfony/string/ByteString.php
-
-use crate::symfony::string::code_point_string::CodePointString;
-
-#[derive(Debug, Clone)]
-pub struct ByteString {
- pub(crate) string: String,
-}
-
-impl ByteString {
- pub fn new(string: &str) -> Self {
- Self {
- string: string.to_string(),
- }
- }
-
- /// `from_encoding` is `""` for PHP's `null`.
- pub fn to_code_point_string(&self, from_encoding: &str) -> CodePointString {
- // The source `string` is always valid UTF-8 (Rust `String`/`&str` guarantee), so
- // `preg_match('//u', ...)` always holds.
- if matches!(from_encoding, "" | "utf8" | "utf-8" | "UTF8" | "UTF-8") {
- return CodePointString {
- string: self.string.clone(),
- };
- }
-
- let valid_encoding = shirabe_php_shim::mb_detect_encoding(
- &self.string,
- Some(vec![from_encoding.to_string()]),
- true,
- )
- .is_some();
- // PHP throws InvalidArgumentException. Callers detect `from_encoding` from this very
- // string, so a mismatch is a programming error.
- assert!(valid_encoding, "Invalid \"{}\" string.", from_encoding);
-
- CodePointString {
- string: shirabe_php_shim::mb_convert_encoding(
- self.string.clone().into_bytes(),
- "UTF-8",
- from_encoding,
- ),
- }
- }
-}
diff --git a/crates/shirabe-external-packages/src/symfony/string/code_point_string.rs b/crates/shirabe-external-packages/src/symfony/string/code_point_string.rs
deleted file mode 100644
index dcbaa1f6..00000000
--- a/crates/shirabe-external-packages/src/symfony/string/code_point_string.rs
+++ /dev/null
@@ -1,93 +0,0 @@
-//! ref: composer/vendor/symfony/string/CodePointString.php
-
-#[derive(Debug, Clone)]
-pub struct CodePointString {
- pub(crate) string: String,
-}
-
-impl CodePointString {
- /// Port of `AbstractString::wordwrap()`, specialised to the non-`ignoreCase` code-point case.
- pub fn wordwrap(&self, width: i64, r#break: &str, cut: bool) -> Self {
- // `split($break)` with no flags reduces to `explode($break, $string)` here, then `chunk()`
- // yields one entry per code point. `ignoreCase` is always false for freshly built instances.
- let lines: Vec<&str> = if !r#break.is_empty() {
- self.string.split(r#break).collect()
- } else {
- vec![&self.string]
- };
-
- let mut chars: Vec<String> = Vec::new();
- let mut mask = String::new();
-
- if lines.len() == 1 && lines[0].is_empty() {
- return Self {
- string: String::new(),
- };
- }
-
- for (i, line) in lines.iter().enumerate() {
- if i != 0 {
- chars.push(r#break.to_string());
- mask.push('#');
- }
-
- for ch in line.chars() {
- let s = ch.to_string();
- mask.push(if s == " " { ' ' } else { '?' });
- chars.push(s);
- }
- }
-
- let mut string = String::new();
- let mut j: usize = 0;
- // PHP seeds both `$b` and `$i` at -1; mirror with signed indices.
- let mut i: i64 = -1;
- let mask = shirabe_php_shim::wordwrap(&mask, width, "#", cut);
- let mask_bytes = mask.as_bytes();
-
- let mut b: i64 = -1;
- loop {
- // strpos($mask, '#', $b + 1)
- let from = (b + 1) as usize;
- let Some(rel) = mask_bytes[from..].iter().position(|&c| c == b'#') else {
- break;
- };
- b = (from + rel) as i64;
-
- i += 1;
- while i < b {
- string.push_str(&chars[j]);
- j += 1;
- i += 1;
- }
-
- if chars[j] == r#break || chars[j] == " " {
- j += 1;
- }
-
- string.push_str(r#break);
- }
-
- for c in &chars[j..] {
- string.push_str(c);
- }
-
- Self { string }
- }
-
- /// `to_encoding` is `""` for PHP's `null`.
- pub fn to_byte_string(&self, to_encoding: &str) -> String {
- // A CodePointString is an AbstractUnicodeString, so PHP's `$fromEncoding` is always
- // 'UTF-8' and the string is returned verbatim for a null/UTF-8 target.
- if matches!(to_encoding, "" | "utf8" | "utf-8" | "UTF8" | "UTF-8") {
- return self.string.clone();
- }
-
- // PHP falls back to iconv() only when mb_convert_encoding() rejects the target encoding.
- shirabe_php_shim::mb_convert_encoding(
- self.string.clone().into_bytes(),
- to_encoding,
- "UTF-8",
- )
- }
-}
diff --git a/crates/shirabe-external-packages/src/symfony/string/unicode_string.rs b/crates/shirabe-external-packages/src/symfony/string/unicode_string.rs
deleted file mode 100644
index 9048f77b..00000000
--- a/crates/shirabe-external-packages/src/symfony/string/unicode_string.rs
+++ /dev/null
@@ -1,56 +0,0 @@
-//! ref: composer/vendor/symfony/string/UnicodeString.php
-
-#[derive(Debug, Clone)]
-pub struct UnicodeString {
- pub(crate) string: String,
-}
-
-impl UnicodeString {
- // TODO(phase-c): the real constructor runs `normalizer_normalize` (Unicode NFC normalization),
- // which has no Rust std equivalent and would need a dedicated normalization implementation.
- // Normalization is skipped here, which is only correct for already-NFC input such as ASCII.
- pub fn new(string: &str) -> Self {
- Self {
- string: string.to_string(),
- }
- }
-
- // TODO(phase-c): ASCII-only provisional implementation. The faithful `width()` uses `wcswidth`
- // with the Unicode width tables to treat wide characters as width 2 and skip zero-width /
- // combining characters; here every character counts as width 1, correct only for ASCII. The
- // ANSI/control-character stripping driven by `ignore_ansi_decoration` is likewise not handled.
- pub fn width(&self, _ignore_ansi_decoration: bool) -> i64 {
- let s = self.string.replace(['\x00', '\x05', '\x07'], "");
- let s = s.replace("\r\n", "\n").replace('\r', "\n");
-
- let mut width: i64 = 0;
- for line in s.split('\n') {
- let line_width = line.chars().count() as i64;
- if line_width > width {
- width = line_width;
- }
- }
-
- width
- }
-
- // TODO(phase-c): the faithful `length()` uses `grapheme_strlen` (extended grapheme clusters),
- // which needs Unicode segmentation tables with no Rust std equivalent and no permitted crate.
- // Approximated with the code-point count, exact only when no combining/multi-code-point
- // clusters are present (e.g. ASCII).
- pub fn length(&self) -> i64 {
- shirabe_php_shim::mb_strlen(&self.string, "UTF-8")
- }
-
- // TODO(phase-c): the faithful `slice()` uses `grapheme_substr` (grapheme-cluster offsets), which
- // needs Unicode segmentation tables with no std equivalent and no permitted crate. Approximated
- // with code-point offsets via `mb_substr`, exact only without combining/multi-code-point clusters.
- pub fn slice(&self, start: i64, length: Option<i64>) -> Self {
- Self::new(&shirabe_php_shim::mb_substr(
- &self.string,
- start,
- length,
- Some("UTF-8"),
- ))
- }
-}