diff options
Diffstat (limited to 'crates/shirabe/src/composer.rs')
| -rw-r--r-- | crates/shirabe/src/composer.rs | 723 |
1 files changed, 354 insertions, 369 deletions
diff --git a/crates/shirabe/src/composer.rs b/crates/shirabe/src/composer.rs index fe700cf..6a2337a 100644 --- a/crates/shirabe/src/composer.rs +++ b/crates/shirabe/src/composer.rs @@ -31,255 +31,315 @@ pub fn get_version() -> String { VERSION.to_string() } +/// Interface for \Composer\PartialComposer. Implemented by every composer handle, since both a +/// partial and a full composer expose these common members. +pub trait PartialComposer { + fn set_package(&self, package: RootPackageInterfaceHandle); + fn get_package(&self) -> RootPackageInterfaceHandle; + fn set_config(&self, config: std::rc::Rc<std::cell::RefCell<Config>>); + fn get_config(&self) -> std::rc::Rc<std::cell::RefCell<Config>>; + fn set_loop(&self, r#loop: std::rc::Rc<std::cell::RefCell<Loop>>); + fn get_loop(&self) -> std::rc::Rc<std::cell::RefCell<Loop>>; + fn set_repository_manager(&self, manager: std::rc::Rc<std::cell::RefCell<RepositoryManager>>); + fn get_repository_manager(&self) -> std::rc::Rc<std::cell::RefCell<RepositoryManager>>; + fn set_installation_manager( + &self, + manager: std::rc::Rc<std::cell::RefCell<InstallationManager>>, + ); + fn get_installation_manager(&self) -> std::rc::Rc<std::cell::RefCell<InstallationManager>>; + fn set_event_dispatcher( + &self, + event_dispatcher: std::rc::Rc<std::cell::RefCell<EventDispatcher>>, + ); + fn get_event_dispatcher(&self) -> std::rc::Rc<std::cell::RefCell<EventDispatcher>>; + fn is_global(&self) -> bool; + fn set_global(&self); +} + +/// Interface for \Composer\Composer (`extends PartialComposer`). Implemented only by fully-loaded +/// composer handles, which additionally expose the full-only members below. +pub trait Composer: PartialComposer { + fn set_locker(&self, locker: std::rc::Rc<std::cell::RefCell<Locker>>); + fn get_locker(&self) -> std::rc::Rc<std::cell::RefCell<Locker>>; + fn set_download_manager(&self, manager: std::rc::Rc<std::cell::RefCell<DownloadManager>>); + fn get_download_manager(&self) -> std::rc::Rc<std::cell::RefCell<DownloadManager>>; + // TODO(plugin): set_plugin_manager is part of the plugin API + fn set_plugin_manager(&self, manager: std::rc::Rc<std::cell::RefCell<PluginManager>>); + // TODO(plugin): get_plugin_manager is part of the plugin API + fn get_plugin_manager(&self) -> std::rc::Rc<std::cell::RefCell<PluginManager>>; + fn set_autoload_generator( + &self, + autoload_generator: std::rc::Rc<std::cell::RefCell<AutoloadGenerator>>, + ); + fn get_autoload_generator(&self) -> std::rc::Rc<std::cell::RefCell<AutoloadGenerator>>; + fn set_archive_manager(&self, manager: std::rc::Rc<std::cell::RefCell<ArchiveManager>>); + fn get_archive_manager(&self) -> std::rc::Rc<std::cell::RefCell<ArchiveManager>>; +} + /// Internal data type corresponding to \Composer\PartialComposer. #[derive(Debug, Default)] -pub struct PartialComposer { - global: bool, - package: Option<RootPackageInterfaceHandle>, - r#loop: Option<std::rc::Rc<std::cell::RefCell<Loop>>>, - repository_manager: Option<std::rc::Rc<std::cell::RefCell<RepositoryManager>>>, - installation_manager: Option<std::rc::Rc<std::cell::RefCell<InstallationManager>>>, - config: Option<std::rc::Rc<std::cell::RefCell<Config>>>, - event_dispatcher: Option<std::rc::Rc<std::cell::RefCell<EventDispatcher>>>, +pub(crate) struct InnerPartialComposer { + pub(crate) global: bool, + pub(crate) package: Option<RootPackageInterfaceHandle>, + pub(crate) r#loop: Option<std::rc::Rc<std::cell::RefCell<Loop>>>, + pub(crate) repository_manager: Option<std::rc::Rc<std::cell::RefCell<RepositoryManager>>>, + pub(crate) installation_manager: Option<std::rc::Rc<std::cell::RefCell<InstallationManager>>>, + pub(crate) config: Option<std::rc::Rc<std::cell::RefCell<Config>>>, + pub(crate) event_dispatcher: Option<std::rc::Rc<std::cell::RefCell<EventDispatcher>>>, } -impl PartialComposer { - pub fn set_package(&mut self, package: RootPackageInterfaceHandle) { - self.package = Some(package); - } +/// Internal data type corresponding to \Composer\Composer. +#[derive(Debug, Default)] +pub(crate) struct InnerFullComposer { + pub(crate) partial: InnerPartialComposer, + pub(crate) locker: Option<std::rc::Rc<std::cell::RefCell<Locker>>>, + pub(crate) download_manager: Option<std::rc::Rc<std::cell::RefCell<DownloadManager>>>, + // TODO(plugin): plugin_manager is part of the plugin API + pub(crate) plugin_manager: Option<std::rc::Rc<std::cell::RefCell<PluginManager>>>, + pub(crate) autoload_generator: Option<std::rc::Rc<std::cell::RefCell<AutoloadGenerator>>>, + pub(crate) archive_manager: Option<std::rc::Rc<std::cell::RefCell<ArchiveManager>>>, +} - pub fn get_package(&self) -> &RootPackageInterfaceHandle { - self.package.as_ref().unwrap() - } +/// Shared reference to a fully-loaded \Composer\Composer. +/// Use this for parameters or fields typed as \Composer\Composer in PHP. +#[derive(Debug, Clone)] +pub struct FullComposerHandle(std::rc::Rc<std::cell::RefCell<InnerFullComposer>>); - pub fn set_config(&mut self, config: std::rc::Rc<std::cell::RefCell<Config>>) { - self.config = Some(config); +impl FullComposerHandle { + pub(crate) fn from_rc(rc: std::rc::Rc<std::cell::RefCell<InnerFullComposer>>) -> Self { + Self(rc) } - pub fn get_config(&self) -> std::rc::Rc<std::cell::RefCell<Config>> { - self.config.as_ref().unwrap().clone() + pub(crate) fn as_rc(&self) -> &std::rc::Rc<std::cell::RefCell<InnerFullComposer>> { + &self.0 } - pub fn set_loop(&mut self, r#loop: std::rc::Rc<std::cell::RefCell<Loop>>) { - self.r#loop = Some(r#loop); + pub fn downgrade(&self) -> FullComposerWeakHandle { + FullComposerWeakHandle(std::rc::Rc::downgrade(&self.0)) } +} - pub fn get_loop(&self) -> std::rc::Rc<std::cell::RefCell<Loop>> { - self.r#loop.as_ref().unwrap().clone() +impl PartialComposer for FullComposerHandle { + fn set_package(&self, package: RootPackageInterfaceHandle) { + self.0.borrow_mut().partial.package = Some(package); } - - pub fn set_repository_manager( - &mut self, - manager: std::rc::Rc<std::cell::RefCell<RepositoryManager>>, - ) { - self.repository_manager = Some(manager); + fn get_package(&self) -> RootPackageInterfaceHandle { + self.0.borrow().partial.package.as_ref().unwrap().clone() } - - pub fn get_repository_manager(&self) -> std::rc::Rc<std::cell::RefCell<RepositoryManager>> { - self.repository_manager.as_ref().unwrap().clone() + fn set_config(&self, config: std::rc::Rc<std::cell::RefCell<Config>>) { + self.0.borrow_mut().partial.config = Some(config); } - - pub fn set_installation_manager( - &mut self, + fn get_config(&self) -> std::rc::Rc<std::cell::RefCell<Config>> { + self.0.borrow().partial.config.as_ref().unwrap().clone() + } + fn set_loop(&self, r#loop: std::rc::Rc<std::cell::RefCell<Loop>>) { + self.0.borrow_mut().partial.r#loop = Some(r#loop); + } + fn get_loop(&self) -> std::rc::Rc<std::cell::RefCell<Loop>> { + self.0.borrow().partial.r#loop.as_ref().unwrap().clone() + } + fn set_repository_manager(&self, manager: std::rc::Rc<std::cell::RefCell<RepositoryManager>>) { + self.0.borrow_mut().partial.repository_manager = Some(manager); + } + fn get_repository_manager(&self) -> std::rc::Rc<std::cell::RefCell<RepositoryManager>> { + self.0 + .borrow() + .partial + .repository_manager + .as_ref() + .unwrap() + .clone() + } + fn set_installation_manager( + &self, manager: std::rc::Rc<std::cell::RefCell<InstallationManager>>, ) { - self.installation_manager = Some(manager); + self.0.borrow_mut().partial.installation_manager = Some(manager); } - - pub fn get_installation_manager(&self) -> std::rc::Rc<std::cell::RefCell<InstallationManager>> { - self.installation_manager.as_ref().unwrap().clone() + fn get_installation_manager(&self) -> std::rc::Rc<std::cell::RefCell<InstallationManager>> { + self.0 + .borrow() + .partial + .installation_manager + .as_ref() + .unwrap() + .clone() } - - pub fn set_event_dispatcher( - &mut self, + fn set_event_dispatcher( + &self, event_dispatcher: std::rc::Rc<std::cell::RefCell<EventDispatcher>>, ) { - self.event_dispatcher = Some(event_dispatcher); + self.0.borrow_mut().partial.event_dispatcher = Some(event_dispatcher); } - - pub fn get_event_dispatcher(&self) -> std::rc::Rc<std::cell::RefCell<EventDispatcher>> { - self.event_dispatcher.as_ref().unwrap().clone() + fn get_event_dispatcher(&self) -> std::rc::Rc<std::cell::RefCell<EventDispatcher>> { + self.0 + .borrow() + .partial + .event_dispatcher + .as_ref() + .unwrap() + .clone() } - - pub fn is_global(&self) -> bool { - self.global + fn is_global(&self) -> bool { + self.0.borrow().partial.global } - - pub fn set_global(&mut self) { - self.global = true; + fn set_global(&self) { + self.0.borrow_mut().partial.global = true; } } -/// Internal data type corresponding to \Composer\Composer. -#[derive(Debug)] -pub struct Composer { - partial: PartialComposer, - locker: Option<std::rc::Rc<std::cell::RefCell<Locker>>>, - download_manager: Option<std::rc::Rc<std::cell::RefCell<DownloadManager>>>, - // TODO(plugin): plugin_manager is part of the plugin API - plugin_manager: Option<std::rc::Rc<std::cell::RefCell<PluginManager>>>, - autoload_generator: Option<std::rc::Rc<std::cell::RefCell<AutoloadGenerator>>>, - archive_manager: Option<std::rc::Rc<std::cell::RefCell<ArchiveManager>>>, -} - -impl Composer { - pub fn new() -> Self { - Self { - partial: PartialComposer::default(), - locker: None, - download_manager: None, - plugin_manager: None, - autoload_generator: None, - archive_manager: None, - } +impl Composer for FullComposerHandle { + fn set_locker(&self, locker: std::rc::Rc<std::cell::RefCell<Locker>>) { + self.0.borrow_mut().locker = Some(locker); } - - pub fn set_locker(&mut self, locker: std::rc::Rc<std::cell::RefCell<Locker>>) { - self.locker = Some(locker); + fn get_locker(&self) -> std::rc::Rc<std::cell::RefCell<Locker>> { + self.0.borrow().locker.as_ref().unwrap().clone() } - - pub fn get_locker(&self) -> std::rc::Rc<std::cell::RefCell<Locker>> { - self.locker.as_ref().unwrap().clone() + fn set_download_manager(&self, manager: std::rc::Rc<std::cell::RefCell<DownloadManager>>) { + self.0.borrow_mut().download_manager = Some(manager); } - - pub fn set_download_manager( - &mut self, - manager: std::rc::Rc<std::cell::RefCell<DownloadManager>>, - ) { - self.download_manager = Some(manager); + fn get_download_manager(&self) -> std::rc::Rc<std::cell::RefCell<DownloadManager>> { + self.0.borrow().download_manager.as_ref().unwrap().clone() } - - pub fn get_download_manager(&self) -> std::rc::Rc<std::cell::RefCell<DownloadManager>> { - self.download_manager.as_ref().unwrap().clone() + fn set_plugin_manager(&self, manager: std::rc::Rc<std::cell::RefCell<PluginManager>>) { + self.0.borrow_mut().plugin_manager = Some(manager); } - - pub fn set_archive_manager( - &mut self, - manager: std::rc::Rc<std::cell::RefCell<ArchiveManager>>, + fn get_plugin_manager(&self) -> std::rc::Rc<std::cell::RefCell<PluginManager>> { + self.0.borrow().plugin_manager.as_ref().unwrap().clone() + } + fn set_autoload_generator( + &self, + autoload_generator: std::rc::Rc<std::cell::RefCell<AutoloadGenerator>>, ) { - self.archive_manager = Some(manager); + self.0.borrow_mut().autoload_generator = Some(autoload_generator); } - - pub fn get_archive_manager(&self) -> std::rc::Rc<std::cell::RefCell<ArchiveManager>> { - self.archive_manager.as_ref().unwrap().clone() + fn get_autoload_generator(&self) -> std::rc::Rc<std::cell::RefCell<AutoloadGenerator>> { + self.0.borrow().autoload_generator.as_ref().unwrap().clone() } - - // TODO(plugin): set_plugin_manager is part of the plugin API - pub fn set_plugin_manager(&mut self, manager: std::rc::Rc<std::cell::RefCell<PluginManager>>) { - self.plugin_manager = Some(manager); + fn set_archive_manager(&self, manager: std::rc::Rc<std::cell::RefCell<ArchiveManager>>) { + self.0.borrow_mut().archive_manager = Some(manager); } - - // TODO(plugin): get_plugin_manager is part of the plugin API - pub fn get_plugin_manager(&self) -> std::rc::Rc<std::cell::RefCell<PluginManager>> { - self.plugin_manager.as_ref().unwrap().clone() + fn get_archive_manager(&self) -> std::rc::Rc<std::cell::RefCell<ArchiveManager>> { + self.0.borrow().archive_manager.as_ref().unwrap().clone() } +} - pub fn set_autoload_generator( - &mut self, - autoload_generator: std::rc::Rc<std::cell::RefCell<AutoloadGenerator>>, - ) { - self.autoload_generator = Some(autoload_generator); - } +/// Shared weak reference to a fully-loaded \Composer\Composer. +#[derive(Debug, Clone)] +pub struct FullComposerWeakHandle(std::rc::Weak<std::cell::RefCell<InnerFullComposer>>); - pub fn get_autoload_generator(&self) -> std::rc::Rc<std::cell::RefCell<AutoloadGenerator>> { - self.autoload_generator.as_ref().unwrap().clone() +impl FullComposerWeakHandle { + pub(crate) fn from_weak(weak: std::rc::Weak<std::cell::RefCell<InnerFullComposer>>) -> Self { + Self(weak) } - pub fn as_partial(&self) -> &PartialComposer { - &self.partial + pub fn upgrade(&self) -> Option<FullComposerHandle> { + self.0.upgrade().map(FullComposerHandle) } - pub fn as_partial_mut(&mut self) -> &mut PartialComposer { - &mut self.partial + fn upgraded(&self) -> FullComposerHandle { + self.upgrade() + .expect("Composer has been dropped before its weak reference") } +} - pub fn set_package(&mut self, package: RootPackageInterfaceHandle) { - self.partial.set_package(package); +impl PartialComposer for FullComposerWeakHandle { + fn set_package(&self, package: RootPackageInterfaceHandle) { + self.upgraded().set_package(package); } - - pub fn get_package(&self) -> &RootPackageInterfaceHandle { - self.partial.get_package() + fn get_package(&self) -> RootPackageInterfaceHandle { + self.upgraded().get_package() } - - pub fn set_config(&mut self, config: std::rc::Rc<std::cell::RefCell<crate::config::Config>>) { - self.partial.set_config(config); + fn set_config(&self, config: std::rc::Rc<std::cell::RefCell<Config>>) { + self.upgraded().set_config(config); } - - pub fn get_config(&self) -> std::rc::Rc<std::cell::RefCell<crate::config::Config>> { - self.partial.get_config() + fn get_config(&self) -> std::rc::Rc<std::cell::RefCell<Config>> { + self.upgraded().get_config() } - - pub fn set_loop(&mut self, r#loop: std::rc::Rc<std::cell::RefCell<crate::util::r#loop::Loop>>) { - self.partial.set_loop(r#loop); + fn set_loop(&self, r#loop: std::rc::Rc<std::cell::RefCell<Loop>>) { + self.upgraded().set_loop(r#loop); } - - pub fn get_loop(&self) -> std::rc::Rc<std::cell::RefCell<crate::util::r#loop::Loop>> { - self.partial.get_loop() + fn get_loop(&self) -> std::rc::Rc<std::cell::RefCell<Loop>> { + self.upgraded().get_loop() } - - pub fn set_repository_manager( - &mut self, - manager: std::rc::Rc<std::cell::RefCell<crate::repository::RepositoryManager>>, - ) { - self.partial.set_repository_manager(manager); + fn set_repository_manager(&self, manager: std::rc::Rc<std::cell::RefCell<RepositoryManager>>) { + self.upgraded().set_repository_manager(manager); } - - pub fn get_repository_manager( - &self, - ) -> std::rc::Rc<std::cell::RefCell<crate::repository::RepositoryManager>> { - self.partial.get_repository_manager() + fn get_repository_manager(&self) -> std::rc::Rc<std::cell::RefCell<RepositoryManager>> { + self.upgraded().get_repository_manager() } - - pub fn set_installation_manager( - &mut self, - manager: std::rc::Rc<std::cell::RefCell<crate::installer::InstallationManager>>, + fn set_installation_manager( + &self, + manager: std::rc::Rc<std::cell::RefCell<InstallationManager>>, ) { - self.partial.set_installation_manager(manager); + self.upgraded().set_installation_manager(manager); } - - pub fn get_installation_manager( - &self, - ) -> std::rc::Rc<std::cell::RefCell<crate::installer::InstallationManager>> { - self.partial.get_installation_manager() + fn get_installation_manager(&self) -> std::rc::Rc<std::cell::RefCell<InstallationManager>> { + self.upgraded().get_installation_manager() } - - pub fn set_event_dispatcher( - &mut self, - dispatcher: std::rc::Rc<std::cell::RefCell<crate::event_dispatcher::EventDispatcher>>, + fn set_event_dispatcher( + &self, + event_dispatcher: std::rc::Rc<std::cell::RefCell<EventDispatcher>>, ) { - self.partial.set_event_dispatcher(dispatcher); + self.upgraded().set_event_dispatcher(event_dispatcher); + } + fn get_event_dispatcher(&self) -> std::rc::Rc<std::cell::RefCell<EventDispatcher>> { + self.upgraded().get_event_dispatcher() + } + fn is_global(&self) -> bool { + self.upgraded().is_global() + } + fn set_global(&self) { + self.upgraded().set_global(); } +} - pub fn get_event_dispatcher( +impl Composer for FullComposerWeakHandle { + fn set_locker(&self, locker: std::rc::Rc<std::cell::RefCell<Locker>>) { + self.upgraded().set_locker(locker); + } + fn get_locker(&self) -> std::rc::Rc<std::cell::RefCell<Locker>> { + self.upgraded().get_locker() + } + fn set_download_manager(&self, manager: std::rc::Rc<std::cell::RefCell<DownloadManager>>) { + self.upgraded().set_download_manager(manager); + } + fn get_download_manager(&self) -> std::rc::Rc<std::cell::RefCell<DownloadManager>> { + self.upgraded().get_download_manager() + } + fn set_plugin_manager(&self, manager: std::rc::Rc<std::cell::RefCell<PluginManager>>) { + self.upgraded().set_plugin_manager(manager); + } + fn get_plugin_manager(&self) -> std::rc::Rc<std::cell::RefCell<PluginManager>> { + self.upgraded().get_plugin_manager() + } + fn set_autoload_generator( &self, - ) -> std::rc::Rc<std::cell::RefCell<crate::event_dispatcher::EventDispatcher>> { - self.partial.get_event_dispatcher() + autoload_generator: std::rc::Rc<std::cell::RefCell<AutoloadGenerator>>, + ) { + self.upgraded().set_autoload_generator(autoload_generator); } - - pub fn is_global(&self) -> bool { - self.partial.is_global() + fn get_autoload_generator(&self) -> std::rc::Rc<std::cell::RefCell<AutoloadGenerator>> { + self.upgraded().get_autoload_generator() } - - pub fn set_global(&mut self) { - self.partial.set_global(); + fn set_archive_manager(&self, manager: std::rc::Rc<std::cell::RefCell<ArchiveManager>>) { + self.upgraded().set_archive_manager(manager); + } + fn get_archive_manager(&self) -> std::rc::Rc<std::cell::RefCell<ArchiveManager>> { + self.upgraded().get_archive_manager() } } -#[derive(Debug)] -pub enum PartialOrFullComposer { - Full(Composer), - Partial(PartialComposer), +/// Shared reference to a \Composer\PartialComposer that may at runtime be either a partial composer +/// or a full \Composer\Composer. Use this for parameters or fields typed as \Composer\PartialComposer +/// in PHP; downcast with [`AnyComposerHandle::as_full`] (`$composer instanceof Composer`). +#[derive(Debug, Clone)] +pub enum AnyComposerHandle { + Partial(std::rc::Rc<std::cell::RefCell<InnerPartialComposer>>), + Full(FullComposerHandle), } -impl PartialOrFullComposer { - pub fn new_full() -> Self { - Self::Full(Composer::new()) - } - - pub fn new_partial() -> Self { - Self::Partial(PartialComposer::default()) - } - +impl AnyComposerHandle { pub fn is_full(&self) -> bool { matches!(self, Self::Full(_)) } @@ -288,274 +348,199 @@ impl PartialOrFullComposer { matches!(self, Self::Partial(_)) } - pub fn as_full(&self) -> Option<&Composer> { + /// Downcast to a full Composer handle. PHP `$composer instanceof Composer`. + pub fn as_full(&self) -> Option<FullComposerHandle> { match self { - Self::Full(full) => Some(full), + Self::Full(full) => Some(full.clone()), Self::Partial(_) => None, } } - pub fn as_full_mut(&mut self) -> Option<&mut Composer> { + pub fn downgrade(&self) -> AnyComposerWeakHandle { match self { - Self::Full(full) => Some(full), - Self::Partial(_) => None, + Self::Partial(rc) => AnyComposerWeakHandle::Partial(std::rc::Rc::downgrade(rc)), + Self::Full(full) => AnyComposerWeakHandle::Full(full.downgrade()), } } +} - pub fn as_partial(&self) -> &PartialComposer { - match self { - Self::Full(full) => full.as_partial(), - Self::Partial(partial) => partial, - } +impl From<FullComposerHandle> for AnyComposerHandle { + fn from(h: FullComposerHandle) -> Self { + Self::Full(h) } +} - pub fn as_partial_mut(&mut self) -> &mut PartialComposer { +impl PartialComposer for AnyComposerHandle { + fn set_package(&self, package: RootPackageInterfaceHandle) { match self { - Self::Full(full) => full.as_partial_mut(), - Self::Partial(partial) => partial, + Self::Partial(rc) => rc.borrow_mut().package = Some(package), + Self::Full(f) => f.set_package(package), } } - - pub fn set_package(&mut self, package: RootPackageInterfaceHandle) { + fn get_package(&self) -> RootPackageInterfaceHandle { match self { - Self::Full(full) => full.set_package(package), - Self::Partial(partial) => partial.set_package(package), + Self::Partial(rc) => rc.borrow().package.as_ref().unwrap().clone(), + Self::Full(f) => f.get_package(), } } - - pub fn get_package(&self) -> &RootPackageInterfaceHandle { + fn set_config(&self, config: std::rc::Rc<std::cell::RefCell<Config>>) { match self { - Self::Full(full) => full.get_package(), - Self::Partial(partial) => partial.get_package(), + Self::Partial(rc) => rc.borrow_mut().config = Some(config), + Self::Full(f) => f.set_config(config), } } - - pub fn set_config(&mut self, config: std::rc::Rc<std::cell::RefCell<crate::config::Config>>) { + fn get_config(&self) -> std::rc::Rc<std::cell::RefCell<Config>> { match self { - Self::Full(full) => full.set_config(config), - Self::Partial(partial) => partial.set_config(config), + Self::Partial(rc) => rc.borrow().config.as_ref().unwrap().clone(), + Self::Full(f) => f.get_config(), } } - - pub fn get_config(&self) -> std::rc::Rc<std::cell::RefCell<crate::config::Config>> { + fn set_loop(&self, r#loop: std::rc::Rc<std::cell::RefCell<Loop>>) { match self { - Self::Full(full) => full.get_config(), - Self::Partial(partial) => partial.get_config(), + Self::Partial(rc) => rc.borrow_mut().r#loop = Some(r#loop), + Self::Full(f) => f.set_loop(r#loop), } } - - pub fn set_loop(&mut self, r#loop: std::rc::Rc<std::cell::RefCell<crate::util::r#loop::Loop>>) { + fn get_loop(&self) -> std::rc::Rc<std::cell::RefCell<Loop>> { match self { - Self::Full(full) => full.set_loop(r#loop), - Self::Partial(partial) => partial.set_loop(r#loop), + Self::Partial(rc) => rc.borrow().r#loop.as_ref().unwrap().clone(), + Self::Full(f) => f.get_loop(), } } - - pub fn get_loop(&self) -> std::rc::Rc<std::cell::RefCell<crate::util::r#loop::Loop>> { + fn set_repository_manager(&self, manager: std::rc::Rc<std::cell::RefCell<RepositoryManager>>) { match self { - Self::Full(full) => full.get_loop(), - Self::Partial(partial) => partial.get_loop(), + Self::Partial(rc) => rc.borrow_mut().repository_manager = Some(manager), + Self::Full(f) => f.set_repository_manager(manager), } } - - pub fn set_repository_manager( - &mut self, - manager: std::rc::Rc<std::cell::RefCell<crate::repository::RepositoryManager>>, - ) { + fn get_repository_manager(&self) -> std::rc::Rc<std::cell::RefCell<RepositoryManager>> { match self { - Self::Full(full) => full.set_repository_manager(manager), - Self::Partial(partial) => partial.set_repository_manager(manager), + Self::Partial(rc) => rc.borrow().repository_manager.as_ref().unwrap().clone(), + Self::Full(f) => f.get_repository_manager(), } } - - pub fn get_repository_manager( + fn set_installation_manager( &self, - ) -> std::rc::Rc<std::cell::RefCell<crate::repository::RepositoryManager>> { - match self { - Self::Full(full) => full.get_repository_manager(), - Self::Partial(partial) => partial.get_repository_manager(), - } - } - - pub fn set_installation_manager( - &mut self, - manager: std::rc::Rc<std::cell::RefCell<crate::installer::InstallationManager>>, + manager: std::rc::Rc<std::cell::RefCell<InstallationManager>>, ) { match self { - Self::Full(full) => full.set_installation_manager(manager), - Self::Partial(partial) => partial.set_installation_manager(manager), + Self::Partial(rc) => rc.borrow_mut().installation_manager = Some(manager), + Self::Full(f) => f.set_installation_manager(manager), } } - - pub fn get_installation_manager( - &self, - ) -> std::rc::Rc<std::cell::RefCell<crate::installer::InstallationManager>> { + fn get_installation_manager(&self) -> std::rc::Rc<std::cell::RefCell<InstallationManager>> { match self { - Self::Full(full) => full.get_installation_manager(), - Self::Partial(partial) => partial.get_installation_manager(), + Self::Partial(rc) => rc.borrow().installation_manager.as_ref().unwrap().clone(), + Self::Full(f) => f.get_installation_manager(), } } - - pub fn set_event_dispatcher( - &mut self, - dispatcher: std::rc::Rc<std::cell::RefCell<crate::event_dispatcher::EventDispatcher>>, + fn set_event_dispatcher( + &self, + event_dispatcher: std::rc::Rc<std::cell::RefCell<EventDispatcher>>, ) { match self { - Self::Full(full) => full.set_event_dispatcher(dispatcher), - Self::Partial(partial) => partial.set_event_dispatcher(dispatcher), + Self::Partial(rc) => rc.borrow_mut().event_dispatcher = Some(event_dispatcher), + Self::Full(f) => f.set_event_dispatcher(event_dispatcher), } } - - pub fn get_event_dispatcher( - &self, - ) -> std::rc::Rc<std::cell::RefCell<crate::event_dispatcher::EventDispatcher>> { + fn get_event_dispatcher(&self) -> std::rc::Rc<std::cell::RefCell<EventDispatcher>> { match self { - Self::Full(full) => full.get_event_dispatcher(), - Self::Partial(partial) => partial.get_event_dispatcher(), + Self::Partial(rc) => rc.borrow().event_dispatcher.as_ref().unwrap().clone(), + Self::Full(f) => f.get_event_dispatcher(), } } - - pub fn is_global(&self) -> bool { + fn is_global(&self) -> bool { match self { - Self::Full(full) => full.is_global(), - Self::Partial(partial) => partial.is_global(), + Self::Partial(rc) => rc.borrow().global, + Self::Full(f) => f.is_global(), } } - - pub fn set_global(&mut self) { + fn set_global(&self) { match self { - Self::Full(full) => full.set_global(), - Self::Partial(partial) => partial.set_global(), + Self::Partial(rc) => rc.borrow_mut().global = true, + Self::Full(f) => f.set_global(), } } } -/// Shared reference to \Composer\PartialComposer or \Composer\Composer. -/// Use this for parameters or fields typed as \Composer\PartialComposer in PHP. +/// Shared weak reference to a \Composer\PartialComposer that may at runtime be either partial or full. #[derive(Debug, Clone)] -pub struct PartialComposerHandle(std::rc::Rc<std::cell::RefCell<PartialOrFullComposer>>); - -impl PartialComposerHandle { - pub fn borrow_partial(&self) -> std::cell::Ref<'_, PartialComposer> { - std::cell::Ref::map(self.0.borrow(), |c| c.as_partial()) - } - - pub fn borrow_partial_mut(&self) -> std::cell::RefMut<'_, PartialComposer> { - std::cell::RefMut::map(self.0.borrow_mut(), |c| c.as_partial_mut()) - } - - pub fn is_full(&self) -> bool { - self.0.borrow().is_full() - } +pub enum AnyComposerWeakHandle { + Partial(std::rc::Weak<std::cell::RefCell<InnerPartialComposer>>), + Full(FullComposerWeakHandle), +} - /// Downcast to a full Composer handle. PHP `$composer instanceof Composer`. - pub fn as_full(&self) -> Option<ComposerHandle> { - if self.0.borrow().is_full() { - Some(ComposerHandle::from_rc_unchecked(self.0.clone())) - } else { - None +impl AnyComposerWeakHandle { + pub fn upgrade(&self) -> Option<AnyComposerHandle> { + match self { + Self::Partial(p) => p.upgrade().map(AnyComposerHandle::Partial), + Self::Full(f) => f.upgrade().map(AnyComposerHandle::Full), } } - pub fn downgrade(&self) -> PartialComposerWeakHandle { - PartialComposerWeakHandle(std::rc::Rc::downgrade(&self.0)) + fn upgraded(&self) -> AnyComposerHandle { + self.upgrade() + .expect("PartialComposer has been dropped before its weak reference") } +} - pub fn from_rc(rc: std::rc::Rc<std::cell::RefCell<PartialOrFullComposer>>) -> Self { - Self(rc) +impl PartialComposer for AnyComposerWeakHandle { + fn set_package(&self, package: RootPackageInterfaceHandle) { + self.upgraded().set_package(package); } - - pub fn as_rc(&self) -> &std::rc::Rc<std::cell::RefCell<PartialOrFullComposer>> { - &self.0 + fn get_package(&self) -> RootPackageInterfaceHandle { + self.upgraded().get_package() } -} - -/// Shared weak reference to \Composer\PartialComposer or \Composer\Composer. -#[derive(Debug, Clone)] -pub struct PartialComposerWeakHandle(std::rc::Weak<std::cell::RefCell<PartialOrFullComposer>>); - -impl PartialComposerWeakHandle { - pub fn upgrade(&self) -> Option<PartialComposerHandle> { - self.0.upgrade().map(PartialComposerHandle) + fn set_config(&self, config: std::rc::Rc<std::cell::RefCell<Config>>) { + self.upgraded().set_config(config); } - - pub fn from_weak(weak: std::rc::Weak<std::cell::RefCell<PartialOrFullComposer>>) -> Self { - Self(weak) + fn get_config(&self) -> std::rc::Rc<std::cell::RefCell<Config>> { + self.upgraded().get_config() } -} - -/// Shared reference to \Composer\Composer. -/// Use this for parameters or fields typed as \Composer\Composer in PHP. -#[derive(Debug, Clone)] -pub struct ComposerHandle(std::rc::Rc<std::cell::RefCell<PartialOrFullComposer>>); - -impl ComposerHandle { - pub fn borrow(&self) -> std::cell::Ref<'_, Composer> { - std::cell::Ref::map(self.0.borrow(), |c| { - c.as_full() - .expect("Composer handle invariant: inner is Full") - }) + fn set_loop(&self, r#loop: std::rc::Rc<std::cell::RefCell<Loop>>) { + self.upgraded().set_loop(r#loop); } - - pub fn borrow_mut(&self) -> std::cell::RefMut<'_, Composer> { - std::cell::RefMut::map(self.0.borrow_mut(), |c| { - c.as_full_mut() - .expect("Composer handle invariant: inner is Full") - }) + fn get_loop(&self) -> std::rc::Rc<std::cell::RefCell<Loop>> { + self.upgraded().get_loop() } - - pub fn upcast(&self) -> PartialComposerHandle { - PartialComposerHandle::from_rc(self.0.clone()) + fn set_repository_manager(&self, manager: std::rc::Rc<std::cell::RefCell<RepositoryManager>>) { + self.upgraded().set_repository_manager(manager); } - - pub fn downgrade(&self) -> ComposerWeakHandle { - ComposerWeakHandle(std::rc::Rc::downgrade(&self.0)) + fn get_repository_manager(&self) -> std::rc::Rc<std::cell::RefCell<RepositoryManager>> { + self.upgraded().get_repository_manager() } - - pub fn from_rc_unchecked(rc: std::rc::Rc<std::cell::RefCell<PartialOrFullComposer>>) -> Self { - Self(rc) + fn set_installation_manager( + &self, + manager: std::rc::Rc<std::cell::RefCell<InstallationManager>>, + ) { + self.upgraded().set_installation_manager(manager); } - - pub fn as_rc(&self) -> &std::rc::Rc<std::cell::RefCell<PartialOrFullComposer>> { - &self.0 + fn get_installation_manager(&self) -> std::rc::Rc<std::cell::RefCell<InstallationManager>> { + self.upgraded().get_installation_manager() } -} - -impl From<ComposerHandle> for PartialComposerHandle { - fn from(c: ComposerHandle) -> Self { - c.upcast() + fn set_event_dispatcher( + &self, + event_dispatcher: std::rc::Rc<std::cell::RefCell<EventDispatcher>>, + ) { + self.upgraded().set_event_dispatcher(event_dispatcher); } -} - -/// Shared weak reference to \Composer\Composer. -#[derive(Debug, Clone)] -pub struct ComposerWeakHandle(std::rc::Weak<std::cell::RefCell<PartialOrFullComposer>>); - -impl ComposerWeakHandle { - pub fn upgrade(&self) -> Option<ComposerHandle> { - self.0.upgrade().map(ComposerHandle) + fn get_event_dispatcher(&self) -> std::rc::Rc<std::cell::RefCell<EventDispatcher>> { + self.upgraded().get_event_dispatcher() } - - pub fn from_weak(weak: std::rc::Weak<std::cell::RefCell<PartialOrFullComposer>>) -> Self { - Self(weak) + fn is_global(&self) -> bool { + self.upgraded().is_global() + } + fn set_global(&self) { + self.upgraded().set_global(); } } -/// Borrows a polymorphic `PartialComposer` as a fully-loaded `Composer`. +/// Downcasts a polymorphic composer handle to a fully-loaded \Composer\Composer. /// /// Commands obtain their Composer through `require_composer` / `create_composer_instance`, /// which always yield a fully-loaded instance, so the downcast is infallible here. -pub fn composer_full(composer: &PartialComposerHandle) -> std::cell::Ref<'_, Composer> { - std::cell::Ref::map(composer.as_rc().borrow(), |c| { - c.as_full() - .expect("a fully loaded Composer is required here") - }) -} - -/// Mutably borrows a polymorphic `PartialComposer` as a fully-loaded `Composer`. See [`composer_full`]. -pub fn composer_full_mut(composer: &PartialComposerHandle) -> std::cell::RefMut<'_, Composer> { - std::cell::RefMut::map(composer.as_rc().borrow_mut(), |c| { - c.as_full_mut() - .expect("a fully loaded Composer is required here") - }) +pub fn composer_full(composer: &AnyComposerHandle) -> FullComposerHandle { + composer + .as_full() + .expect("a fully loaded Composer is required here") } |
