diff options
Diffstat (limited to 'crates/shirabe/src/package/handle.rs')
| -rw-r--r-- | crates/shirabe/src/package/handle.rs | 41 |
1 files changed, 40 insertions, 1 deletions
diff --git a/crates/shirabe/src/package/handle.rs b/crates/shirabe/src/package/handle.rs index 746e2ce..aecc219 100644 --- a/crates/shirabe/src/package/handle.rs +++ b/crates/shirabe/src/package/handle.rs @@ -12,7 +12,7 @@ use crate::package::{ }; /// Any package type. -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum AnyPackage { Package(Package), CompletePackage(CompletePackage), @@ -137,6 +137,36 @@ impl AnyPackage { pub fn is_root_alias(&self) -> bool { matches!(self, Self::RootAliasPackage(_)) } + + /// PHP `clone $package`: fresh object identity. Matches PHP's shallow + /// clone for most types (scalars/arrays are copied, nested object + /// references — including `aliasOf` on alias variants — are shared), + /// except for RootAliasPackage where PHP's `__clone` hook explicitly + /// reseats `aliasOf` to a fresh clone. + pub fn dup(&self) -> Self { + match self { + Self::Package(p) => Self::Package(p.clone()), + Self::CompletePackage(p) => Self::CompletePackage(p.clone()), + Self::RootPackage(p) => Self::RootPackage(p.clone()), + Self::AliasPackage(p) => Self::AliasPackage(p.clone()), + Self::CompleteAliasPackage(p) => Self::CompleteAliasPackage(p.clone()), + Self::RootAliasPackage(p) => { + // PHP's RootAliasPackage overrides `__clone()`: + // $this->aliasOf = clone $this->aliasOf; + let new_alias_of_inner = p.alias_of.0.borrow().dup(); + let new_alias_of_rc = Rc::new(RefCell::new(new_alias_of_inner)); + let new_root = RootPackageHandle(new_alias_of_rc.clone()); + let new_complete = CompletePackageHandle(new_alias_of_rc.clone()); + let new_pkg = PackageHandle(new_alias_of_rc); + + let mut cloned = p.clone(); + cloned.alias_of = new_root; + cloned.inner.alias_of = new_complete; + cloned.inner.inner.alias_of = new_pkg; + Self::RootAliasPackage(cloned) + } + } + } } macro_rules! delegate_package_interface_to_inner { @@ -1119,6 +1149,15 @@ macro_rules! impl_handle_common { pub fn ptr_eq(&self, other: &Self) -> bool { std::rc::Rc::ptr_eq(&self.0, &other.0) } + + /// PHP `clone $x`: fresh object identity. See [`AnyPackage::dup`] + /// for the per-variant semantics (including the RootAliasPackage + /// `__clone` hook). + pub fn dup(other: &Self) -> Self { + Self(std::rc::Rc::new(std::cell::RefCell::new( + other.0.borrow().dup(), + ))) + } } impl PartialEq for $Handle { |
