aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe-external-packages/src/symfony/console/input
diff options
context:
space:
mode:
Diffstat (limited to 'crates/shirabe-external-packages/src/symfony/console/input')
-rw-r--r--crates/shirabe-external-packages/src/symfony/console/input/argv_input.rs657
-rw-r--r--crates/shirabe-external-packages/src/symfony/console/input/array_input.rs386
-rw-r--r--crates/shirabe-external-packages/src/symfony/console/input/input.rs225
-rw-r--r--crates/shirabe-external-packages/src/symfony/console/input/input_argument.rs96
-rw-r--r--crates/shirabe-external-packages/src/symfony/console/input/input_aware_interface.rs7
-rw-r--r--crates/shirabe-external-packages/src/symfony/console/input/input_definition.rs450
-rw-r--r--crates/shirabe-external-packages/src/symfony/console/input/input_interface.rs60
-rw-r--r--crates/shirabe-external-packages/src/symfony/console/input/input_option.rs193
-rw-r--r--crates/shirabe-external-packages/src/symfony/console/input/streamable_input_interface.rs10
-rw-r--r--crates/shirabe-external-packages/src/symfony/console/input/string_input.rs243
10 files changed, 0 insertions, 2327 deletions
diff --git a/crates/shirabe-external-packages/src/symfony/console/input/argv_input.rs b/crates/shirabe-external-packages/src/symfony/console/input/argv_input.rs
deleted file mode 100644
index 65ab9053..00000000
--- a/crates/shirabe-external-packages/src/symfony/console/input/argv_input.rs
+++ /dev/null
@@ -1,657 +0,0 @@
-//! ref: composer/vendor/symfony/console/Input/ArgvInput.php
-
-use crate::symfony::console::exception::runtime_exception::RuntimeException;
-use crate::symfony::console::input::input::Input;
-use crate::symfony::console::input::input_definition::InputDefinition;
-use crate::symfony::console::input::input_interface::InputInterface;
-use crate::symfony::console::input::streamable_input_interface::StreamableInputInterface;
-use indexmap::IndexMap;
-use shirabe_php_shim::{PhpMixed, php_regex};
-
-/// ArgvInput represents an input coming from the CLI arguments.
-///
-/// Usage:
-///
-/// ```php
-/// $input = new ArgvInput();
-/// ```
-///
-/// By default, the `$_SERVER['argv']` array is used for the input values.
-///
-/// This can be overridden by explicitly passing the input values in the constructor:
-///
-/// ```php
-/// $input = new ArgvInput($_SERVER['argv']);
-/// ```
-///
-/// If you pass it yourself, don't forget that the first element of the array
-/// is the name of the running application.
-///
-/// When passing an argument to the constructor, be sure that it respects
-/// the same rules as the argv one. It's almost always better to use the
-/// `StringInput` when you want to provide your own input.
-#[derive(Debug, Clone)]
-pub struct ArgvInput {
- pub(crate) inner: Input,
- tokens: Vec<String>,
- parsed: Vec<String>,
-}
-
-impl ArgvInput {
- pub fn new(
- argv: Option<Vec<String>>,
- definition: Option<InputDefinition>,
- ) -> anyhow::Result<Self> {
- // $argv = $argv ?? $_SERVER['argv'] ?? [];
- let mut argv = match argv {
- Some(argv) => argv,
- None => std::env::args().collect(),
- };
-
- // strip the application name
- if !argv.is_empty() {
- argv.remove(0);
- }
-
- let mut input = ArgvInput {
- inner: Input::new(None)?,
- tokens: argv,
- parsed: vec![],
- };
-
- // parent::__construct($definition)
- match definition {
- None => {}
- Some(definition) => {
- input.bind(&definition)?;
- input.inner.validate()?;
- }
- }
-
- Ok(input)
- }
-
- pub(crate) fn set_tokens(&mut self, tokens: Vec<String>) {
- self.tokens = tokens;
- }
-
- pub fn bind(&mut self, definition: &InputDefinition) -> anyhow::Result<()> {
- self.base_bind(definition, ArgvInput::parse_token)
- }
-
- /// Shared body of `bind` (PHP `Input::bind`). PHP's `$this->parse()` ends in
- /// `$this->parseToken()`, which late-binds to `CompletionInput::parseToken`; `parseToken`
- /// is protected and not part of any trait, so the concrete implementation is threaded in
- /// as a callback taking the embedded ArgvInput.
- pub(crate) fn base_bind(
- &mut self,
- definition: &InputDefinition,
- parse_token: impl FnMut(&mut ArgvInput, &str, bool) -> anyhow::Result<bool>,
- ) -> anyhow::Result<()> {
- self.inner.arguments = IndexMap::new();
- self.inner.options = IndexMap::new();
- self.inner.definition = definition.clone();
-
- self.base_parse(parse_token)?;
-
- Ok(())
- }
-
- /// Shared body of `parse`; see `base_bind` for why `parse_token` is a parameter.
- fn base_parse(
- &mut self,
- mut parse_token: impl FnMut(&mut ArgvInput, &str, bool) -> anyhow::Result<bool>,
- ) -> anyhow::Result<()> {
- let mut parse_options = true;
- self.parsed = self.tokens.clone();
- while !self.parsed.is_empty() {
- let token = self.parsed.remove(0);
- parse_options = parse_token(self, &token, parse_options)?;
- }
- Ok(())
- }
-
- pub(crate) fn parse_token(&mut self, token: &str, parse_options: bool) -> anyhow::Result<bool> {
- if parse_options && token.is_empty() {
- self.parse_argument(token)?;
- } else if parse_options && token == "--" {
- return Ok(false);
- } else if parse_options && shirabe_php_shim::str_starts_with(token, "--") {
- self.parse_long_option(token)?;
- } else if parse_options && token.as_bytes().first() == Some(&b'-') && token != "-" {
- self.parse_short_option(token)?;
- } else {
- self.parse_argument(token)?;
- }
-
- Ok(parse_options)
- }
-
- /// Parses a short option.
- fn parse_short_option(&mut self, token: &str) -> anyhow::Result<()> {
- let name = shirabe_php_shim::substr(token, 1, None);
-
- if shirabe_php_shim::strlen(&name) > 1 {
- let first = shirabe_php_shim::substr(&name, 0, Some(1));
- if self.inner.definition.has_shortcut(&first)
- && self
- .inner
- .definition
- .get_option_for_shortcut(&first)?
- .accept_value()
- {
- // an option with a value (with no space)
- self.add_short_option(
- &first,
- PhpMixed::String(shirabe_php_shim::substr(&name, 1, None)),
- )?;
- } else {
- self.parse_short_option_set(&name)?;
- }
- } else {
- self.add_short_option(&name, PhpMixed::Null)?;
- }
-
- Ok(())
- }
-
- /// Parses a short option set.
- fn parse_short_option_set(&mut self, name: &str) -> anyhow::Result<()> {
- let len = shirabe_php_shim::strlen(name);
- let mut i = 0;
- while i < len {
- let name_i = shirabe_php_shim::substr(name, i, Some(1));
- if !self.inner.definition.has_shortcut(&name_i) {
- let encoding = shirabe_php_shim::mb_detect_encoding(name, None, true);
- let bad = match encoding {
- None => name_i,
- Some(encoding) => {
- shirabe_php_shim::mb_substr(name, i, Some(1), Some(&encoding))
- }
- };
- return Err(RuntimeException::new(format!(
- "The \"-{}\" option does not exist.",
- bad
- ))
- .into());
- }
-
- let option = self.inner.definition.get_option_for_shortcut(&name_i)?;
- if option.accept_value() {
- let value = if i == len - 1 {
- PhpMixed::Null
- } else {
- PhpMixed::String(shirabe_php_shim::substr(name, i + 1, None))
- };
- self.add_long_option(option.get_name(), value)?;
-
- break;
- } else {
- self.add_long_option(option.get_name(), PhpMixed::Null)?;
- }
- i += 1;
- }
-
- Ok(())
- }
-
- /// Parses a long option.
- fn parse_long_option(&mut self, token: &str) -> anyhow::Result<()> {
- let name = shirabe_php_shim::substr(token, 2, None);
-
- match shirabe_php_shim::strpos(&name, "=") {
- Some(pos) => {
- let pos = pos as i64;
- let value = shirabe_php_shim::substr(&name, pos + 1, None);
- if value.is_empty() {
- self.parsed.insert(0, value.clone());
- }
- self.add_long_option(
- &shirabe_php_shim::substr(&name, 0, Some(pos)),
- PhpMixed::String(value),
- )?;
- }
- None => {
- self.add_long_option(&name, PhpMixed::Null)?;
- }
- }
-
- Ok(())
- }
-
- /// Parses an argument.
- fn parse_argument(&mut self, token: &str) -> anyhow::Result<()> {
- let c = self.inner.arguments.len() as i64;
-
- // if input is expecting another argument, add it
- if self.inner.definition.has_argument(&PhpMixed::Int(c)) {
- let arg = self.inner.definition.get_argument(&PhpMixed::Int(c))?;
- let value = if arg.is_array() {
- PhpMixed::List(vec![PhpMixed::String(token.to_string())])
- } else {
- PhpMixed::String(token.to_string())
- };
- self.inner
- .arguments
- .insert(arg.get_name().to_string(), value);
-
- // if last argument isArray(), append token to last argument
- } else if self.inner.definition.has_argument(&PhpMixed::Int(c - 1))
- && self
- .inner
- .definition
- .get_argument(&PhpMixed::Int(c - 1))?
- .is_array()
- {
- let arg = self.inner.definition.get_argument(&PhpMixed::Int(c - 1))?;
- if let Some(PhpMixed::List(list)) = self.inner.arguments.get_mut(arg.get_name()) {
- list.push(PhpMixed::String(token.to_string()));
- }
-
- // unexpected argument
- } else {
- let mut all = self.inner.definition.get_arguments().clone();
- let mut symfony_command_name: Option<PhpMixed> = None;
- let first_key = all.keys().next().cloned();
- if let Some(key) = &first_key {
- let input_argument = &all[key];
- if input_argument.get_name() == "command" {
- symfony_command_name = self.inner.arguments.get("command").cloned();
- all.shift_remove(key);
- }
- }
-
- let message = if !all.is_empty() {
- let names: Vec<String> = all.keys().cloned().collect();
- match &symfony_command_name {
- Some(symfony_command_name)
- if !matches!(symfony_command_name, PhpMixed::Null) =>
- {
- format!(
- "Too many arguments to \"{}\" command, expected arguments \"{}\".",
- symfony_command_name.clone(),
- shirabe_php_shim::implode("\" \"", &names),
- )
- }
- _ => format!(
- "Too many arguments, expected arguments \"{}\".",
- shirabe_php_shim::implode("\" \"", &names),
- ),
- }
- } else if symfony_command_name
- .as_ref()
- .map(|n| !matches!(n, PhpMixed::Null))
- .unwrap_or(false)
- {
- format!(
- "No arguments expected for \"{}\" command, got \"{}\".",
- symfony_command_name.unwrap(),
- token,
- )
- } else {
- format!("No arguments expected, got \"{}\".", token)
- };
-
- return Err(RuntimeException::new(message).into());
- }
-
- Ok(())
- }
-
- /// Adds a short option value.
- fn add_short_option(&mut self, shortcut: &str, value: PhpMixed) -> anyhow::Result<()> {
- if !self.inner.definition.has_shortcut(shortcut) {
- return Err(RuntimeException::new(format!(
- "The \"-{}\" option does not exist.",
- shortcut
- ))
- .into());
- }
-
- self.add_long_option(
- self.inner
- .definition
- .get_option_for_shortcut(shortcut)?
- .get_name(),
- value,
- )
- }
-
- /// Adds a long option value.
- fn add_long_option(&mut self, name: &str, mut value: PhpMixed) -> anyhow::Result<()> {
- if !self.inner.definition.has_option(name) {
- if !self.inner.definition.has_negation(name) {
- return Err(RuntimeException::new(format!(
- "The \"--{}\" option does not exist.",
- name
- ))
- .into());
- }
-
- let option_name = self.inner.definition.negation_to_name(name)?;
- if !matches!(value, PhpMixed::Null) {
- return Err(RuntimeException::new(format!(
- "The \"--{}\" option does not accept a value.",
- name
- ))
- .into());
- }
- self.inner
- .options
- .insert(option_name, PhpMixed::Bool(false));
-
- return Ok(());
- }
-
- let option = self.inner.definition.get_option(name)?;
-
- if !matches!(value, PhpMixed::Null) && !option.accept_value() {
- return Err(RuntimeException::new(format!(
- "The \"--{}\" option does not accept a value.",
- name
- ))
- .into());
- }
-
- // in_array($value, ['', null], true)
- let value_is_empty_or_null = matches!(&value, PhpMixed::String(s) if s.is_empty())
- || matches!(value, PhpMixed::Null);
- if value_is_empty_or_null && option.accept_value() && !self.parsed.is_empty() {
- // if option accepts an optional or mandatory argument
- // let's see if there is one provided
- let next = self.parsed.remove(0);
- // (isset($next[0]) && '-' !== $next[0]) || in_array($next, ['', null], true)
- let next_first = next.as_bytes().first().copied();
- if (next_first.is_some() && next_first != Some(b'-')) || next.is_empty() {
- value = PhpMixed::String(next);
- } else {
- self.parsed.insert(0, next);
- }
- }
-
- if matches!(value, PhpMixed::Null) {
- if option.is_value_required() {
- return Err(RuntimeException::new(format!(
- "The \"--{}\" option requires a value.",
- name
- ))
- .into());
- }
-
- if !option.is_array() && !option.is_value_optional() {
- value = PhpMixed::Bool(true);
- }
- }
-
- if option.is_array() {
- match self.inner.options.get_mut(name) {
- Some(PhpMixed::List(list)) => {
- list.push(value);
- }
- _ => {
- self.inner
- .options
- .insert(name.to_string(), PhpMixed::List(vec![value]));
- }
- }
- } else {
- self.inner.options.insert(name.to_string(), value);
- }
-
- Ok(())
- }
-
- pub fn get_first_argument(&self) -> Option<String> {
- let mut is_option = false;
- for (i, token) in self.tokens.iter().enumerate() {
- if !token.is_empty() && token.as_bytes()[0] == b'-' {
- if shirabe_php_shim::str_contains(token, "=") || self.tokens.get(i + 1).is_none() {
- continue;
- }
-
- // If it's a long option, consider that everything after "--" is the option name.
- // Otherwise, use the last char (if it's a short option set, only the last one can take a value with space separator)
- let mut name = if token.as_bytes().get(1) == Some(&b'-') {
- shirabe_php_shim::substr(token, 2, None)
- } else {
- shirabe_php_shim::substr(token, -1, None)
- };
- if !self.inner.options.contains_key(&name)
- && !self.inner.definition.has_shortcut(&name)
- {
- // noop
- } else {
- if !self.inner.options.contains_key(&name)
- && let Ok(resolved) = self.inner.definition.shortcut_to_name(&name)
- {
- name = resolved;
- }
- if let Some(option_value) = self.inner.options.get(&name)
- && self.tokens.get(i + 1).map(|t| t.as_str()) == option_value.as_string()
- {
- is_option = true;
- }
- }
-
- continue;
- }
-
- if is_option {
- is_option = false;
- continue;
- }
-
- return Some(token.clone());
- }
-
- None
- }
-
- pub fn has_parameter_option(&self, values: PhpMixed, only_params: bool) -> bool {
- let values = to_array(values);
-
- for token in &self.tokens {
- if only_params && token == "--" {
- return false;
- }
- for value in &values {
- // Options with values:
- // For long options, test for '--option=' at beginning
- // For short options, test for '-o' at beginning
- let leading = if shirabe_php_shim::str_starts_with(value, "--") {
- format!("{}=", value)
- } else {
- value.clone()
- };
- if token == value
- || (!leading.is_empty() && shirabe_php_shim::str_starts_with(token, &leading))
- {
- return true;
- }
- }
- }
-
- false
- }
-
- pub fn get_parameter_option(
- &self,
- values: PhpMixed,
- default: PhpMixed,
- only_params: bool,
- ) -> PhpMixed {
- let values = to_array(values);
- let mut tokens = self.tokens.clone();
-
- while !tokens.is_empty() {
- let token = tokens.remove(0);
- if only_params && token == "--" {
- return default;
- }
-
- for value in &values {
- if &token == value {
- return match tokens.first() {
- Some(_) => PhpMixed::String(tokens.remove(0)),
- None => PhpMixed::Null,
- };
- }
- // Options with values:
- // For long options, test for '--option=' at beginning
- // For short options, test for '-o' at beginning
- let leading = if shirabe_php_shim::str_starts_with(value, "--") {
- format!("{}=", value)
- } else {
- value.clone()
- };
- if !leading.is_empty() && shirabe_php_shim::str_starts_with(&token, &leading) {
- return PhpMixed::String(shirabe_php_shim::substr(
- &token,
- shirabe_php_shim::strlen(&leading),
- None,
- ));
- }
- }
- }
-
- default
- }
-}
-
-/// Returns a stringified representation of the args passed to the command.
-impl std::fmt::Display for ArgvInput {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- let tokens: Vec<String> = self
- .tokens
- .iter()
- .map(|token| {
- let mut r#match: Vec<Option<String>> = Vec::new();
- if shirabe_php_shim::preg_match(php_regex!("{^(-[^=]+=)(.+)}"), token, &mut r#match)
- {
- return format!(
- "{}{}",
- r#match[1].as_deref().unwrap_or(""),
- self.inner.escape_token(r#match[2].as_deref().unwrap_or(""))
- );
- }
-
- if !token.is_empty() && token.as_bytes()[0] != b'-' {
- return self.inner.escape_token(token);
- }
-
- token.clone()
- })
- .collect();
-
- write!(f, "{}", shirabe_php_shim::implode(" ", &tokens))
- }
-}
-
-impl InputInterface for ArgvInput {
- fn dup(&self) -> std::rc::Rc<std::cell::RefCell<dyn InputInterface>> {
- std::rc::Rc::new(std::cell::RefCell::new(self.clone()))
- }
-
- fn get_first_argument(&self) -> Option<String> {
- ArgvInput::get_first_argument(self)
- }
-
- fn has_parameter_option(&self, values: PhpMixed, only_params: bool) -> bool {
- ArgvInput::has_parameter_option(self, values, only_params)
- }
-
- fn get_parameter_option(
- &self,
- values: PhpMixed,
- default: PhpMixed,
- only_params: bool,
- ) -> PhpMixed {
- ArgvInput::get_parameter_option(self, values, default, only_params)
- }
-
- fn bind(&mut self, definition: &InputDefinition) -> anyhow::Result<()> {
- ArgvInput::bind(self, definition)
- }
-
- fn validate(&mut self) -> anyhow::Result<()> {
- self.inner.validate()
- }
-
- fn get_arguments(&self) -> IndexMap<String, PhpMixed> {
- self.inner.get_arguments()
- }
-
- fn get_argument(&self, name: &str) -> anyhow::Result<PhpMixed> {
- self.inner.get_argument(name)
- }
-
- fn set_argument(&mut self, name: &str, value: PhpMixed) -> anyhow::Result<()> {
- self.inner.set_argument(name, value)
- }
-
- fn has_argument(&self, name: &str) -> bool {
- self.inner.has_argument(name)
- }
-
- fn get_options(&self) -> IndexMap<String, PhpMixed> {
- self.inner.get_options()
- }
-
- fn get_option(&self, name: &str) -> anyhow::Result<PhpMixed> {
- self.inner.get_option(name)
- }
-
- fn set_option(&mut self, name: &str, value: PhpMixed) -> anyhow::Result<()> {
- self.inner.set_option(name, value)
- }
-
- fn has_option(&self, name: &str) -> bool {
- self.inner.has_option(name)
- }
-
- fn is_interactive(&self) -> bool {
- self.inner.is_interactive()
- }
-
- fn set_interactive(&mut self, interactive: bool) {
- self.inner.set_interactive(interactive)
- }
-
- fn __to_string(&self) -> String {
- self.to_string()
- }
-
- fn as_streamable(&self) -> Option<&dyn StreamableInputInterface> {
- Some(self)
- }
-
- fn as_streamable_mut(&mut self) -> Option<&mut dyn StreamableInputInterface> {
- Some(self)
- }
-}
-
-impl StreamableInputInterface for ArgvInput {
- fn set_stream(&mut self, stream: shirabe_php_shim::PhpResource) {
- self.inner.set_stream(stream)
- }
-
- fn get_stream(&self) -> Option<shirabe_php_shim::PhpResource> {
- self.inner.get_stream()
- }
-}
-
-/// PHP `(array) $values` cast: a string becomes a single-element array.
-fn to_array(values: PhpMixed) -> Vec<String> {
- match values {
- PhpMixed::List(list) => list
- .into_iter()
- .map(|v| shirabe_php_shim::php_to_string(&v))
- .collect(),
- PhpMixed::Array(array) => array
- .into_iter()
- .map(|(_, v)| shirabe_php_shim::php_to_string(&v))
- .collect(),
- PhpMixed::Null => vec![],
- other => vec![shirabe_php_shim::php_to_string(&other)],
- }
-}
diff --git a/crates/shirabe-external-packages/src/symfony/console/input/array_input.rs b/crates/shirabe-external-packages/src/symfony/console/input/array_input.rs
deleted file mode 100644
index de89a340..00000000
--- a/crates/shirabe-external-packages/src/symfony/console/input/array_input.rs
+++ /dev/null
@@ -1,386 +0,0 @@
-//! ref: composer/vendor/symfony/console/Input/ArrayInput.php
-
-use crate::symfony::console::exception::invalid_argument_exception::InvalidArgumentException;
-use crate::symfony::console::exception::invalid_option_exception::InvalidOptionException;
-use crate::symfony::console::input::input::Input;
-use crate::symfony::console::input::input_definition::InputDefinition;
-use crate::symfony::console::input::input_interface::InputInterface;
-use crate::symfony::console::input::streamable_input_interface::StreamableInputInterface;
-use indexmap::IndexMap;
-use shirabe_php_shim::PhpMixed;
-
-/// ArrayInput represents an input provided as an array.
-///
-/// Usage:
-///
-/// ```php
-/// $input = new ArrayInput(['command' => 'foo:bar', 'foo' => 'bar', '--bar' => 'foobar']);
-/// ```
-///
-/// PHP arrays can mix integer and string keys; `parameters` preserves both the
-/// key type (`PhpMixed::Int` / `PhpMixed::String`) and the insertion order.
-#[derive(Debug, Clone)]
-pub struct ArrayInput {
- pub(crate) inner: Input,
- parameters: Vec<(PhpMixed, PhpMixed)>,
-}
-
-impl ArrayInput {
- pub fn new(
- parameters: Vec<(PhpMixed, PhpMixed)>,
- definition: Option<InputDefinition>,
- ) -> anyhow::Result<Self> {
- let mut array_input = ArrayInput {
- inner: Input::new(None)?,
- parameters,
- };
-
- // parent::__construct($definition)
- match definition {
- None => {}
- Some(definition) => {
- array_input.bind(&definition)?;
- array_input.inner.validate()?;
- }
- }
-
- Ok(array_input)
- }
-
- pub fn bind(&mut self, definition: &InputDefinition) -> anyhow::Result<()> {
- self.inner.arguments = IndexMap::new();
- self.inner.options = IndexMap::new();
- self.inner.definition = definition.clone();
-
- self.parse()?;
-
- Ok(())
- }
-
- pub fn get_first_argument(&self) -> Option<PhpMixed> {
- for (param, value) in &self.parameters {
- // $param && \is_string($param) && '-' === $param[0]
- if let PhpMixed::String(param) = param
- && !param.is_empty()
- && param.as_bytes()[0] == b'-'
- {
- continue;
- }
-
- return Some(value.clone());
- }
-
- None
- }
-
- pub fn has_parameter_option(&self, values: PhpMixed, only_params: bool) -> bool {
- let values = to_array(values);
-
- for (k, v) in &self.parameters {
- // if (!\is_int($k)) { $v = $k; }
- let v: PhpMixed = match k {
- PhpMixed::Int(_) => v.clone(),
- _ => k.clone(),
- };
-
- if only_params && matches!(&v, PhpMixed::String(s) if s == "--") {
- return false;
- }
-
- if values.iter().any(|x| x == &v) {
- return true;
- }
- }
-
- false
- }
-
- pub fn get_parameter_option(
- &self,
- values: PhpMixed,
- default: PhpMixed,
- only_params: bool,
- ) -> PhpMixed {
- let values = to_array(values);
-
- for (k, v) in &self.parameters {
- // $onlyParams && ('--' === $k || (\is_int($k) && '--' === $v))
- if only_params {
- let k_is_double_dash = matches!(k, PhpMixed::String(s) if s == "--");
- let int_v_double_dash =
- matches!(k, PhpMixed::Int(_)) && matches!(v, PhpMixed::String(s) if s == "--");
- if k_is_double_dash || int_v_double_dash {
- return default;
- }
- }
-
- match k {
- PhpMixed::Int(_) => {
- if values.iter().any(|x| x == v) {
- return PhpMixed::Bool(true);
- }
- }
- _ => {
- if values.iter().any(|x| x == k) {
- return v.clone();
- }
- }
- }
- }
-
- default
- }
-
- fn parse(&mut self) -> anyhow::Result<()> {
- // Clone to avoid borrowing self while mutating; PHP iterates over a copy semantically.
- let parameters = self.parameters.clone();
- for (key, value) in parameters {
- let key = shirabe_php_shim::php_to_string(&key);
- if key == "--" {
- return Ok(());
- }
- if shirabe_php_shim::str_starts_with(&key, "--") {
- self.add_long_option(&shirabe_php_shim::substr(&key, 2, None), value)?;
- } else if shirabe_php_shim::str_starts_with(&key, "-") {
- self.add_short_option(&shirabe_php_shim::substr(&key, 1, None), value)?;
- } else {
- self.add_argument(&PhpMixed::String(key), value)?;
- }
- }
-
- Ok(())
- }
-
- /// Adds a short option value.
- fn add_short_option(&mut self, shortcut: &str, value: PhpMixed) -> anyhow::Result<()> {
- if !self.inner.definition.has_shortcut(shortcut) {
- return Err(InvalidOptionException::new(format!(
- "The \"-{}\" option does not exist.",
- shortcut
- ))
- .into());
- }
-
- self.add_long_option(
- self.inner
- .definition
- .get_option_for_shortcut(shortcut)?
- .get_name(),
- value,
- )
- }
-
- /// Adds a long option value.
- fn add_long_option(&mut self, name: &str, mut value: PhpMixed) -> anyhow::Result<()> {
- if !self.inner.definition.has_option(name) {
- if !self.inner.definition.has_negation(name) {
- return Err(InvalidOptionException::new(format!(
- "The \"--{}\" option does not exist.",
- name
- ))
- .into());
- }
-
- let option_name = self.inner.definition.negation_to_name(name)?;
- self.inner
- .options
- .insert(option_name, PhpMixed::Bool(false));
-
- return Ok(());
- }
-
- let option = self.inner.definition.get_option(name)?;
-
- if matches!(value, PhpMixed::Null) {
- if option.is_value_required() {
- return Err(InvalidOptionException::new(format!(
- "The \"--{}\" option requires a value.",
- name
- ))
- .into());
- }
-
- if !option.is_value_optional() {
- value = PhpMixed::Bool(true);
- }
- }
-
- self.inner.options.insert(name.to_string(), value);
-
- Ok(())
- }
-
- /// Adds an argument value.
- fn add_argument(&mut self, name: &PhpMixed, value: PhpMixed) -> anyhow::Result<()> {
- if !self.inner.definition.has_argument(name) {
- return Err(InvalidArgumentException::new(format!(
- "The \"{}\" argument does not exist.",
- name.clone()
- ))
- .into());
- }
-
- self.inner
- .arguments
- .insert(shirabe_php_shim::php_to_string(name), value);
-
- Ok(())
- }
-}
-
-/// Returns a stringified representation of the args passed to the command.
-impl std::fmt::Display for ArrayInput {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- let mut params: Vec<String> = vec![];
- for (param, val) in &self.parameters {
- // $param && \is_string($param) && '-' === $param[0]
- let is_option_key =
- matches!(param, PhpMixed::String(s) if !s.is_empty() && s.as_bytes()[0] == b'-');
- if is_option_key {
- let param = param.as_string().unwrap();
- let glue = if param.as_bytes().get(1) == Some(&b'-') {
- "="
- } else {
- " "
- };
- if let PhpMixed::List(list) = val {
- for v in list {
- let v = shirabe_php_shim::php_to_string(v);
- params.push(format!(
- "{}{}",
- param,
- if !v.is_empty() {
- format!("{}{}", glue, self.inner.escape_token(&v))
- } else {
- String::new()
- }
- ));
- }
- } else {
- let val = shirabe_php_shim::php_to_string(val);
- params.push(format!(
- "{}{}",
- param,
- if !val.is_empty() {
- format!("{}{}", glue, self.inner.escape_token(&val))
- } else {
- String::new()
- }
- ));
- }
- } else if let PhpMixed::List(list) = val {
- let escaped: Vec<String> = list
- .iter()
- .map(|v| self.inner.escape_token(&shirabe_php_shim::php_to_string(v)))
- .collect();
- params.push(shirabe_php_shim::implode(" ", &escaped));
- } else {
- params.push(
- self.inner
- .escape_token(&shirabe_php_shim::php_to_string(val)),
- );
- }
- }
-
- write!(f, "{}", shirabe_php_shim::implode(" ", &params))
- }
-}
-
-impl InputInterface for ArrayInput {
- fn dup(&self) -> std::rc::Rc<std::cell::RefCell<dyn InputInterface>> {
- std::rc::Rc::new(std::cell::RefCell::new(self.clone()))
- }
-
- fn get_first_argument(&self) -> Option<String> {
- ArrayInput::get_first_argument(self).map(|v| shirabe_php_shim::php_to_string(&v))
- }
-
- fn has_parameter_option(&self, values: PhpMixed, only_params: bool) -> bool {
- ArrayInput::has_parameter_option(self, values, only_params)
- }
-
- fn get_parameter_option(
- &self,
- values: PhpMixed,
- default: PhpMixed,
- only_params: bool,
- ) -> PhpMixed {
- ArrayInput::get_parameter_option(self, values, default, only_params)
- }
-
- fn bind(&mut self, definition: &InputDefinition) -> anyhow::Result<()> {
- ArrayInput::bind(self, definition)
- }
-
- fn validate(&mut self) -> anyhow::Result<()> {
- self.inner.validate()
- }
-
- fn get_arguments(&self) -> IndexMap<String, PhpMixed> {
- self.inner.get_arguments()
- }
-
- fn get_argument(&self, name: &str) -> anyhow::Result<PhpMixed> {
- self.inner.get_argument(name)
- }
-
- fn set_argument(&mut self, name: &str, value: PhpMixed) -> anyhow::Result<()> {
- self.inner.set_argument(name, value)
- }
-
- fn has_argument(&self, name: &str) -> bool {
- self.inner.has_argument(name)
- }
-
- fn get_options(&self) -> IndexMap<String, PhpMixed> {
- self.inner.get_options()
- }
-
- fn get_option(&self, name: &str) -> anyhow::Result<PhpMixed> {
- self.inner.get_option(name)
- }
-
- fn set_option(&mut self, name: &str, value: PhpMixed) -> anyhow::Result<()> {
- self.inner.set_option(name, value)
- }
-
- fn has_option(&self, name: &str) -> bool {
- self.inner.has_option(name)
- }
-
- fn is_interactive(&self) -> bool {
- self.inner.is_interactive()
- }
-
- fn set_interactive(&mut self, interactive: bool) {
- self.inner.set_interactive(interactive)
- }
-
- fn __to_string(&self) -> String {
- self.to_string()
- }
-
- fn as_streamable(&self) -> Option<&dyn StreamableInputInterface> {
- Some(self)
- }
-}
-
-impl StreamableInputInterface for ArrayInput {
- fn set_stream(&mut self, stream: shirabe_php_shim::PhpResource) {
- self.inner.set_stream(stream)
- }
-
- fn get_stream(&self) -> Option<shirabe_php_shim::PhpResource> {
- self.inner.get_stream()
- }
-}
-
-/// PHP `(array) $values` cast: a string becomes a single-element array.
-fn to_array(values: PhpMixed) -> Vec<PhpMixed> {
- match values {
- PhpMixed::List(list) => list.into_iter().collect(),
- PhpMixed::Array(array) => array.into_iter().map(|(_, v)| v).collect(),
- PhpMixed::Null => vec![],
- other => vec![other],
- }
-}
diff --git a/crates/shirabe-external-packages/src/symfony/console/input/input.rs b/crates/shirabe-external-packages/src/symfony/console/input/input.rs
deleted file mode 100644
index ceff85f6..00000000
--- a/crates/shirabe-external-packages/src/symfony/console/input/input.rs
+++ /dev/null
@@ -1,225 +0,0 @@
-//! ref: composer/vendor/symfony/console/Input/Input.php
-
-use crate::symfony::console::exception::invalid_argument_exception::InvalidArgumentException;
-use crate::symfony::console::exception::runtime_exception::RuntimeException;
-use crate::symfony::console::input::input_definition::InputDefinition;
-use indexmap::IndexMap;
-use shirabe_php_shim::{PhpMixed, PhpResource, php_regex};
-
-/// Input is the base class for all concrete Input classes.
-///
-/// Three concrete classes are provided by default:
-///
-/// * `ArgvInput`: The input comes from the CLI arguments (argv)
-/// * `StringInput`: The input is provided as a string
-/// * `ArrayInput`: The input is provided as an array
-#[derive(Debug, Clone)]
-pub struct Input {
- pub(crate) definition: InputDefinition,
- pub(crate) stream: Option<PhpResource>,
- pub(crate) options: IndexMap<String, PhpMixed>,
- pub(crate) arguments: IndexMap<String, PhpMixed>,
- pub(crate) interactive: bool,
-}
-
-impl Input {
- pub fn new(definition: Option<InputDefinition>) -> anyhow::Result<Self> {
- let mut input = Input {
- definition: InputDefinition::new(vec![])?,
- stream: None,
- options: IndexMap::new(),
- arguments: IndexMap::new(),
- interactive: true,
- };
-
- match definition {
- None => {
- input.definition = InputDefinition::new(vec![])?;
- }
- Some(definition) => {
- input.bind(&definition)?;
- input.validate()?;
- }
- }
-
- Ok(input)
- }
-
- pub fn bind(&mut self, definition: &InputDefinition) -> anyhow::Result<()> {
- self.arguments = IndexMap::new();
- self.options = IndexMap::new();
- self.definition = definition.clone();
-
- self.parse()?;
-
- Ok(())
- }
-
- /// Processes command line arguments.
- ///
- /// This is abstract in PHP; concrete subclasses provide their own `parse`.
- /// Since `Input` is embedded via `inner` in the subclasses, the subclass
- /// drives the parsing instead.
- fn parse(&mut self) -> anyhow::Result<()> {
- unreachable!("Input::parse is abstract and overridden by subclasses")
- }
-
- pub fn validate(&mut self) -> anyhow::Result<()> {
- let definition = &self.definition;
- let given_arguments = &self.arguments;
-
- let missing_arguments: Vec<String> = shirabe_php_shim::array_filter(
- &shirabe_php_shim::array_keys(definition.get_arguments()),
- |argument: &String| {
- !given_arguments.contains_key(argument)
- && definition
- .get_argument(&PhpMixed::String(argument.clone()))
- .map(|a| a.is_required())
- .unwrap_or(false)
- },
- );
-
- if !missing_arguments.is_empty() {
- return Err(RuntimeException::new(format!(
- "Not enough arguments (missing: \"{}\").",
- shirabe_php_shim::implode(", ", &missing_arguments),
- ))
- .into());
- }
-
- Ok(())
- }
-
- pub fn is_interactive(&self) -> bool {
- self.interactive
- }
-
- pub fn set_interactive(&mut self, interactive: bool) {
- self.interactive = interactive;
- }
-
- pub fn get_arguments(&self) -> IndexMap<String, PhpMixed> {
- shirabe_php_shim::array_merge_map(
- self.definition.get_argument_defaults(),
- self.arguments.clone(),
- )
- }
-
- pub fn get_argument(&self, name: &str) -> anyhow::Result<PhpMixed> {
- if !self
- .definition
- .has_argument(&PhpMixed::String(name.to_string()))
- {
- return Err(InvalidArgumentException::new(format!(
- "The \"{}\" argument does not exist.",
- name
- ))
- .into());
- }
-
- Ok(match self.arguments.get(name) {
- Some(value) => value.clone(),
- None => self
- .definition
- .get_argument(&PhpMixed::String(name.to_string()))?
- .get_default()
- .clone(),
- })
- }
-
- pub fn set_argument(&mut self, name: &str, value: PhpMixed) -> anyhow::Result<()> {
- if !self
- .definition
- .has_argument(&PhpMixed::String(name.to_string()))
- {
- return Err(InvalidArgumentException::new(format!(
- "The \"{}\" argument does not exist.",
- name
- ))
- .into());
- }
-
- self.arguments.insert(name.to_string(), value);
-
- Ok(())
- }
-
- pub fn has_argument(&self, name: &str) -> bool {
- self.definition
- .has_argument(&PhpMixed::String(name.to_string()))
- }
-
- pub fn get_options(&self) -> IndexMap<String, PhpMixed> {
- shirabe_php_shim::array_merge_map(
- self.definition.get_option_defaults(),
- self.options.clone(),
- )
- }
-
- pub fn get_option(&self, name: &str) -> anyhow::Result<PhpMixed> {
- if self.definition.has_negation(name) {
- let value = self.get_option(&self.definition.negation_to_name(name)?)?;
- if matches!(value, PhpMixed::Null) {
- return Ok(value);
- }
-
- return Ok(PhpMixed::Bool(!value.as_bool().unwrap_or(false)));
- }
-
- if !self.definition.has_option(name) {
- return Err(InvalidArgumentException::new(format!(
- "The \"{}\" option does not exist.",
- name
- ))
- .into());
- }
-
- Ok(if self.options.contains_key(name) {
- self.options[name].clone()
- } else {
- self.definition.get_option(name)?.get_default().clone()
- })
- }
-
- pub fn set_option(&mut self, name: &str, value: PhpMixed) -> anyhow::Result<()> {
- if self.definition.has_negation(name) {
- let negated = self.definition.negation_to_name(name)?;
- self.options
- .insert(negated, PhpMixed::Bool(!value.as_bool().unwrap_or(false)));
-
- return Ok(());
- } else if !self.definition.has_option(name) {
- return Err(InvalidArgumentException::new(format!(
- "The \"{}\" option does not exist.",
- name
- ))
- .into());
- }
-
- self.options.insert(name.to_string(), value);
-
- Ok(())
- }
-
- pub fn has_option(&self, name: &str) -> bool {
- self.definition.has_option(name) || self.definition.has_negation(name)
- }
-
- /// Escapes a token through escapeshellarg if it contains unsafe chars.
- pub fn escape_token(&self, token: &str) -> String {
- let mut matches: Vec<Option<String>> = vec![];
- if shirabe_php_shim::preg_match(php_regex!("{^[\\w-]+$}"), token, &mut matches) {
- token.to_string()
- } else {
- shirabe_php_shim::escapeshellarg(token)
- }
- }
-
- pub fn set_stream(&mut self, stream: PhpResource) {
- self.stream = Some(stream);
- }
-
- pub fn get_stream(&self) -> Option<PhpResource> {
- self.stream.clone()
- }
-}
diff --git a/crates/shirabe-external-packages/src/symfony/console/input/input_argument.rs b/crates/shirabe-external-packages/src/symfony/console/input/input_argument.rs
deleted file mode 100644
index 35f62389..00000000
--- a/crates/shirabe-external-packages/src/symfony/console/input/input_argument.rs
+++ /dev/null
@@ -1,96 +0,0 @@
-//! ref: composer/vendor/symfony/console/Input/InputArgument.php
-
-use crate::symfony::console::exception::invalid_argument_exception::InvalidArgumentException;
-use crate::symfony::console::exception::logic_exception::LogicException;
-use shirabe_php_shim::PhpMixed;
-
-#[derive(Debug, Clone)]
-pub struct InputArgument {
- name: String,
- mode: i64,
- default: PhpMixed,
- description: String,
-}
-
-impl InputArgument {
- pub const REQUIRED: i64 = 1;
- pub const OPTIONAL: i64 = 2;
- pub const IS_ARRAY: i64 = 4;
-
- pub fn new(
- name: String,
- mode: Option<i64>,
- description: String,
- default: PhpMixed,
- ) -> anyhow::Result<Self> {
- let mode = match mode {
- None => Self::OPTIONAL,
- Some(m) if !(1..=7).contains(&m) => {
- return Err(InvalidArgumentException::new(format!(
- "Argument mode \"{}\" is not valid.",
- m
- ))
- .into());
- }
- Some(m) => m,
- };
-
- let mut argument = InputArgument {
- name,
- mode,
- description,
- default: PhpMixed::Null,
- };
-
- argument.set_default(default)?;
-
- Ok(argument)
- }
-
- pub fn get_name(&self) -> &str {
- &self.name
- }
-
- pub fn is_required(&self) -> bool {
- Self::REQUIRED == (Self::REQUIRED & self.mode)
- }
-
- pub fn is_array(&self) -> bool {
- Self::IS_ARRAY == (Self::IS_ARRAY & self.mode)
- }
-
- pub fn set_default(&mut self, default: PhpMixed) -> anyhow::Result<()> {
- if self.is_required() && !matches!(default, PhpMixed::Null) {
- return Err(LogicException::new(
- "Cannot set a default value except for InputArgument::OPTIONAL mode.".to_string(),
- )
- .into());
- }
-
- let default = if self.is_array() {
- match default {
- PhpMixed::Null => PhpMixed::List(vec![]),
- PhpMixed::List(_) => default,
- _ => {
- return Err(LogicException::new(
- "A default value for an array argument must be an array.".to_string(),
- )
- .into());
- }
- }
- } else {
- default
- };
-
- self.default = default;
- Ok(())
- }
-
- pub fn get_default(&self) -> &PhpMixed {
- &self.default
- }
-
- pub fn get_description(&self) -> &str {
- &self.description
- }
-}
diff --git a/crates/shirabe-external-packages/src/symfony/console/input/input_aware_interface.rs b/crates/shirabe-external-packages/src/symfony/console/input/input_aware_interface.rs
deleted file mode 100644
index 0d042808..00000000
--- a/crates/shirabe-external-packages/src/symfony/console/input/input_aware_interface.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//! ref: composer/vendor/symfony/console/Input/InputAwareInterface.php
-
-use crate::symfony::console::input::input_interface::InputInterface;
-
-pub trait InputAwareInterface {
- fn set_input(&mut self, input: Box<dyn InputInterface>);
-}
diff --git a/crates/shirabe-external-packages/src/symfony/console/input/input_definition.rs b/crates/shirabe-external-packages/src/symfony/console/input/input_definition.rs
deleted file mode 100644
index bd32a8f9..00000000
--- a/crates/shirabe-external-packages/src/symfony/console/input/input_definition.rs
+++ /dev/null
@@ -1,450 +0,0 @@
-//! ref: composer/vendor/symfony/console/Input/InputDefinition.php
-
-use crate::symfony::console::exception::invalid_argument_exception::InvalidArgumentException;
-use crate::symfony::console::exception::logic_exception::LogicException;
-use crate::symfony::console::input::input_argument::InputArgument;
-use crate::symfony::console::input::input_option::InputOption;
-use indexmap::IndexMap;
-use shirabe_php_shim::PhpMixed;
-
-/// A InputDefinition represents a set of valid command line arguments and options.
-///
-/// `InputArgument` and `InputOption` are stored behind `Rc` to model PHP's
-/// shared object references; this also lets the definition be cloned cheaply
-/// (PHP `bind` assigns the definition by reference).
-#[derive(Debug, Clone)]
-pub struct InputDefinition {
- arguments: IndexMap<String, std::rc::Rc<InputArgument>>,
- required_count: i64,
- last_array_argument: Option<std::rc::Rc<InputArgument>>,
- last_optional_argument: Option<std::rc::Rc<InputArgument>>,
- options: IndexMap<String, std::rc::Rc<InputOption>>,
- negations: IndexMap<String, String>,
- shortcuts: IndexMap<String, String>,
-}
-
-/// A definition entry is either an InputArgument or an InputOption.
-#[derive(Debug)]
-pub enum DefinitionItem {
- InputArgument(InputArgument),
- InputOption(InputOption),
-}
-
-impl InputDefinition {
- pub fn new(definition: Vec<DefinitionItem>) -> anyhow::Result<Self> {
- let mut input_definition = InputDefinition {
- arguments: IndexMap::new(),
- required_count: 0,
- last_array_argument: None,
- last_optional_argument: None,
- options: IndexMap::new(),
- negations: IndexMap::new(),
- shortcuts: IndexMap::new(),
- };
- input_definition.set_definition(definition)?;
- Ok(input_definition)
- }
-
- /// Builds an option-only definition that shares the given options by
- /// reference, mirroring `new InputDefinition($definition->getOptions())`.
- /// `InputOption` is not `Clone` and lives behind `Rc`, so the options are
- /// reused rather than reconstructed by value.
- pub fn from_options(options: Vec<std::rc::Rc<InputOption>>) -> anyhow::Result<Self> {
- let mut input_definition = InputDefinition {
- arguments: IndexMap::new(),
- required_count: 0,
- last_array_argument: None,
- last_optional_argument: None,
- options: IndexMap::new(),
- negations: IndexMap::new(),
- shortcuts: IndexMap::new(),
- };
- for option in options {
- input_definition.add_option_rc(option)?;
- }
- Ok(input_definition)
- }
-
- /// Sets the definition of the input.
- pub fn set_definition(&mut self, definition: Vec<DefinitionItem>) -> anyhow::Result<()> {
- let mut arguments = vec![];
- let mut options = vec![];
- for item in definition {
- match item {
- DefinitionItem::InputOption(option) => {
- options.push(option);
- }
- DefinitionItem::InputArgument(argument) => {
- arguments.push(argument);
- }
- }
- }
-
- self.set_arguments(arguments)?;
- self.set_options(options)?;
-
- Ok(())
- }
-
- /// Sets the InputArgument objects.
- pub fn set_arguments(&mut self, arguments: Vec<InputArgument>) -> anyhow::Result<()> {
- self.arguments = IndexMap::new();
- self.required_count = 0;
- self.last_optional_argument = None;
- self.last_array_argument = None;
- self.add_arguments(Some(arguments))?;
- Ok(())
- }
-
- /// Adds an array of InputArgument objects.
- pub fn add_arguments(&mut self, arguments: Option<Vec<InputArgument>>) -> anyhow::Result<()> {
- if let Some(arguments) = arguments {
- for argument in arguments {
- self.add_argument(argument)?;
- }
- }
- Ok(())
- }
-
- pub fn add_argument(&mut self, argument: InputArgument) -> anyhow::Result<()> {
- let argument = std::rc::Rc::new(argument);
-
- if self.arguments.contains_key(argument.get_name()) {
- return Err(LogicException::new(format!(
- "An argument with name \"{}\" already exists.",
- argument.get_name(),
- ))
- .into());
- }
-
- if let Some(last_array_argument) = &self.last_array_argument {
- return Err(LogicException::new(format!(
- "Cannot add a required argument \"{}\" after an array argument \"{}\".",
- argument.get_name(),
- last_array_argument.get_name(),
- ))
- .into());
- }
-
- if argument.is_required()
- && let Some(last_optional_argument) = &self.last_optional_argument
- {
- return Err(LogicException::new(format!(
- "Cannot add a required argument \"{}\" after an optional one \"{}\".",
- argument.get_name(),
- last_optional_argument.get_name(),
- ))
- .into());
- }
-
- if argument.is_array() {
- self.last_array_argument = Some(std::rc::Rc::clone(&argument));
- }
-
- if argument.is_required() {
- self.required_count += 1;
- } else {
- self.last_optional_argument = Some(std::rc::Rc::clone(&argument));
- }
-
- self.arguments
- .insert(argument.get_name().to_string(), argument);
-
- Ok(())
- }
-
- /// Returns an InputArgument by name or by position.
- pub fn get_argument(&self, name: &PhpMixed) -> anyhow::Result<std::rc::Rc<InputArgument>> {
- if !self.has_argument(name) {
- return Err(InvalidArgumentException::new(format!(
- "The \"{}\" argument does not exist.",
- name.clone()
- ))
- .into());
- }
-
- match name {
- PhpMixed::Int(index) => {
- let arguments: Vec<std::rc::Rc<InputArgument>> =
- self.arguments.values().cloned().collect();
- Ok(std::rc::Rc::clone(&arguments[*index as usize]))
- }
- _ => {
- let key = shirabe_php_shim::php_to_string(name);
- Ok(std::rc::Rc::clone(&self.arguments[&key]))
- }
- }
- }
-
- /// Returns true if an InputArgument object exists by name or position.
- pub fn has_argument(&self, name: &PhpMixed) -> bool {
- match name {
- PhpMixed::Int(index) => {
- let arguments: Vec<std::rc::Rc<InputArgument>> =
- self.arguments.values().cloned().collect();
- *index >= 0 && (*index as usize) < arguments.len()
- }
- _ => {
- let key = shirabe_php_shim::php_to_string(name);
- self.arguments.contains_key(&key)
- }
- }
- }
-
- /// Gets the array of InputArgument objects.
- pub fn get_arguments(&self) -> &IndexMap<String, std::rc::Rc<InputArgument>> {
- &self.arguments
- }
-
- /// Returns the number of InputArguments.
- pub fn get_argument_count(&self) -> i64 {
- if self.last_array_argument.is_some() {
- i64::MAX
- } else {
- self.arguments.len() as i64
- }
- }
-
- /// Returns the number of required InputArguments.
- pub fn get_argument_required_count(&self) -> i64 {
- self.required_count
- }
-
- pub fn get_argument_defaults(&self) -> IndexMap<String, PhpMixed> {
- let mut values = IndexMap::new();
- for argument in self.arguments.values() {
- values.insert(
- argument.get_name().to_string(),
- argument.get_default().clone(),
- );
- }
-
- values
- }
-
- /// Sets the InputOption objects.
- pub fn set_options(&mut self, options: Vec<InputOption>) -> anyhow::Result<()> {
- self.options = IndexMap::new();
- self.shortcuts = IndexMap::new();
- self.negations = IndexMap::new();
- self.add_options(options)?;
- Ok(())
- }
-
- /// Adds an array of InputOption objects.
- pub fn add_options(&mut self, options: Vec<InputOption>) -> anyhow::Result<()> {
- for option in options {
- self.add_option(option)?;
- }
- Ok(())
- }
-
- pub fn add_option(&mut self, option: InputOption) -> anyhow::Result<()> {
- self.add_option_rc(std::rc::Rc::new(option))
- }
-
- /// Adds an option that is already shared behind `Rc`, mirroring PHP passing
- /// `InputOption` objects by reference.
- pub fn add_option_rc(&mut self, option: std::rc::Rc<InputOption>) -> anyhow::Result<()> {
- if let Some(existing) = self.options.get(option.get_name())
- && !option.equals(existing)
- {
- return Err(LogicException::new(format!(
- "An option named \"{}\" already exists.",
- option.get_name()
- ))
- .into());
- }
- if self.negations.contains_key(option.get_name()) {
- return Err(LogicException::new(format!(
- "An option named \"{}\" already exists.",
- option.get_name()
- ))
- .into());
- }
-
- if let Some(shortcut) = option.get_shortcut() {
- for shortcut in shirabe_php_shim::explode("|", shortcut) {
- if let Some(existing_name) = self.shortcuts.get(&shortcut)
- && !option.equals(&self.options[existing_name])
- {
- return Err(LogicException::new(format!(
- "An option with shortcut \"{}\" already exists.",
- shortcut.clone(),
- ))
- .into());
- }
- }
- }
-
- self.options
- .insert(option.get_name().to_string(), std::rc::Rc::clone(&option));
- if let Some(shortcut) = option.get_shortcut() {
- for shortcut in shirabe_php_shim::explode("|", shortcut) {
- self.shortcuts
- .insert(shortcut, option.get_name().to_string());
- }
- }
-
- if option.is_negatable() {
- let negated_name = format!("no-{}", option.get_name());
- if self.options.contains_key(&negated_name) {
- return Err(LogicException::new(format!(
- "An option named \"{}\" already exists.",
- negated_name
- ))
- .into());
- }
- self.negations
- .insert(negated_name, option.get_name().to_string());
- }
-
- Ok(())
- }
-
- /// Returns an InputOption by name.
- pub fn get_option(&self, name: &str) -> anyhow::Result<std::rc::Rc<InputOption>> {
- if !self.has_option(name) {
- return Err(InvalidArgumentException::new(format!(
- "The \"--{}\" option does not exist.",
- name
- ))
- .into());
- }
-
- Ok(std::rc::Rc::clone(&self.options[name]))
- }
-
- /// Returns true if an InputOption object exists by name.
- ///
- /// This method can't be used to check if the user included the option when
- /// executing the command (use getOption() instead).
- pub fn has_option(&self, name: &str) -> bool {
- self.options.contains_key(name)
- }
-
- /// Gets the array of InputOption objects.
- pub fn get_options(&self) -> &IndexMap<String, std::rc::Rc<InputOption>> {
- &self.options
- }
-
- /// Returns true if an InputOption object exists by shortcut.
- pub fn has_shortcut(&self, name: &str) -> bool {
- self.shortcuts.contains_key(name)
- }
-
- /// Returns true if an InputOption object exists by negated name.
- pub fn has_negation(&self, name: &str) -> bool {
- self.negations.contains_key(name)
- }
-
- /// Gets an InputOption by shortcut.
- pub fn get_option_for_shortcut(
- &self,
- shortcut: &str,
- ) -> anyhow::Result<std::rc::Rc<InputOption>> {
- self.get_option(&self.shortcut_to_name(shortcut)?)
- }
-
- pub fn get_option_defaults(&self) -> IndexMap<String, PhpMixed> {
- let mut values = IndexMap::new();
- for option in self.options.values() {
- values.insert(option.get_name().to_string(), option.get_default().clone());
- }
-
- values
- }
-
- /// Returns the InputOption name given a shortcut.
- pub fn shortcut_to_name(&self, shortcut: &str) -> anyhow::Result<String> {
- match self.shortcuts.get(shortcut) {
- None => Err(InvalidArgumentException::new(format!(
- "The \"-{}\" option does not exist.",
- shortcut
- ))
- .into()),
- Some(name) => Ok(name.clone()),
- }
- }
-
- /// Returns the InputOption name given a negation.
- pub fn negation_to_name(&self, negation: &str) -> anyhow::Result<String> {
- match self.negations.get(negation) {
- None => Err(InvalidArgumentException::new(format!(
- "The \"--{}\" option does not exist.",
- negation
- ))
- .into()),
- Some(name) => Ok(name.clone()),
- }
- }
-
- /// Gets the synopsis.
- pub fn get_synopsis(&self, short: bool) -> String {
- let mut elements: Vec<String> = vec![];
-
- if short && !self.get_options().is_empty() {
- elements.push("[options]".to_string());
- } else if !short {
- for option in self.get_options().values() {
- let mut value = String::new();
- if option.accept_value() {
- value = format!(
- " {}{}{}",
- if option.is_value_optional() {
- "[".to_string()
- } else {
- String::new()
- },
- shirabe_php_shim::strtoupper(option.get_name()),
- if option.is_value_optional() {
- "]".to_string()
- } else {
- String::new()
- },
- );
- }
-
- let shortcut = match option.get_shortcut() {
- Some(shortcut) => {
- format!("-{}|", shortcut)
- }
- None => String::new(),
- };
- let negation = if option.is_negatable() {
- format!("|--no-{}", option.get_name())
- } else {
- String::new()
- };
- elements.push(format!(
- "[{}--{}{}{}]",
- shortcut,
- option.get_name(),
- value,
- negation,
- ));
- }
- }
-
- if !elements.is_empty() && !self.get_arguments().is_empty() {
- elements.push("[--]".to_string());
- }
-
- let mut tail = String::new();
- for argument in self.get_arguments().values() {
- let mut element = format!("<{}>", argument.get_name());
- if argument.is_array() {
- element.push_str("...");
- }
-
- if !argument.is_required() {
- element = format!("[{}", element);
- tail.push(']');
- }
-
- elements.push(element);
- }
-
- format!("{}{}", shirabe_php_shim::implode(" ", &elements), tail)
- }
-}
diff --git a/crates/shirabe-external-packages/src/symfony/console/input/input_interface.rs b/crates/shirabe-external-packages/src/symfony/console/input/input_interface.rs
deleted file mode 100644
index e4beca91..00000000
--- a/crates/shirabe-external-packages/src/symfony/console/input/input_interface.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-//! ref: composer/vendor/symfony/console/Input/InputInterface.php
-
-use crate::symfony::console::input::input_definition::InputDefinition;
-use crate::symfony::console::input::streamable_input_interface::StreamableInputInterface;
-use shirabe_php_shim::PhpMixed;
-
-pub trait InputInterface: std::fmt::Debug + shirabe_php_shim::AsAny {
- /// Models PHP's `clone` operatior.
- fn dup(&self) -> std::rc::Rc<std::cell::RefCell<dyn InputInterface>>;
-
- fn get_first_argument(&self) -> Option<String>;
-
- fn has_parameter_option(&self, values: PhpMixed, only_params: bool) -> bool;
-
- fn get_parameter_option(
- &self,
- values: PhpMixed,
- default: PhpMixed,
- only_params: bool,
- ) -> PhpMixed;
-
- fn bind(&mut self, definition: &InputDefinition) -> anyhow::Result<()>;
-
- fn validate(&mut self) -> anyhow::Result<()>;
-
- fn get_arguments(&self) -> indexmap::IndexMap<String, PhpMixed>;
-
- fn get_argument(&self, name: &str) -> anyhow::Result<PhpMixed>;
-
- fn set_argument(&mut self, name: &str, value: PhpMixed) -> anyhow::Result<()>;
-
- fn has_argument(&self, name: &str) -> bool;
-
- fn get_options(&self) -> indexmap::IndexMap<String, PhpMixed>;
-
- fn get_option(&self, name: &str) -> anyhow::Result<PhpMixed>;
-
- fn set_option(&mut self, name: &str, value: PhpMixed) -> anyhow::Result<()>;
-
- fn has_option(&self, name: &str) -> bool;
-
- fn is_interactive(&self) -> bool;
-
- fn set_interactive(&mut self, interactive: bool);
-
- /// PHP's `(string) $input` (the `__toString` magic method every Symfony input implements);
- /// implementors forward to their `Display` impl.
- fn __to_string(&self) -> String;
-
- /// Models PHP's `$input instanceof StreamableInputInterface` check. Streamable inputs override
- /// this to return `Some(self)`; everything else falls back to `None`.
- fn as_streamable(&self) -> Option<&dyn StreamableInputInterface> {
- None
- }
-
- /// Mutable counterpart of `as_streamable`, needed to call `set_stream`/`set_interactive`.
- fn as_streamable_mut(&mut self) -> Option<&mut dyn StreamableInputInterface> {
- None
- }
-}
diff --git a/crates/shirabe-external-packages/src/symfony/console/input/input_option.rs b/crates/shirabe-external-packages/src/symfony/console/input/input_option.rs
deleted file mode 100644
index 79eff582..00000000
--- a/crates/shirabe-external-packages/src/symfony/console/input/input_option.rs
+++ /dev/null
@@ -1,193 +0,0 @@
-//! ref: composer/vendor/symfony/console/Input/InputOption.php
-
-use crate::symfony::console::exception::invalid_argument_exception::InvalidArgumentException;
-use crate::symfony::console::exception::logic_exception::LogicException;
-use shirabe_php_shim::{PhpMixed, php_regex};
-
-#[derive(Debug, Clone)]
-pub struct InputOption {
- name: String,
- shortcut: Option<String>,
- mode: i64,
- default: PhpMixed,
- description: String,
-}
-
-impl InputOption {
- pub const VALUE_NONE: i64 = 1;
- pub const VALUE_REQUIRED: i64 = 2;
- pub const VALUE_OPTIONAL: i64 = 4;
- pub const VALUE_IS_ARRAY: i64 = 8;
- pub const VALUE_NEGATABLE: i64 = 16;
-
- pub fn new(
- name: &str,
- shortcut: PhpMixed,
- mode: Option<i64>,
- description: String,
- default: PhpMixed,
- ) -> anyhow::Result<Self> {
- let name = if let Some(stripped) = name.strip_prefix("--") {
- stripped.to_string()
- } else {
- name.to_string()
- };
-
- if name.is_empty() {
- return Err(InvalidArgumentException::new(
- "An option name cannot be empty.".to_string(),
- )
- .into());
- }
-
- let shortcut = match shortcut {
- PhpMixed::String(ref s) if s.is_empty() => None,
- PhpMixed::List(ref v) if v.is_empty() => None,
- PhpMixed::Bool(false) => None,
- PhpMixed::Null => None,
- PhpMixed::List(ref arr) => {
- let parts: Vec<String> = arr
- .iter()
- .filter_map(|v| {
- if let PhpMixed::String(s) = v {
- Some(s.clone())
- } else {
- None
- }
- })
- .collect();
- let joined = shirabe_php_shim::implode("|", &parts);
- Self::normalize_shortcut(joined)?
- }
- PhpMixed::String(s) => Self::normalize_shortcut(s)?,
- _ => None,
- };
-
- let mode = match mode {
- None => Self::VALUE_NONE,
- Some(m) if !(1..(Self::VALUE_NEGATABLE << 1)).contains(&m) => {
- return Err(InvalidArgumentException::new(format!(
- "Option mode \"{}\" is not valid.",
- m
- ))
- .into());
- }
- Some(m) => m,
- };
-
- let mut option = InputOption {
- name,
- shortcut,
- mode,
- description,
- default: PhpMixed::Null,
- };
-
- if option.is_array() && !option.accept_value() {
- return Err(InvalidArgumentException::new("Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.".to_string())
- .into());
- }
- if option.is_negatable() && option.accept_value() {
- return Err(InvalidArgumentException::new("Impossible to have an option mode VALUE_NEGATABLE if the option also accepts a value.".to_string())
- .into());
- }
-
- option.set_default(default)?;
-
- Ok(option)
- }
-
- fn normalize_shortcut(s: String) -> anyhow::Result<Option<String>> {
- let stripped = shirabe_php_shim::ltrim(&s, Some("-"));
- let parts = shirabe_php_shim::preg_split(php_regex!(r"{(\|)-?}"), &stripped);
- let filtered: Vec<String> =
- shirabe_php_shim::array_filter(&parts, |s: &String| !s.is_empty());
- let result = shirabe_php_shim::implode("|", &filtered);
- if result.is_empty() {
- return Err(InvalidArgumentException::new(
- "An option shortcut cannot be empty.".to_string(),
- )
- .into());
- }
- Ok(Some(result))
- }
-
- pub fn get_shortcut(&self) -> Option<&str> {
- self.shortcut.as_deref()
- }
-
- pub fn get_name(&self) -> &str {
- &self.name
- }
-
- pub fn accept_value(&self) -> bool {
- self.is_value_required() || self.is_value_optional()
- }
-
- pub fn is_value_required(&self) -> bool {
- Self::VALUE_REQUIRED == (Self::VALUE_REQUIRED & self.mode)
- }
-
- pub fn is_value_optional(&self) -> bool {
- Self::VALUE_OPTIONAL == (Self::VALUE_OPTIONAL & self.mode)
- }
-
- pub fn is_array(&self) -> bool {
- Self::VALUE_IS_ARRAY == (Self::VALUE_IS_ARRAY & self.mode)
- }
-
- pub fn is_negatable(&self) -> bool {
- Self::VALUE_NEGATABLE == (Self::VALUE_NEGATABLE & self.mode)
- }
-
- pub fn set_default(&mut self, default: PhpMixed) -> anyhow::Result<()> {
- if Self::VALUE_NONE == (Self::VALUE_NONE & self.mode) && !matches!(default, PhpMixed::Null)
- {
- return Err(LogicException::new(
- "Cannot set a default value when using InputOption::VALUE_NONE mode.".to_string(),
- )
- .into());
- }
-
- let default = if self.is_array() {
- match default {
- PhpMixed::Null => PhpMixed::List(vec![]),
- // PHP `is_array()` accepts both list-style and associative arrays.
- PhpMixed::List(_) | PhpMixed::Array(_) => default,
- _ => {
- return Err(LogicException::new(
- "A default value for an array option must be an array.".to_string(),
- )
- .into());
- }
- }
- } else {
- default
- };
-
- self.default = if self.accept_value() || self.is_negatable() {
- default
- } else {
- PhpMixed::Bool(false)
- };
- Ok(())
- }
-
- pub fn get_default(&self) -> &PhpMixed {
- &self.default
- }
-
- pub fn get_description(&self) -> &str {
- &self.description
- }
-
- pub fn equals(&self, option: &InputOption) -> bool {
- option.get_name() == self.get_name()
- && option.get_shortcut() == self.get_shortcut()
- && option.get_default() == self.get_default()
- && option.is_negatable() == self.is_negatable()
- && option.is_array() == self.is_array()
- && option.is_value_required() == self.is_value_required()
- && option.is_value_optional() == self.is_value_optional()
- }
-}
diff --git a/crates/shirabe-external-packages/src/symfony/console/input/streamable_input_interface.rs b/crates/shirabe-external-packages/src/symfony/console/input/streamable_input_interface.rs
deleted file mode 100644
index d4bdbfd3..00000000
--- a/crates/shirabe-external-packages/src/symfony/console/input/streamable_input_interface.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-//! ref: composer/vendor/symfony/console/Input/StreamableInputInterface.php
-
-use crate::symfony::console::input::input_interface::InputInterface;
-use shirabe_php_shim::PhpResource;
-
-pub trait StreamableInputInterface: InputInterface {
- fn set_stream(&mut self, stream: PhpResource);
-
- fn get_stream(&self) -> Option<PhpResource>;
-}
diff --git a/crates/shirabe-external-packages/src/symfony/console/input/string_input.rs b/crates/shirabe-external-packages/src/symfony/console/input/string_input.rs
deleted file mode 100644
index 0ca8c975..00000000
--- a/crates/shirabe-external-packages/src/symfony/console/input/string_input.rs
+++ /dev/null
@@ -1,243 +0,0 @@
-//! ref: composer/vendor/symfony/console/Input/StringInput.php
-
-use crate::symfony::console::exception::invalid_argument_exception::InvalidArgumentException;
-use crate::symfony::console::input::argv_input::ArgvInput;
-use crate::symfony::console::input::input_definition::InputDefinition;
-use crate::symfony::console::input::input_interface::InputInterface;
-use crate::symfony::console::input::streamable_input_interface::StreamableInputInterface;
-use indexmap::IndexMap;
-use shirabe_php_shim::{CaptureKey, PhpMixed, php_regex};
-
-/// StringInput represents an input provided as a string.
-///
-/// Usage:
-///
-/// ```php
-/// $input = new StringInput('foo --bar="foobar"');
-/// ```
-#[derive(Debug, Clone)]
-pub struct StringInput {
- pub(crate) inner: ArgvInput,
-}
-
-impl StringInput {
- pub const REGEX_STRING: &'static str = r#"([^\s]+?)(?:\s|(?<!\\)"|(?<!\\)'|$)"#;
- pub const REGEX_UNQUOTED_STRING: &'static str = r#"([^\s\\]+?)"#;
- pub const REGEX_QUOTED_STRING: &'static str =
- r#"(?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)')"#;
-
- pub fn new(input: &str) -> anyhow::Result<Self> {
- // parent::__construct([])
- let inner = ArgvInput::new(Some(vec![]), None)?;
-
- let mut string_input = StringInput { inner };
-
- let tokens = string_input.tokenize(input)?;
- string_input.inner.set_tokens(tokens);
-
- Ok(string_input)
- }
-
- /// Tokenizes a string.
- fn tokenize(&self, input: &str) -> anyhow::Result<Vec<String>> {
- let bytes = input.as_bytes();
- let mut tokens: Vec<String> = vec![];
- let length = shirabe_php_shim::strlen(input);
- let mut cursor: i64 = 0;
- let mut token: Option<String> = None;
- while cursor < length {
- if bytes[cursor as usize] == b'\\' {
- cursor += 1;
- let next: String = match bytes.get(cursor as usize) {
- Some(b) => String::from_utf8_lossy(&[*b]).into_owned(),
- None => String::new(),
- };
- token = Some(format!("{}{}", token.unwrap_or_default(), next));
- cursor += 1;
- continue;
- }
-
- let mut m: IndexMap<CaptureKey, Option<String>> = IndexMap::new();
- if shirabe_php_shim::preg_match2(
- php_regex!(r"/\s+/A"),
- input,
- &mut m,
- 0,
- cursor as usize,
- ) {
- if token.is_some() {
- tokens.push(token.take().unwrap());
- }
- cursor +=
- shirabe_php_shim::strlen(m[&CaptureKey::ByIndex(0)].as_deref().unwrap_or(""));
- } else if shirabe_php_shim::preg_match2(
- format!(r#"/([^="'\s]+?)(=?)({}+)/A"#, Self::REGEX_QUOTED_STRING),
- input,
- &mut m,
- 0,
- cursor as usize,
- ) {
- let inner = shirabe_php_shim::substr(
- m[&CaptureKey::ByIndex(3)].as_deref().unwrap_or(""),
- 1,
- Some(-1),
- );
- let replaced =
- shirabe_php_shim::str_replace_arr(&["\"'", "'\"", "''", "\"\""], "", &inner);
- token = Some(format!(
- "{}{}{}{}",
- token.unwrap_or_default(),
- m[&CaptureKey::ByIndex(1)].as_deref().unwrap_or(""),
- m[&CaptureKey::ByIndex(2)].as_deref().unwrap_or(""),
- shirabe_php_shim::stripcslashes(&replaced)
- ));
- cursor +=
- shirabe_php_shim::strlen(m[&CaptureKey::ByIndex(0)].as_deref().unwrap_or(""));
- } else if shirabe_php_shim::preg_match2(
- format!(r"/{}/A", Self::REGEX_QUOTED_STRING),
- input,
- &mut m,
- 0,
- cursor as usize,
- ) {
- token = Some(format!(
- "{}{}",
- token.unwrap_or_default(),
- shirabe_php_shim::stripcslashes(&shirabe_php_shim::substr(
- m[&CaptureKey::ByIndex(0)].as_deref().unwrap_or(""),
- 1,
- Some(-1)
- ))
- ));
- cursor +=
- shirabe_php_shim::strlen(m[&CaptureKey::ByIndex(0)].as_deref().unwrap_or(""));
- } else if shirabe_php_shim::preg_match2(
- format!(r"/{}/A", Self::REGEX_UNQUOTED_STRING),
- input,
- &mut m,
- 0,
- cursor as usize,
- ) {
- token = Some(format!(
- "{}{}",
- token.unwrap_or_default(),
- m[&CaptureKey::ByIndex(1)].as_deref().unwrap_or("")
- ));
- cursor +=
- shirabe_php_shim::strlen(m[&CaptureKey::ByIndex(0)].as_deref().unwrap_or(""));
- } else {
- // should never happen
- return Err(InvalidArgumentException::new(format!(
- "Unable to parse input near \"... {} ...\".",
- shirabe_php_shim::substr(input, cursor, Some(10)),
- ))
- .into());
- }
- }
-
- if let Some(token) = token {
- tokens.push(token);
- }
-
- Ok(tokens)
- }
-}
-
-impl std::fmt::Display for StringInput {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- self.inner.fmt(f)
- }
-}
-
-impl InputInterface for StringInput {
- fn dup(&self) -> std::rc::Rc<std::cell::RefCell<dyn InputInterface>> {
- std::rc::Rc::new(std::cell::RefCell::new(self.clone()))
- }
-
- fn get_first_argument(&self) -> Option<String> {
- self.inner.get_first_argument()
- }
-
- fn has_parameter_option(&self, values: PhpMixed, only_params: bool) -> bool {
- InputInterface::has_parameter_option(&self.inner, values, only_params)
- }
-
- fn get_parameter_option(
- &self,
- values: PhpMixed,
- default: PhpMixed,
- only_params: bool,
- ) -> PhpMixed {
- InputInterface::get_parameter_option(&self.inner, values, default, only_params)
- }
-
- fn bind(&mut self, definition: &InputDefinition) -> anyhow::Result<()> {
- InputInterface::bind(&mut self.inner, definition)
- }
-
- fn validate(&mut self) -> anyhow::Result<()> {
- self.inner.validate()
- }
-
- fn get_arguments(&self) -> IndexMap<String, PhpMixed> {
- InputInterface::get_arguments(&self.inner)
- }
-
- fn get_argument(&self, name: &str) -> anyhow::Result<PhpMixed> {
- self.inner.get_argument(name)
- }
-
- fn set_argument(&mut self, name: &str, value: PhpMixed) -> anyhow::Result<()> {
- self.inner.set_argument(name, value)
- }
-
- fn has_argument(&self, name: &str) -> bool {
- self.inner.has_argument(name)
- }
-
- fn get_options(&self) -> IndexMap<String, PhpMixed> {
- InputInterface::get_options(&self.inner)
- }
-
- fn get_option(&self, name: &str) -> anyhow::Result<PhpMixed> {
- self.inner.get_option(name)
- }
-
- fn set_option(&mut self, name: &str, value: PhpMixed) -> anyhow::Result<()> {
- self.inner.set_option(name, value)
- }
-
- fn has_option(&self, name: &str) -> bool {
- self.inner.has_option(name)
- }
-
- fn is_interactive(&self) -> bool {
- self.inner.is_interactive()
- }
-
- fn set_interactive(&mut self, interactive: bool) {
- self.inner.set_interactive(interactive)
- }
-
- fn __to_string(&self) -> String {
- self.to_string()
- }
-
- fn as_streamable(&self) -> Option<&dyn StreamableInputInterface> {
- Some(self)
- }
-
- fn as_streamable_mut(&mut self) -> Option<&mut dyn StreamableInputInterface> {
- Some(self)
- }
-}
-
-impl StreamableInputInterface for StringInput {
- fn set_stream(&mut self, stream: shirabe_php_shim::PhpResource) {
- self.inner.set_stream(stream)
- }
-
- fn get_stream(&self) -> Option<shirabe_php_shim::PhpResource> {
- self.inner.get_stream()
- }
-}