Skip to content

Commit 0a0ec55

Browse files
committed
feat: Add interface class registration
1 parent 3d26586 commit 0a0ec55

File tree

4 files changed

+127
-14
lines changed

4 files changed

+127
-14
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ parking_lot = "0.12"
1717
cfg-if = "1.0"
1818
once_cell = "1.17"
1919
anyhow = { version = "1", optional = true }
20-
ext-php-rs-derive = { version = "=0.11.0", path = "./crates/macros" }
20+
ext-php-rs-derive = { version = "=0.10.2", path = "./crates/macros" }
2121

2222
[dev-dependencies]
2323
skeptic = "0.13"

crates/macros/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description = "Derive macros for ext-php-rs."
44
repository = "https://github.com/davidcole1340/ext-php-rs"
55
homepage = "https://github.com/davidcole1340/ext-php-rs"
66
license = "MIT OR Apache-2.0"
7-
version = "0.11.0"
7+
version = "0.10.2"
88
authors = ["David Cole <[email protected]>"]
99
edition = "2018"
1010

src/builders/class.rs

Lines changed: 93 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::{
99
exception::PhpException,
1010
ffi::{
1111
zend_declare_class_constant, zend_declare_property, zend_do_implement_interface,
12-
zend_register_internal_class_ex,
12+
zend_register_internal_class_ex, zend_register_internal_interface,
1313
},
1414
flags::{ClassFlags, MethodFlags, PropertyFlags},
1515
types::{ZendClassObject, ZendObject, ZendStr, Zval},
@@ -293,16 +293,24 @@ impl ClassBuilder {
293293
let func = Box::into_raw(methods.into_boxed_slice()) as *const FunctionEntry;
294294
self.ce.info.internal.builtin_functions = func;
295295

296-
let class = unsafe {
297-
zend_register_internal_class_ex(
298-
&mut self.ce,
299-
match self.extends {
300-
Some(ptr) => (ptr as *const _) as *mut _,
301-
None => std::ptr::null_mut(),
302-
},
303-
)
304-
.as_mut()
305-
.ok_or(Error::InvalidPointer)?
296+
let class = if self.ce.flags().contains(ClassFlags::Interface) {
297+
unsafe {
298+
zend_register_internal_interface(&mut self.ce)
299+
.as_mut()
300+
.ok_or(Error::InvalidPointer)?
301+
}
302+
} else {
303+
unsafe {
304+
zend_register_internal_class_ex(
305+
&mut self.ce,
306+
match self.extends {
307+
Some(ptr) => (ptr as *const _) as *mut _,
308+
None => std::ptr::null_mut(),
309+
},
310+
)
311+
.as_mut()
312+
.ok_or(Error::InvalidPointer)?
313+
}
306314
};
307315

308316
// disable serialization if the class has an associated object
@@ -364,3 +372,77 @@ impl ClassBuilder {
364372
Ok(())
365373
}
366374
}
375+
376+
pub struct InterfaceBuilder {
377+
class_builder: ClassBuilder,
378+
}
379+
380+
impl InterfaceBuilder {
381+
pub fn new<T: Into<String>>(name: T) -> Self {
382+
Self {
383+
class_builder: ClassBuilder::new(name),
384+
}
385+
}
386+
387+
pub fn implements(mut self, interface: &'static ClassEntry) -> Self {
388+
self.class_builder = self.class_builder.implements(interface);
389+
390+
self
391+
}
392+
393+
pub fn method(mut self, func: FunctionBuilder<'static>, flags: MethodFlags) -> Self {
394+
self.class_builder = self.class_builder.method(func, flags);
395+
396+
self
397+
}
398+
399+
pub fn constant<T: Into<String>>(
400+
mut self,
401+
name: T,
402+
value: impl IntoZval + 'static,
403+
docs: DocComments,
404+
) -> Result<Self> {
405+
self.class_builder = self.class_builder.constant(name, value, docs)?;
406+
407+
Ok(self)
408+
}
409+
410+
pub fn dyn_constant<T: Into<String>>(
411+
mut self,
412+
name: T,
413+
value: &'static dyn IntoZvalDyn,
414+
docs: DocComments,
415+
) -> Result<Self> {
416+
self.class_builder = self.class_builder.dyn_constant(name, value, docs)?;
417+
418+
Ok(self)
419+
}
420+
421+
pub fn flags(mut self, flags: ClassFlags) -> Self {
422+
self.class_builder = self.class_builder.flags(flags);
423+
self
424+
}
425+
426+
pub fn object_override<T: RegisteredClass>(mut self) -> Self {
427+
self.class_builder = self.class_builder.object_override::<T>();
428+
429+
self
430+
}
431+
432+
pub fn registration(mut self, register: fn(&'static mut ClassEntry)) -> Self {
433+
self.class_builder = self.class_builder.registration(register);
434+
435+
self
436+
}
437+
438+
pub fn docs(mut self, docs: DocComments) -> Self {
439+
self.class_builder = self.class_builder.docs(docs);
440+
self
441+
}
442+
443+
pub fn builder(mut self) -> ClassBuilder {
444+
self.class_builder = self.class_builder.flags(ClassFlags::Interface);
445+
dbg!(self.class_builder.ce.ce_flags);
446+
self.class_builder
447+
}
448+
}

src/builders/module.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::{convert::TryFrom, ffi::CString, mem, ptr};
22

3-
use super::{ClassBuilder, FunctionBuilder};
3+
use super::{class::InterfaceBuilder, ClassBuilder, FunctionBuilder};
44
use crate::{
55
class::RegisteredClass,
66
constant::IntoConst,
@@ -167,6 +167,37 @@ impl ModuleBuilder<'_> {
167167
self
168168
}
169169

170+
pub fn interface<T: RegisteredClass>(mut self) -> Self {
171+
self.classes.push(|| {
172+
let mut builder = InterfaceBuilder::new(T::CLASS_NAME);
173+
for (method, flags) in T::method_builders() {
174+
builder = builder.method(method, flags);
175+
}
176+
for iface in T::IMPLEMENTS {
177+
builder = builder.implements(iface());
178+
}
179+
for (name, value, docs) in T::constants() {
180+
builder = builder
181+
.dyn_constant(*name, *value, docs)
182+
.expect("Failed to register constant");
183+
}
184+
185+
let mut class_builder = builder.builder();
186+
187+
if let Some(modifier) = T::BUILDER_MODIFIER {
188+
class_builder = modifier(class_builder);
189+
}
190+
191+
class_builder
192+
.object_override::<T>()
193+
.registration(|ce| {
194+
T::get_metadata().set_ce(ce);
195+
})
196+
.docs(T::DOC_COMMENTS)
197+
});
198+
self
199+
}
200+
170201
/// Adds a class to the extension.
171202
pub fn class<T: RegisteredClass>(mut self) -> Self {
172203
self.classes.push(|| {

0 commit comments

Comments
 (0)