Skip to content

Commit

Permalink
Back to compilation
Browse files Browse the repository at this point in the history
Signed-off-by: Dusan Malusev <[email protected]>
  • Loading branch information
CodeLieutenant committed Jun 20, 2024
1 parent 469452b commit 03f3412
Show file tree
Hide file tree
Showing 11 changed files with 333 additions and 327 deletions.
1 change: 0 additions & 1 deletion examples/complex/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ mod args_bindings;

use std::convert::Infallible;
use std::ffi::CStr;
use std::mem::size_of;

use args_bindings::{
arginfo_Complex_get_all_ini, arginfo_Complex_say_hello, arginfo_Complex_throw_exception,
Expand Down
70 changes: 34 additions & 36 deletions phper/src/classes/entity.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,25 @@
use smallvec::SmallVec;
use std::{any::Any, marker::PhantomData, mem::zeroed, ptr::null_mut, rc::Rc};

use smallvec::SmallVec;

use phper_sys::{
phper_init_class_entry, phper_register_class_entry, zend_class_entry, zend_class_implements,
zend_function_entry,
};

use crate::{functions::FunctionEntry, objects::StateObj, types::Scalar, values::ZVal};
use crate::{functions::FunctionEntry, objects::StateObj, values::ZVal};

use super::{
create_object, entry::ClassEntry, PropertyEntity, StateCloner, StateConstructor,
StaticStateClass, Visibility,
};
use super::{create_object, entry::ClassEntry, StateCloner, StateConstructor, StaticStateClass};

/// Builder for registering class.
///
/// *It is a common practice for PHP extensions to use PHP objects to package
/// third-party resources.*
pub struct ClassEntity<T> {
class: zend_class_entry,
state_constructor: Rc<StateConstructor<T>>,
state_constructor: Rc<StateConstructor>,
method_entities: SmallVec<[FunctionEntry; 16]>,
property_entities: Vec<PropertyEntity>,
// property_entities: Vec<PropertyEntity>,
parent: Option<Box<dyn Fn() -> &'static ClassEntry>>,
interfaces: Vec<Box<dyn Fn() -> &'static ClassEntry>>,
bind_class: Option<&'static StaticStateClass<()>>,
Expand All @@ -47,12 +45,12 @@ impl<T> ClassEntity<T> {
}
}

pub trait Handler<T, Z, E> {
fn execute(&self, state: &mut StateObj<T>, args: &mut [ZVal]) -> Result<Z, E>;
pub trait Handler<Z, E> {
fn execute(&self, state: &mut StateObj, args: &mut [ZVal]) -> Result<Z, E>;
}

impl<T, Z, E> Handler<T, Z, E> for dyn Fn(&mut StateObj<T>, &mut [ZVal]) -> Result<Z, E> + 'static {
fn execute(&self, state: &mut StateObj<T>, args: &mut [ZVal]) -> Result<Z, E> {
impl<Z, E> Handler<Z, E> for dyn Fn(&mut StateObj, &mut [ZVal]) -> Result<Z, E> + 'static {
fn execute(&self, state: &mut StateObj, args: &mut [ZVal]) -> Result<Z, E> {
self(state, args)
}
}
Expand All @@ -72,9 +70,9 @@ impl<T> ClassEntity<T> {

Self {
class: unsafe { phper_init_class_entry(class_name.as_ptr().cast(), class_name_len) },
state_constructor: Rc::new(state_constructor),
state_constructor: Rc::new(move || Box::new(state_constructor()) as Box<dyn Any>),
method_entities: SmallVec::default(),
property_entities: Vec::new(),
// property_entities: Vec::new(),
parent: None,
interfaces: Vec::new(),
state_cloner: None,
Expand Down Expand Up @@ -139,31 +137,31 @@ impl<T> ClassEntity<T> {
/// The argument `value` should be `Copy` because 'zend_declare_property'
/// receive only scalar zval , otherwise will report fatal error:
/// "Internal zvals cannot be refcounted".
pub fn add_property(
&mut self,
name: impl Into<String>,
visibility: Visibility,
value: impl Into<Scalar>,
) {
self.property_entities
.push(PropertyEntity::new(name, visibility, value));
}
// pub fn add_property(
// &mut self,
// name: impl Into<String>,
// visibility: Visibility,
// value: impl Into<Scalar>,
// ) {
// self.property_entities
// .push(PropertyEntity::new(name, visibility, value));
// }

/// Declare static property.
///
/// The argument `value` should be `Copy` because 'zend_declare_property'
/// receive only scalar zval , otherwise will report fatal error:
/// "Internal zvals cannot be refcounted".
pub fn add_static_property(
&mut self,
name: impl Into<String>,
visibility: Visibility,
value: impl Into<Scalar>,
) {
let mut entity = PropertyEntity::new(name, visibility, value);
entity.set_vis_static();
self.property_entities.push(entity);
}
// pub fn add_static_property(
// &mut self,
// name: impl Into<String>,
// visibility: Visibility,
// value: impl Into<Scalar>,
// ) {
// let mut entity = PropertyEntity::new(name, visibility, value);
// entity.set_vis_static();
// self.property_entities.push(entity);
// }

/// Register class to `extends` the parent class.
///
Expand Down Expand Up @@ -307,9 +305,9 @@ impl<T> crate::modules::Registerer for ClassEntity<T> {

(*class_ce).__bindgen_anon_2.create_object = Some(create_object);

for property in &self.property_entities {
property.declare(class_ce);
}
// for property in &self.property_entities {
// property.declare(class_ce);
// }
}

Ok(())
Expand Down
112 changes: 112 additions & 0 deletions phper/src/classes/interfaces.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
use crate::classes::entry::ClassEntry;
use crate::classes::methods::MethodEntityBuilder;
use crate::functions::FunctionEntry;
use phper_sys::{
phper_init_interface_entry, phper_register_interface_entry, zend_class_entry,
zend_class_implements,
};
use smallvec::SmallVec;
use std::mem::zeroed;
use std::ptr::null_mut;
use std::sync::atomic::{AtomicPtr, Ordering};

#[repr(transparent)]
pub struct StaticInterface(AtomicPtr<zend_class_entry>);

impl StaticInterface {
/// Create empty [StaticInterface], with null
/// [zend_class_entry].
pub const fn null() -> Self {
Self(AtomicPtr::new(null_mut()))
}

fn bind(&'static self, ptr: *mut zend_class_entry) {
self.0.store(ptr, Ordering::Relaxed);
}

/// Converts to class entry.
pub fn as_class_entry(&'static self) -> &'static ClassEntry {
unsafe { ClassEntry::from_mut_ptr(self.0.load(Ordering::Relaxed)) }
}
}

/// Builder for registering interface.
pub struct InterfaceEntity {
interface: zend_class_entry,
methods: SmallVec<[FunctionEntry; 16]>,
extends: SmallVec<[Box<dyn Fn() -> &'static ClassEntry>; 1]>,
bind_interface: Option<&'static StaticInterface>,
}

impl InterfaceEntity {
/// Construct a new `InterfaceEntity` with interface name.
pub fn new(interface_name: impl AsRef<str>) -> Self {
let interface_name = interface_name.as_ref();
let interface_name_len = interface_name.len();

Self {
interface: unsafe {
phper_init_interface_entry(interface_name.as_ptr().cast(), interface_name_len)
},
methods: SmallVec::default(),
extends: SmallVec::default(),
bind_interface: None,
}
}

/// Add member method to interface, with mandatory visibility public
/// abstract.
pub fn add_method(&mut self, builder: MethodEntityBuilder) {
self.methods.push(builder.set_abstract().build().into());
}

/// Register interface to `extends` the interfaces, due to the interface can
/// extend multi interface, so this method can be called multi time.
///
/// *Because in the `MINIT` phase, the class starts to register, so the*
/// *closure is used to return the `ClassEntry` to delay the acquisition of*
/// *the class.*
///
/// # Examples
///
/// ```no_run
/// use phper::classes::{ClassEntry, InterfaceEntity};
///
/// let mut interface = InterfaceEntity::new("MyInterface");
/// interface.extends(|| ClassEntry::from_globals("Stringable").unwrap());
/// ```
pub fn extends(&mut self, interface: impl Fn() -> &'static ClassEntry + 'static) {
self.extends.push(Box::new(interface));
}

/// Bind to static [StaticInterface].
///
/// When the interface registered, the [StaticInterface] will be
/// initialized, so you can use the [StaticInterface] to be implemented
/// by other class.
pub fn bind(&mut self, i: &'static StaticInterface) {
self.bind_interface = Some(i);
}
}

impl crate::modules::Registerer for InterfaceEntity {
fn register(mut self, _: i32) -> Result<(), Box<dyn std::error::Error>> {
unsafe {
self.methods.push(zeroed::<FunctionEntry>());

let class_ce =
phper_register_interface_entry(&mut self.interface, self.methods.as_ptr().cast());

if let Some(bind_interface) = self.bind_interface {
bind_interface.bind(class_ce);
}

for interface in &self.extends {
let interface_ce = interface().as_ptr();
zend_class_implements(class_ce, 1, interface_ce);
}
};

Ok(())
}
}
13 changes: 8 additions & 5 deletions phper/src/classes/methods.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use std::ffi::CString;
use std::rc::Rc;
use phper_sys::{ZEND_ACC_ABSTRACT, ZEND_ACC_FINAL, ZEND_ACC_PRIVATE, ZEND_ACC_PROMOTED, ZEND_ACC_PROTECTED, ZEND_ACC_PUBLIC, zend_internal_arg_info};
use crate::classes::{RawVisibility, Visibility};
use crate::classes::RawVisibility;
use crate::functions::{Callable, FunctionEntry};
use crate::utils::ensure_end_with_zero;
use phper_sys::{
zend_internal_arg_info, ZEND_ACC_ABSTRACT, ZEND_ACC_FINAL, ZEND_ACC_PRIVATE,
ZEND_ACC_PROTECTED, ZEND_ACC_PUBLIC,
};
use std::ffi::CString;
use std::rc::Rc;

/// Builder for registering class method.
pub struct MethodEntity {
Expand All @@ -20,7 +23,7 @@ pub struct MethodEntityBuilder {
arguments: &'static [zend_internal_arg_info],
visibility: RawVisibility,
}

#[allow(clippy::from_over_into)]
impl Into<FunctionEntry> for MethodEntity {
fn into(self) -> FunctionEntry {
unsafe { FunctionEntry::from_method_entity(self) }
Expand Down
Loading

0 comments on commit 03f3412

Please sign in to comment.