diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-06-03 00:34:01 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-06-03 00:34:01 +0900 |
| commit | e93ea9ae1058334fc72b7795021bb42c1bd64401 (patch) | |
| tree | dd0972233aa13308975f7a3c1e0380ebbd7672ec /crates/shirabe/src | |
| parent | 51843230859ef39344c0b67daa9049ead87ec49c (diff) | |
| download | php-shirabe-e93ea9ae1058334fc72b7795021bb42c1bd64401.tar.gz php-shirabe-e93ea9ae1058334fc72b7795021bb42c1bd64401.tar.zst php-shirabe-e93ea9ae1058334fc72b7795021bb42c1bd64401.zip | |
feat(io): add as_any downcast shims for IOInterface and OutputInterface
Introduce the cross-cutting downcast base for PHP `instanceof` checks on
io/output trait objects: `IOInterface::as_any` (ConsoleIO/NullIO/BufferIO)
and `OutputInterface::as_console_output_interface` (promoting ConsoleOutput
to a proper ConsoleOutputInterface). Wire the resolved downcasts in
ConsoleIO error output, Auditor table format, and the event dispatcher.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/src')
| -rw-r--r-- | crates/shirabe/src/advisory/auditor.rs | 6 | ||||
| -rw-r--r-- | crates/shirabe/src/event_dispatcher/event_dispatcher.rs | 7 | ||||
| -rw-r--r-- | crates/shirabe/src/io/buffer_io.rs | 6 | ||||
| -rw-r--r-- | crates/shirabe/src/io/console_io.rs | 18 | ||||
| -rw-r--r-- | crates/shirabe/src/io/io_interface.rs | 4 | ||||
| -rw-r--r-- | crates/shirabe/src/io/null_io.rs | 6 |
6 files changed, 25 insertions, 22 deletions
diff --git a/crates/shirabe/src/advisory/auditor.rs b/crates/shirabe/src/advisory/auditor.rs index 18af0f3..af54d06 100644 --- a/crates/shirabe/src/advisory/auditor.rs +++ b/crates/shirabe/src/advisory/auditor.rs @@ -434,8 +434,7 @@ impl Auditor { ) -> Result<()> { match format { Self::FORMAT_TABLE => { - // TODO(phase-b): `$io instanceof ConsoleIO` downcast from &dyn IOInterface - let io_as_console: Option<&ConsoleIO> = None; + let io_as_console = io.as_any().downcast_ref::<ConsoleIO>(); if io_as_console.is_none() { return Err(InvalidArgumentException { message: format!( @@ -610,8 +609,7 @@ impl Auditor { return Ok(()); } - // TODO(phase-b): `$io instanceof ConsoleIO` downcast from &dyn IOInterface - let io_as_console: Option<&ConsoleIO> = None; + let io_as_console = io.as_any().downcast_ref::<ConsoleIO>(); if io_as_console.is_none() { return Err(InvalidArgumentException { message: format!( diff --git a/crates/shirabe/src/event_dispatcher/event_dispatcher.rs b/crates/shirabe/src/event_dispatcher/event_dispatcher.rs index 237fad4..175b689 100644 --- a/crates/shirabe/src/event_dispatcher/event_dispatcher.rs +++ b/crates/shirabe/src/event_dispatcher/event_dispatcher.rs @@ -609,11 +609,8 @@ impl EventDispatcher { .join(" "); // reusing the output from $this->io is mostly needed for tests, but generally speaking // it does not hurt to keep the same stream as the current Application - // TODO(phase-b): IOInterface needs an `as_any` shim before - // `instanceof ConsoleIO` can be expressed; treat io as a - // generic IOInterface for now. - let downcast: Option<&ConsoleIO> = None; - let output: ConsoleOutput = if let Some(_console_io) = downcast { + let is_console_io = self.io.borrow().as_any().is::<ConsoleIO>(); + let output: ConsoleOutput = if is_console_io { // TODO(plugin): \ReflectionProperty to read private `output` from ConsoleIO // is required by the original PHP — needs user-decided porting strategy. let _refl_php_version_gate = PHP_VERSION_ID < 80100; diff --git a/crates/shirabe/src/io/buffer_io.rs b/crates/shirabe/src/io/buffer_io.rs index ed87b71..291b64b 100644 --- a/crates/shirabe/src/io/buffer_io.rs +++ b/crates/shirabe/src/io/buffer_io.rs @@ -245,7 +245,11 @@ impl crate::io::IOInterfaceMutable for BufferIO { } } -impl crate::io::IOInterface for BufferIO {} +impl crate::io::IOInterface for BufferIO { + fn as_any(&self) -> &dyn std::any::Any { + self + } +} impl crate::io::BaseIO for BufferIO { fn authentications( diff --git a/crates/shirabe/src/io/console_io.rs b/crates/shirabe/src/io/console_io.rs index 2b1c334..b69b68b 100644 --- a/crates/shirabe/src/io/console_io.rs +++ b/crates/shirabe/src/io/console_io.rs @@ -142,10 +142,7 @@ impl ConsoleIO { messages }; - if true == stderr && self.output.is_console_output_interface() { - // TODO(phase-b): downcast Box<dyn OutputInterface> to ConsoleOutputInterface - let console_output: &dyn ConsoleOutputInterface = - todo!("downcast self.output to ConsoleOutputInterface"); + if stderr && let Some(console_output) = self.output.as_console_output_interface() { console_output.get_error_output().write( &Self::to_string_list(&messages).join(if newline { "\n" } else { "" }), newline, @@ -263,11 +260,8 @@ impl ConsoleIO { } fn get_error_output(&self) -> &dyn OutputInterface { - if self.output.is_console_output_interface() { - // TODO(phase-b): downcast Box<dyn OutputInterface> to ConsoleOutputInterface - return todo!( - "downcast self.output to ConsoleOutputInterface and call get_error_output()" - ); + if let Some(console_output) = self.output.as_console_output_interface() { + return console_output.get_error_output(); } &*self.output @@ -677,7 +671,11 @@ impl IOInterfaceMutable for ConsoleIO { } } -impl IOInterface for ConsoleIO {} +impl IOInterface for ConsoleIO { + fn as_any(&self) -> &dyn std::any::Any { + self + } +} impl BaseIO for ConsoleIO { fn authentications( diff --git a/crates/shirabe/src/io/io_interface.rs b/crates/shirabe/src/io/io_interface.rs index aac1488..e48f9ce 100644 --- a/crates/shirabe/src/io/io_interface.rs +++ b/crates/shirabe/src/io/io_interface.rs @@ -149,7 +149,9 @@ pub trait IOInterfaceMutable { // PHP `IOInterface`. This is the type used for the shared trait object // `dyn IOInterface`; its vtable carries both the immutable and mutable methods. -pub trait IOInterface: IOInterfaceImmutable + IOInterfaceMutable {} +pub trait IOInterface: IOInterfaceImmutable + IOInterfaceMutable { + fn as_any(&self) -> &dyn std::any::Any; +} // Shared-ownership handle for a PHP IO instance (reference semantics). It // exposes only the immutable surface; mutating methods (`set_authentication`, diff --git a/crates/shirabe/src/io/null_io.rs b/crates/shirabe/src/io/null_io.rs index b0e11f1..85a5fa5 100644 --- a/crates/shirabe/src/io/null_io.rs +++ b/crates/shirabe/src/io/null_io.rs @@ -138,7 +138,11 @@ impl IOInterfaceMutable for NullIO { } } -impl IOInterface for NullIO {} +impl IOInterface for NullIO { + fn as_any(&self) -> &dyn std::any::Any { + self + } +} impl BaseIO for NullIO { fn authentications( |
