aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/composer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/shirabe/src/composer.rs')
-rw-r--r--crates/shirabe/src/composer.rs543
1 files changed, 460 insertions, 83 deletions
diff --git a/crates/shirabe/src/composer.rs b/crates/shirabe/src/composer.rs
index 1dfe5c8..9f420ef 100644
--- a/crates/shirabe/src/composer.rs
+++ b/crates/shirabe/src/composer.rs
@@ -1,36 +1,131 @@
//! ref: composer/src/Composer/Composer.php
+//! ref: composer/src/Composer/PartialComposer.php
use shirabe_external_packages::composer::pcre::Preg;
use crate::autoload::AutoloadGenerator;
+use crate::config::Config;
use crate::downloader::DownloadManager;
-use crate::package::Locker;
+use crate::event_dispatcher::EventDispatcher;
+use crate::installer::InstallationManager;
use crate::package::archiver::ArchiveManager;
-use crate::partial_composer::PartialComposer;
+use crate::package::{Locker, RootPackageInterface};
use crate::plugin::PluginManager;
+use crate::repository::RepositoryManager;
+use crate::util::r#loop::Loop;
+// TODO: change this information to Shirabe version.
+pub const VERSION: &'static str = "2.9.7";
+pub const BRANCH_ALIAS_VERSION: &'static str = "";
+pub const RELEASE_DATE: &'static str = "2026-04-14 13:31:52";
+pub const SOURCE_VERSION: &'static str = "";
+pub const RUNTIME_API_VERSION: &'static str = "2.2.2";
+
+pub fn get_version() -> String {
+ if VERSION == "@package_version@" {
+ return SOURCE_VERSION.to_string();
+ }
+ if BRANCH_ALIAS_VERSION != "" && Preg::is_match("{^[a-f0-9]{40}$}", VERSION).unwrap_or(false) {
+ return format!("{}+{}", BRANCH_ALIAS_VERSION, VERSION);
+ }
+ VERSION.to_string()
+}
+
+/// Internal data type corresponding to \Composer\PartialComposer.
+#[derive(Debug, Default)]
+pub struct PartialComposer {
+ global: bool,
+ package: Option<Box<dyn RootPackageInterface>>,
+ 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>>>,
+}
+
+impl PartialComposer {
+ pub fn set_package(&mut self, package: Box<dyn RootPackageInterface>) {
+ self.package = Some(package);
+ }
+
+ pub fn get_package(&self) -> &dyn RootPackageInterface {
+ self.package.as_deref().unwrap()
+ }
+
+ pub fn set_config(&mut self, config: std::rc::Rc<std::cell::RefCell<Config>>) {
+ self.config = Some(config);
+ }
+
+ pub fn get_config(&self) -> std::rc::Rc<std::cell::RefCell<Config>> {
+ self.config.as_ref().unwrap().clone()
+ }
+
+ pub fn set_loop(&mut self, r#loop: std::rc::Rc<std::cell::RefCell<Loop>>) {
+ self.r#loop = Some(r#loop);
+ }
+
+ pub fn get_loop(&self) -> std::rc::Rc<std::cell::RefCell<Loop>> {
+ self.r#loop.as_ref().unwrap().clone()
+ }
+
+ pub fn set_repository_manager(
+ &mut self,
+ manager: std::rc::Rc<std::cell::RefCell<RepositoryManager>>,
+ ) {
+ self.repository_manager = Some(manager);
+ }
+
+ pub fn get_repository_manager(&self) -> std::rc::Rc<std::cell::RefCell<RepositoryManager>> {
+ self.repository_manager.as_ref().unwrap().clone()
+ }
+
+ pub fn set_installation_manager(
+ &mut self,
+ manager: std::rc::Rc<std::cell::RefCell<InstallationManager>>,
+ ) {
+ self.installation_manager = Some(manager);
+ }
+
+ pub fn get_installation_manager(&self) -> std::rc::Rc<std::cell::RefCell<InstallationManager>> {
+ self.installation_manager.as_ref().unwrap().clone()
+ }
+
+ pub fn set_event_dispatcher(
+ &mut self,
+ event_dispatcher: std::rc::Rc<std::cell::RefCell<EventDispatcher>>,
+ ) {
+ self.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()
+ }
+
+ pub fn is_global(&self) -> bool {
+ self.global
+ }
+
+ pub fn set_global(&mut self) {
+ self.global = true;
+ }
+}
+
+/// Internal data type corresponding to \Composer\Composer.
#[derive(Debug)]
pub struct Composer {
- inner: PartialComposer,
- locker: Option<Locker>,
+ 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<Box<PluginManager>>,
- autoload_generator: Option<AutoloadGenerator>,
- archive_manager: Option<ArchiveManager>,
+ 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 {
- // TODO: change this information to Shirabe version.
- pub const VERSION: &'static str = "2.9.7";
- pub const BRANCH_ALIAS_VERSION: &'static str = "";
- pub const RELEASE_DATE: &'static str = "2026-04-14 13:31:52";
- pub const SOURCE_VERSION: &'static str = "";
- pub const RUNTIME_API_VERSION: &'static str = "2.2.2";
-
pub fn new() -> Self {
Self {
- inner: PartialComposer::default(),
+ partial: PartialComposer::default(),
locker: None,
download_manager: None,
plugin_manager: None,
@@ -39,28 +134,12 @@ impl Composer {
}
}
- pub fn get_version() -> String {
- if Self::VERSION == "@package_version@" {
- return Self::SOURCE_VERSION.to_string();
- }
- if Self::BRANCH_ALIAS_VERSION != ""
- && Preg::is_match("{^[a-f0-9]{40}$}", Self::VERSION).unwrap_or(false)
- {
- return format!("{}+{}", Self::BRANCH_ALIAS_VERSION, Self::VERSION);
- }
- Self::VERSION.to_string()
- }
-
- pub fn set_locker(&mut self, locker: Locker) {
+ pub fn set_locker(&mut self, locker: std::rc::Rc<std::cell::RefCell<Locker>>) {
self.locker = Some(locker);
}
- pub fn get_locker(&self) -> &Locker {
- self.locker.as_ref().unwrap()
- }
-
- pub fn get_locker_mut(&mut self) -> &mut Locker {
- self.locker.as_mut().unwrap()
+ pub fn get_locker(&self) -> std::rc::Rc<std::cell::RefCell<Locker>> {
+ self.locker.as_ref().unwrap().clone()
}
pub fn set_download_manager(
@@ -70,117 +149,415 @@ impl Composer {
self.download_manager = Some(manager);
}
- pub fn get_download_manager(&self) -> &std::rc::Rc<std::cell::RefCell<DownloadManager>> {
- self.download_manager.as_ref().unwrap()
+ pub fn get_download_manager(&self) -> std::rc::Rc<std::cell::RefCell<DownloadManager>> {
+ self.download_manager.as_ref().unwrap().clone()
}
- pub fn set_archive_manager(&mut self, manager: ArchiveManager) {
+ pub fn set_archive_manager(
+ &mut self,
+ manager: std::rc::Rc<std::cell::RefCell<ArchiveManager>>,
+ ) {
self.archive_manager = Some(manager);
}
- pub fn get_archive_manager(&self) -> &ArchiveManager {
- self.archive_manager.as_ref().unwrap()
+ pub fn get_archive_manager(&self) -> std::rc::Rc<std::cell::RefCell<ArchiveManager>> {
+ self.archive_manager.as_ref().unwrap().clone()
}
// TODO(plugin): set_plugin_manager is part of the plugin API
- pub fn set_plugin_manager(&mut self, manager: PluginManager) {
- self.plugin_manager = Some(Box::new(manager));
+ pub fn set_plugin_manager(&mut self, manager: std::rc::Rc<std::cell::RefCell<PluginManager>>) {
+ self.plugin_manager = Some(manager);
}
// TODO(plugin): get_plugin_manager is part of the plugin API
- pub fn get_plugin_manager(&self) -> &PluginManager {
- self.plugin_manager.as_ref().unwrap()
+ pub fn get_plugin_manager(&self) -> std::rc::Rc<std::cell::RefCell<PluginManager>> {
+ self.plugin_manager.as_ref().unwrap().clone()
}
- // TODO(plugin): get_plugin_manager_mut is part of the plugin API
- pub fn get_plugin_manager_mut(&mut self) -> &mut PluginManager {
- self.plugin_manager.as_mut().unwrap()
+ pub fn set_autoload_generator(
+ &mut self,
+ autoload_generator: std::rc::Rc<std::cell::RefCell<AutoloadGenerator>>,
+ ) {
+ self.autoload_generator = Some(autoload_generator);
}
- pub fn set_autoload_generator(&mut self, autoload_generator: AutoloadGenerator) {
- self.autoload_generator = Some(autoload_generator);
+ pub fn get_autoload_generator(&self) -> std::rc::Rc<std::cell::RefCell<AutoloadGenerator>> {
+ self.autoload_generator.as_ref().unwrap().clone()
+ }
+
+ pub fn as_partial(&self) -> &PartialComposer {
+ &self.partial
}
- pub fn get_autoload_generator(&self) -> &AutoloadGenerator {
- self.autoload_generator.as_ref().unwrap()
+ pub fn as_partial_mut(&mut self) -> &mut PartialComposer {
+ &mut self.partial
}
- pub fn get_autoload_generator_mut(&mut self) -> &mut AutoloadGenerator {
- self.autoload_generator.as_mut().unwrap()
+ pub fn set_package(&mut self, package: Box<dyn crate::package::RootPackageInterface>) {
+ self.partial.set_package(package);
}
pub fn get_package(&self) -> &dyn crate::package::RootPackageInterface {
- self.inner.get_package()
+ self.partial.get_package()
}
- pub fn get_config(&self) -> &std::rc::Rc<std::cell::RefCell<crate::config::Config>> {
- self.inner.get_config()
+ pub fn set_config(&mut self, config: std::rc::Rc<std::cell::RefCell<crate::config::Config>>) {
+ self.partial.set_config(config);
}
- pub fn get_config_mut(
+ pub fn get_config(&self) -> std::rc::Rc<std::cell::RefCell<crate::config::Config>> {
+ self.partial.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);
+ }
+
+ pub fn get_loop(&self) -> std::rc::Rc<std::cell::RefCell<crate::util::r#loop::Loop>> {
+ self.partial.get_loop()
+ }
+
+ pub fn set_repository_manager(
&mut self,
- ) -> &mut std::rc::Rc<std::cell::RefCell<crate::config::Config>> {
- self.inner.get_config_mut()
+ manager: std::rc::Rc<std::cell::RefCell<crate::repository::RepositoryManager>>,
+ ) {
+ self.partial.set_repository_manager(manager);
+ }
+
+ pub fn get_repository_manager(
+ &self,
+ ) -> std::rc::Rc<std::cell::RefCell<crate::repository::RepositoryManager>> {
+ self.partial.get_repository_manager()
}
- pub fn get_repository_manager(&self) -> &crate::repository::RepositoryManager {
- self.inner.get_repository_manager()
+ pub fn set_installation_manager(
+ &mut self,
+ manager: std::rc::Rc<std::cell::RefCell<crate::installer::InstallationManager>>,
+ ) {
+ self.partial.set_installation_manager(manager);
+ }
+
+ pub fn get_installation_manager(
+ &self,
+ ) -> std::rc::Rc<std::cell::RefCell<crate::installer::InstallationManager>> {
+ self.partial.get_installation_manager()
}
pub fn set_event_dispatcher(
&mut self,
dispatcher: std::rc::Rc<std::cell::RefCell<crate::event_dispatcher::EventDispatcher>>,
) {
- self.inner.set_event_dispatcher(dispatcher);
+ self.partial.set_event_dispatcher(dispatcher);
}
pub fn get_event_dispatcher(
&self,
- ) -> &std::rc::Rc<std::cell::RefCell<crate::event_dispatcher::EventDispatcher>> {
- self.inner.get_event_dispatcher()
+ ) -> std::rc::Rc<std::cell::RefCell<crate::event_dispatcher::EventDispatcher>> {
+ self.partial.get_event_dispatcher()
+ }
+
+ pub fn is_global(&self) -> bool {
+ self.partial.is_global()
}
- pub fn get_installation_manager(&self) -> &crate::installer::InstallationManager {
- self.inner.get_installation_manager()
+ pub fn set_global(&mut self) {
+ self.partial.set_global();
}
+}
+
+#[derive(Debug)]
+pub enum PartialOrFullComposer {
+ Full(Composer),
+ Partial(PartialComposer),
+}
- pub fn get_installation_manager_mut(&mut self) -> &mut crate::installer::InstallationManager {
- self.inner.get_installation_manager_mut()
+impl PartialOrFullComposer {
+ pub fn new_full() -> Self {
+ Self::Full(Composer::new())
}
- pub fn get_loop(&self) -> &std::rc::Rc<std::cell::RefCell<crate::util::r#loop::Loop>> {
- self.inner.get_loop()
+ pub fn new_partial() -> Self {
+ Self::Partial(PartialComposer::default())
}
- pub fn set_loop(&mut self, r#loop: std::rc::Rc<std::cell::RefCell<crate::util::r#loop::Loop>>) {
- self.inner.set_loop(r#loop);
+ pub fn is_full(&self) -> bool {
+ matches!(self, Self::Full(_))
+ }
+
+ pub fn is_partial(&self) -> bool {
+ matches!(self, Self::Partial(_))
+ }
+
+ pub fn as_full(&self) -> Option<&Composer> {
+ match self {
+ Self::Full(full) => Some(full),
+ Self::Partial(_) => None,
+ }
+ }
+
+ pub fn as_full_mut(&mut self) -> Option<&mut Composer> {
+ match self {
+ Self::Full(full) => Some(full),
+ Self::Partial(_) => None,
+ }
+ }
+
+ pub fn as_partial(&self) -> &PartialComposer {
+ match self {
+ Self::Full(full) => full.as_partial(),
+ Self::Partial(partial) => partial,
+ }
+ }
+
+ pub fn as_partial_mut(&mut self) -> &mut PartialComposer {
+ match self {
+ Self::Full(full) => full.as_partial_mut(),
+ Self::Partial(partial) => partial,
+ }
+ }
+
+ pub fn set_package(&mut self, package: Box<dyn crate::package::RootPackageInterface>) {
+ match self {
+ Self::Full(full) => full.set_package(package),
+ Self::Partial(partial) => partial.set_package(package),
+ }
+ }
+
+ pub fn get_package(&self) -> &dyn crate::package::RootPackageInterface {
+ match self {
+ Self::Full(full) => full.get_package(),
+ Self::Partial(partial) => partial.get_package(),
+ }
}
pub fn set_config(&mut self, config: std::rc::Rc<std::cell::RefCell<crate::config::Config>>) {
- self.inner.set_config(config);
+ match self {
+ Self::Full(full) => full.set_config(config),
+ Self::Partial(partial) => partial.set_config(config),
+ }
}
- pub fn set_global(&mut self) {
- self.inner.set_global();
+ pub fn get_config(&self) -> std::rc::Rc<std::cell::RefCell<crate::config::Config>> {
+ match self {
+ Self::Full(full) => full.get_config(),
+ Self::Partial(partial) => partial.get_config(),
+ }
}
- pub fn set_repository_manager(&mut self, manager: crate::repository::RepositoryManager) {
- self.inner.set_repository_manager(manager);
+ pub fn set_loop(&mut self, r#loop: std::rc::Rc<std::cell::RefCell<crate::util::r#loop::Loop>>) {
+ match self {
+ Self::Full(full) => full.set_loop(r#loop),
+ Self::Partial(partial) => partial.set_loop(r#loop),
+ }
+ }
+
+ pub fn get_loop(&self) -> std::rc::Rc<std::cell::RefCell<crate::util::r#loop::Loop>> {
+ match self {
+ Self::Full(full) => full.get_loop(),
+ Self::Partial(partial) => partial.get_loop(),
+ }
+ }
+
+ pub fn set_repository_manager(
+ &mut self,
+ manager: std::rc::Rc<std::cell::RefCell<crate::repository::RepositoryManager>>,
+ ) {
+ match self {
+ Self::Full(full) => full.set_repository_manager(manager),
+ Self::Partial(partial) => partial.set_repository_manager(manager),
+ }
}
- pub fn set_installation_manager(&mut self, manager: crate::installer::InstallationManager) {
- self.inner.set_installation_manager(manager);
+ pub fn get_repository_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>>,
+ ) {
+ match self {
+ Self::Full(full) => full.set_installation_manager(manager),
+ Self::Partial(partial) => partial.set_installation_manager(manager),
+ }
+ }
+
+ pub fn get_installation_manager(
+ &self,
+ ) -> std::rc::Rc<std::cell::RefCell<crate::installer::InstallationManager>> {
+ match self {
+ Self::Full(full) => full.get_installation_manager(),
+ Self::Partial(partial) => partial.get_installation_manager(),
+ }
+ }
+
+ pub fn set_event_dispatcher(
+ &mut self,
+ dispatcher: std::rc::Rc<std::cell::RefCell<crate::event_dispatcher::EventDispatcher>>,
+ ) {
+ match self {
+ Self::Full(full) => full.set_event_dispatcher(dispatcher),
+ Self::Partial(partial) => partial.set_event_dispatcher(dispatcher),
+ }
+ }
+
+ pub fn get_event_dispatcher(
+ &self,
+ ) -> std::rc::Rc<std::cell::RefCell<crate::event_dispatcher::EventDispatcher>> {
+ match self {
+ Self::Full(full) => full.get_event_dispatcher(),
+ Self::Partial(partial) => partial.get_event_dispatcher(),
+ }
}
pub fn is_global(&self) -> bool {
- self.inner.is_global()
+ match self {
+ Self::Full(full) => full.is_global(),
+ Self::Partial(partial) => partial.is_global(),
+ }
+ }
+
+ pub fn set_global(&mut self) {
+ match self {
+ Self::Full(full) => full.set_global(),
+ Self::Partial(partial) => partial.set_global(),
+ }
}
+}
+
+/// Shared reference to \Composer\PartialComposer or \Composer\Composer.
+/// Use this for parameters or fields typed as \Composer\PartialComposer in PHP.
+#[derive(Debug, Clone)]
+pub struct PartialComposerHandle(std::rc::Rc<std::cell::RefCell<PartialOrFullComposer>>);
- pub fn as_partial(&self) -> &crate::partial_composer::PartialComposer {
- &self.inner
+impl PartialComposerHandle {
+ pub fn borrow_partial(&self) -> std::cell::Ref<'_, PartialComposer> {
+ std::cell::Ref::map(self.0.borrow(), |c| c.as_partial())
}
- pub fn set_package(&mut self, package: Box<dyn crate::package::RootPackageInterface>) {
- self.inner.set_package(package);
+ 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()
}
+
+ /// 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(std::rc::Rc::clone(
+ &self.0,
+ )))
+ } else {
+ None
+ }
+ }
+
+ pub fn downgrade(&self) -> PartialComposerWeakHandle {
+ PartialComposerWeakHandle(std::rc::Rc::downgrade(&self.0))
+ }
+
+ pub fn from_rc(rc: std::rc::Rc<std::cell::RefCell<PartialOrFullComposer>>) -> Self {
+ Self(rc)
+ }
+
+ pub fn as_rc(&self) -> &std::rc::Rc<std::cell::RefCell<PartialOrFullComposer>> {
+ &self.0
+ }
+}
+
+/// 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)
+ }
+
+ pub fn from_weak(weak: std::rc::Weak<std::cell::RefCell<PartialOrFullComposer>>) -> Self {
+ Self(weak)
+ }
+}
+
+/// 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")
+ })
+ }
+
+ 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")
+ })
+ }
+
+ pub fn upcast(&self) -> PartialComposerHandle {
+ PartialComposerHandle::from_rc(std::rc::Rc::clone(&self.0))
+ }
+
+ pub fn downgrade(&self) -> ComposerWeakHandle {
+ ComposerWeakHandle(std::rc::Rc::downgrade(&self.0))
+ }
+
+ pub fn from_rc_unchecked(rc: std::rc::Rc<std::cell::RefCell<PartialOrFullComposer>>) -> Self {
+ Self(rc)
+ }
+
+ pub fn as_rc(&self) -> &std::rc::Rc<std::cell::RefCell<PartialOrFullComposer>> {
+ &self.0
+ }
+}
+
+impl From<ComposerHandle> for PartialComposerHandle {
+ fn from(c: ComposerHandle) -> Self {
+ c.upcast()
+ }
+}
+
+/// 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)
+ }
+
+ pub fn from_weak(weak: std::rc::Weak<std::cell::RefCell<PartialOrFullComposer>>) -> Self {
+ Self(weak)
+ }
+}
+
+/// Borrows a polymorphic `PartialComposer` as a fully-loaded `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")
+ })
}