Add instance_of() and get_class_entry() methods on ZendObject (#197)

* adds `ZendObject::get_class_entry()` to retrieve the class entry of an object without casting pointers
* adds `ZendObject::instance_of()` to allow more idiomatic instanceof checks.
* adds a mention that `ZendObject::is_instance::<T>()` does not check the parent classes or interfaces. This bit me when I tried to check if `my_object.is_instance::<MyInterface>()` and it didn't work.
This commit is contained in:
ju1ius 2022-11-24 11:17:12 +01:00 committed by GitHub
parent 580ad9f462
commit a331213670
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -80,6 +80,17 @@ impl ZendObject {
unsafe { ZBox::from_raw(this.get_mut_zend_obj()) }
}
/// Returns the [`ClassEntry`] associated with this object.
///
/// # Panics
///
/// Panics if the class entry is invalid.
pub fn get_class_entry(&self) -> &'static ClassEntry {
// SAFETY: it is OK to panic here since PHP would segfault anyway
// when encountering an object with no class entry.
unsafe { self.ce.as_ref() }.expect("Could not retrieve class entry.")
}
/// Attempts to retrieve the class name of the object.
pub fn get_class_name(&self) -> Result<String> {
unsafe {
@ -91,8 +102,21 @@ impl ZendObject {
}
}
/// Returns whether this object is an instance of the given [`ClassEntry`].
///
/// This method checks the class and interface inheritance chain.
///
/// # Panics
///
/// Panics if the class entry is invalid.
pub fn instance_of(&self, ce: &ClassEntry) -> bool {
self.get_class_entry().instance_of(ce)
}
/// Checks if the given object is an instance of a registered class with
/// Rust type `T`.
///
/// This method doesn't check the class and interface inheritance chain.
pub fn is_instance<T: RegisteredClass>(&self) -> bool {
(self.ce as *const ClassEntry).eq(&(T::get_metadata().ce() as *const _))
}