aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/io
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-06-14 16:39:38 +0900
committernsfisis <nsfisis@gmail.com>2026-06-14 22:19:30 +0900
commit7f3171b14a89762b2f0c71969d7243f2297af7c9 (patch)
tree37253f75e4f3b1c0e8a3c4161f7186bbe2c1a2d7 /crates/shirabe/src/io
parentae113f91fefff415898781272b892d670fcb46f4 (diff)
downloadphp-shirabe-7f3171b14a89762b2f0c71969d7243f2297af7c9.tar.gz
php-shirabe-7f3171b14a89762b2f0c71969d7243f2297af7c9.tar.zst
php-shirabe-7f3171b14a89762b2f0c71969d7243f2297af7c9.zip
feat(php-shim): implement more shim functions
Diffstat (limited to 'crates/shirabe/src/io')
-rw-r--r--crates/shirabe/src/io/console_io.rs27
1 files changed, 15 insertions, 12 deletions
diff --git a/crates/shirabe/src/io/console_io.rs b/crates/shirabe/src/io/console_io.rs
index 3afd300..ecb12b1 100644
--- a/crates/shirabe/src/io/console_io.rs
+++ b/crates/shirabe/src/io/console_io.rs
@@ -275,10 +275,6 @@ impl ConsoleIO {
/// All other control chars (except NULL bytes) as well as ANSI escape sequences are removed.
///
/// Invalid unicode sequences are turned into question marks.
- ///
- /// @param string|iterable<string> $messages
- /// @return string|array<string>
- /// @phpstan-return ($messages is string ? string : array<string>)
pub fn sanitize(messages: PhpMixed, allow_newlines: bool) -> PhpMixed {
// Match ANSI escape sequences:
// - CSI (Control Sequence Introducer): ESC [ params intermediate final
@@ -286,17 +282,24 @@ impl ConsoleIO {
// - Other ESC sequences: ESC followed by any character
let escape_pattern =
r"\x1B\[[\x30-\x3F]*[\x20-\x2F]*[\x40-\x7E]|\x1B\].*?(?:\x1B\\|\x07)|\x1B.";
- let pattern = if allow_newlines {
- format!(
- "{{{}|[\\x01-\\x09\\x0B\\x0C\\x0E-\\x1A]|\\r(?!\\n)}}u",
- escape_pattern
+ // Regex pattern compatibility:
+ // PCRE's `\r(?!\n)` (non-CRLF CR) uses a negative lookahead, which the regex crate does
+ // not support. Instead we capture `\r\n` and re-emit it via the `$1` backreference. A CRLF
+ // pair is preserved while a lone CR is removed.
+ let (pattern, replacement) = if allow_newlines {
+ (
+ format!(
+ r#"@{}|[\x01-\x09\x0B\x0C\x0E-\x1A]|(\r\n)|\r@u"#,
+ escape_pattern
+ ),
+ "$1",
)
} else {
- format!("{{{}|[\\x01-\\x1A]}}u", escape_pattern)
+ (format!("{{{}|[\\x01-\\x1A]}}u", escape_pattern), "")
};
if is_string(&messages) {
let message = Self::ensure_valid_utf8(messages.as_string().unwrap_or(""));
- return PhpMixed::String(Preg::replace(&pattern, "", &message));
+ return PhpMixed::String(Preg::replace(&pattern, replacement, &message));
}
// PHP: $sanitized = []; foreach ($messages as $key => $message) { ... }
@@ -307,7 +310,7 @@ impl ConsoleIO {
let s = Self::ensure_valid_utf8(message.as_string().unwrap_or(""));
sanitized.insert(
key.to_string(),
- PhpMixed::String(Preg::replace(&pattern, "", &s)),
+ PhpMixed::String(Preg::replace(&pattern, replacement, &s)),
);
}
}
@@ -316,7 +319,7 @@ impl ConsoleIO {
let s = Self::ensure_valid_utf8(message.as_string().unwrap_or(""));
sanitized.insert(
key.clone(),
- PhpMixed::String(Preg::replace(&pattern, "", &s)),
+ PhpMixed::String(Preg::replace(&pattern, replacement, &s)),
);
}
}