diff options
Diffstat (limited to 'crates/shirabe-external-packages/src/symfony/console/helper/descriptor_helper.rs')
| -rw-r--r-- | crates/shirabe-external-packages/src/symfony/console/helper/descriptor_helper.rs | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/crates/shirabe-external-packages/src/symfony/console/helper/descriptor_helper.rs b/crates/shirabe-external-packages/src/symfony/console/helper/descriptor_helper.rs new file mode 100644 index 0000000..64c166c --- /dev/null +++ b/crates/shirabe-external-packages/src/symfony/console/helper/descriptor_helper.rs @@ -0,0 +1,135 @@ +use crate::symfony::console::descriptor::descriptor_interface::DescriptorInterface; +use crate::symfony::console::descriptor::json_descriptor::JsonDescriptor; +use crate::symfony::console::descriptor::markdown_descriptor::MarkdownDescriptor; +use crate::symfony::console::descriptor::text_descriptor::TextDescriptor; +use crate::symfony::console::descriptor::xml_descriptor::XmlDescriptor; +use crate::symfony::console::exception::invalid_argument_exception::InvalidArgumentException; +use crate::symfony::console::helper::helper::Helper; +use crate::symfony::console::helper::helper_interface::HelperInterface; +use crate::symfony::console::helper::helper_set::HelperSet; +use crate::symfony::console::output::output_interface::OutputInterface; +use indexmap::IndexMap; +use std::cell::RefCell; +use std::rc::Rc; + +/// This class adds helper method to describe objects in various formats. +#[derive(Default)] +pub struct DescriptorHelper { + inner: Helper, + /// @var DescriptorInterface[] + descriptors: IndexMap<String, Box<dyn DescriptorInterface>>, +} + +// `DescriptorInterface` does not require `Debug`, so the derive cannot see +// through the trait object; provide a minimal manual impl. +impl std::fmt::Debug for DescriptorHelper { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("DescriptorHelper") + .field("inner", &self.inner) + .field("descriptors", &self.descriptors.keys().collect::<Vec<_>>()) + .finish() + } +} + +impl DescriptorHelper { + pub fn new() -> Self { + let mut this = Self { + inner: Helper::default(), + descriptors: IndexMap::new(), + }; + // The XML/JSON/Markdown descriptors do not yet expose a constructor + // (no `Default`/`new`); their construction is deferred until those + // descriptor types provide one. + let xml: Box<dyn DescriptorInterface> = todo!(); + let json: Box<dyn DescriptorInterface> = todo!(); + let md: Box<dyn DescriptorInterface> = todo!(); + this.register("txt", Box::new(TextDescriptor::default())) + .register("xml", xml) + .register("json", json) + .register("md", md); + this + } + + /// Describes an object if supported. + /// + /// Available options are: + /// * format: string, the output format name + /// * raw_text: boolean, sets output type as raw + /// + /// @throws InvalidArgumentException when the given format is not supported + pub fn describe2( + &self, + output: &dyn OutputInterface, + object: Option<shirabe_php_shim::PhpMixed>, + options: IndexMap<String, shirabe_php_shim::PhpMixed>, + ) -> Result<(), InvalidArgumentException> { + let mut merged: IndexMap<String, shirabe_php_shim::PhpMixed> = IndexMap::new(); + merged.insert( + "raw_text".to_string(), + shirabe_php_shim::PhpMixed::Bool(false), + ); + merged.insert( + "format".to_string(), + shirabe_php_shim::PhpMixed::String("txt".to_string()), + ); + for (key, value) in options { + merged.insert(key, value); + } + let options = merged; + + let format = match &options["format"] { + shirabe_php_shim::PhpMixed::String(format) => format.clone(), + _ => String::new(), + }; + + if !self.descriptors.contains_key(&format) { + return Err(InvalidArgumentException( + shirabe_php_shim::InvalidArgumentException { + message: shirabe_php_shim::sprintf( + "Unsupported format \"%s\".", + &[shirabe_php_shim::PhpMixed::String(format.clone())], + ), + code: 0, + }, + )); + } + + let _ = (&self.descriptors[&format], output, object, options); + // `DescriptorInterface::describe` takes an owned + // `Rc<RefCell<dyn OutputInterface>>` and `&mut self`, while the helper + // only holds a shared `&dyn OutputInterface` and `&self`. Reconciling + // this ownership/mutability gap is a Phase C decision. + todo!("dispatch to DescriptorInterface::describe (Phase C ownership)"); + } + + /// Registers a descriptor. + /// + /// @return $this + pub fn register( + &mut self, + format: &str, + descriptor: Box<dyn DescriptorInterface>, + ) -> &mut Self { + self.descriptors.insert(format.to_string(), descriptor); + + self + } + + pub fn get_formats(&self) -> Vec<String> { + self.descriptors.keys().cloned().collect() + } +} + +impl HelperInterface for DescriptorHelper { + fn set_helper_set(&mut self, helper_set: Option<Rc<RefCell<HelperSet>>>) { + self.inner.set_helper_set(helper_set); + } + + fn get_helper_set(&self) -> Option<Rc<RefCell<HelperSet>>> { + self.inner.get_helper_set() + } + + fn get_name(&self) -> String { + "descriptor".to_string() + } +} |
