Skip to content

Commit a7e50d8

Browse files
committed
Add method visibility and static access modifier.
1 parent 05b9120 commit a7e50d8

File tree

12 files changed

+114
-31
lines changed

12 files changed

+114
-31
lines changed

examples/hello/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use phper::{
22
arrays::Array,
3-
classes::DynamicClass,
3+
classes::{DynamicClass, Visibility},
44
functions::Argument,
55
ini::Policy,
66
modules::{Module, ModuleArgs},
@@ -66,6 +66,7 @@ pub fn get_module() -> Module {
6666
foo_class.add_property("foo", "100".to_string());
6767
foo_class.add_method(
6868
"getFoo",
69+
Visibility::Public,
6970
|this: &mut Object<()>, _: &mut [Val]| -> phper::Result<Val> {
7071
let prop = this.get_property("foo");
7172
Ok(Val::new(prop.as_string_value()?))
@@ -74,6 +75,7 @@ pub fn get_module() -> Module {
7475
);
7576
foo_class.add_method(
7677
"setFoo",
78+
Visibility::Public,
7779
|this: &mut Object<()>, arguments: &mut [Val]| -> phper::Result<()> {
7880
this.set_property("foo", Val::new(arguments[0].as_string_value()?));
7981
Ok(())

examples/http-client/src/client.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ use crate::{
33
response::{ReadiedResponse, RESPONSE_CLASS_NAME},
44
};
55

6-
use phper::{classes::DynamicClass, functions::Argument, objects::Object};
6+
use phper::{
7+
classes::{DynamicClass, Visibility},
8+
functions::Argument,
9+
objects::Object,
10+
};
711
use reqwest::blocking::{Client, ClientBuilder};
812
use std::time::Duration;
913

@@ -19,6 +23,7 @@ pub fn make_client_class() -> DynamicClass<Client> {
1923

2024
class.add_method(
2125
"get",
26+
Visibility::Public,
2227
|this, arguments| {
2328
let url = arguments[0].as_string()?;
2429
let client = this.as_state();

examples/http-client/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use phper::{modules::Module, php_get_module};
55

66
pub mod client;
77
pub mod errors;
8+
pub mod request;
89
pub mod response;
910

1011
#[php_get_module]

examples/http-client/src/request.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
use phper::classes::DynamicClass;
2+
use reqwest::blocking::{Request, RequestBuilder};
3+
4+
pub const REQUEST_BUILDER_CLASS_NAME: &'static str = "HttpClient\\RequestBuilder";
5+
6+
pub fn make_request_builder_class() -> DynamicClass<Option<RequestBuilder>> {
7+
let mut class = DynamicClass::new_with_none(REQUEST_BUILDER_CLASS_NAME);
8+
9+
class
10+
}

examples/http-client/src/response.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use bytes::Bytes;
22
use indexmap::map::IndexMap;
3-
use phper::classes::DynamicClass;
3+
use phper::{
4+
classes::{DynamicClass, Visibility},
5+
objects::Object,
6+
};
47
use reqwest::{header::HeaderMap, StatusCode};
58
use std::{convert::Infallible, net::SocketAddr};
69

@@ -14,13 +17,12 @@ pub struct ReadiedResponse {
1417
}
1518

1619
pub fn make_response_class() -> DynamicClass<Option<ReadiedResponse>> {
17-
let mut class = DynamicClass::new_with_constructor(RESPONSE_CLASS_NAME, || {
18-
Ok::<Option<ReadiedResponse>, Infallible>(None)
19-
});
20+
let mut class = DynamicClass::new_with_none(RESPONSE_CLASS_NAME);
2021

2122
class.add_method(
2223
"body",
23-
|this, _arguments| {
24+
Visibility::Public,
25+
|this: &mut Object<Option<ReadiedResponse>>, _arguments| {
2426
let readied_response = this.as_state().as_ref().unwrap();
2527
let body: &[u8] = readied_response.body.as_ref();
2628
body.to_vec()
@@ -30,6 +32,7 @@ pub fn make_response_class() -> DynamicClass<Option<ReadiedResponse>> {
3032

3133
class.add_method(
3234
"status",
35+
Visibility::Public,
3336
|this, _arguments| {
3437
let readied_response = this.as_state().as_ref().unwrap();
3538
readied_response.status.as_u16() as i64
@@ -39,6 +42,7 @@ pub fn make_response_class() -> DynamicClass<Option<ReadiedResponse>> {
3942

4043
class.add_method(
4144
"headers",
45+
Visibility::Public,
4246
|this, _arguments| {
4347
let readied_response = this.as_state().as_ref().unwrap();
4448
let headers_map =

phper/src/classes.rs

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
11
//! Apis relate to [crate::sys::zend_class_entry].
22
3-
use crate::alloc::EBox;
3+
use crate::{
4+
alloc::EBox,
5+
errors::{ClassNotFoundError, StateTypeError, Throwable},
6+
functions::{Argument, Function, FunctionEntity, FunctionEntry, Method},
7+
objects::{ExtendObject, Object},
8+
sys::*,
9+
utils::ensure_end_with_zero,
10+
values::{SetVal, Val},
11+
};
12+
use dashmap::DashMap;
413
use once_cell::sync::OnceCell;
514
use std::{
6-
any::Any,
15+
any::{Any, TypeId},
716
convert::Infallible,
817
marker::PhantomData,
918
mem::{size_of, zeroed, ManuallyDrop},
@@ -15,17 +24,6 @@ use std::{
1524
},
1625
};
1726

18-
use crate::{
19-
errors::{ClassNotFoundError, StateTypeError, Throwable},
20-
functions::{Argument, FunctionEntity, FunctionEntry, Method},
21-
objects::{ExtendObject, Object},
22-
sys::*,
23-
utils::ensure_end_with_zero,
24-
values::{SetVal, Val},
25-
};
26-
use dashmap::DashMap;
27-
use std::any::TypeId;
28-
2927
pub trait Classifiable {
3028
fn state_constructor(&self) -> Box<StateConstructor<Box<dyn Any>>>;
3129
fn state_type_id(&self) -> TypeId;
@@ -37,7 +35,7 @@ pub trait Classifiable {
3735

3836
pub type StateConstructor<T> = dyn Fn() -> Result<T, Box<dyn Throwable>> + Send + Sync;
3937

40-
pub struct DynamicClass<T: Send + Sync + 'static> {
38+
pub struct DynamicClass<T: Send + 'static> {
4139
class_name: String,
4240
state_constructor: Arc<StateConstructor<T>>,
4341
pub(crate) method_entities: Vec<FunctionEntity>,
@@ -52,19 +50,19 @@ impl DynamicClass<()> {
5250
}
5351
}
5452

55-
impl<T: Default + Send + Sync + 'static> DynamicClass<T> {
53+
impl<T: Default + Send + 'static> DynamicClass<T> {
5654
pub fn new_with_default(class_name: impl ToString) -> Self {
5755
Self::new_with_constructor(class_name, || Ok::<_, Infallible>(Default::default()))
5856
}
5957
}
6058

61-
impl<T: Send + Sync + 'static> DynamicClass<Option<T>> {
59+
impl<T: Send + 'static> DynamicClass<Option<T>> {
6260
pub fn new_with_none(class_name: impl ToString) -> Self {
6361
Self::new_with_constructor(class_name, || Ok::<_, Infallible>(None))
6462
}
6563
}
6664

67-
impl<T: Send + Sync + 'static> DynamicClass<T> {
65+
impl<T: Send + 'static> DynamicClass<T> {
6866
pub fn new_with_constructor<F, E>(class_name: impl ToString, state_constructor: F) -> Self
6967
where
7068
F: Fn() -> Result<T, E> + Send + Sync + 'static,
@@ -85,15 +83,41 @@ impl<T: Send + Sync + 'static> DynamicClass<T> {
8583
dyn_class
8684
}
8785

88-
pub fn add_method<F, R>(&mut self, name: impl ToString, handler: F, arguments: Vec<Argument>)
89-
where
86+
pub fn add_method<F, R>(
87+
&mut self,
88+
name: impl ToString,
89+
vis: Visibility,
90+
handler: F,
91+
arguments: Vec<Argument>,
92+
) where
9093
F: Fn(&mut Object<T>, &mut [Val]) -> R + Send + Sync + 'static,
9194
R: SetVal + 'static,
9295
{
9396
self.method_entities.push(FunctionEntity::new(
9497
name,
9598
Box::new(Method::new(handler)),
9699
arguments,
100+
Some(vis),
101+
Some(false),
102+
));
103+
}
104+
105+
pub fn add_static_method<F, R>(
106+
&mut self,
107+
name: impl ToString,
108+
vis: Visibility,
109+
handler: F,
110+
arguments: Vec<Argument>,
111+
) where
112+
F: Fn(&mut [Val]) -> R + Send + Sync + 'static,
113+
R: SetVal + 'static,
114+
{
115+
self.method_entities.push(FunctionEntity::new(
116+
name,
117+
Box::new(Function::new(handler)),
118+
arguments,
119+
Some(vis),
120+
Some(true),
97121
));
98122
}
99123

@@ -108,7 +132,7 @@ impl<T: Send + Sync + 'static> DynamicClass<T> {
108132
}
109133
}
110134

111-
impl<T: Send + Sync> Classifiable for DynamicClass<T> {
135+
impl<T: Send> Classifiable for DynamicClass<T> {
112136
fn state_constructor(&self) -> Box<StateConstructor<Box<dyn Any>>> {
113137
let sc = self.state_constructor.clone();
114138
Box::new(move || sc().map(|x| Box::new(x) as _))

phper/src/functions.rs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use std::{mem::zeroed, os::raw::c_char};
44

55
use crate::{
6+
classes::Visibility,
67
errors::ArgumentCountError,
78
objects::Object,
89
strings::ZendString,
@@ -16,11 +17,21 @@ pub(crate) trait Callable {
1617
fn call(&self, execute_data: &mut ExecuteData, arguments: &mut [Val], return_value: &mut Val);
1718
}
1819

19-
pub(crate) struct Function<F, R>(pub(crate) F)
20+
pub(crate) struct Function<F, R>(F)
2021
where
2122
F: Fn(&mut [Val]) -> R + Send + Sync,
2223
R: SetVal;
2324

25+
impl<F, R> Function<F, R>
26+
where
27+
F: Fn(&mut [Val]) -> R + Send + Sync,
28+
R: SetVal,
29+
{
30+
pub fn new(f: F) -> Self {
31+
Self(f)
32+
}
33+
}
34+
2435
impl<F, R> Callable for Function<F, R>
2536
where
2637
F: Fn(&mut [Val]) -> R + Send + Sync,
@@ -84,23 +95,29 @@ pub struct FunctionEntity {
8495
pub(crate) name: String,
8596
pub(crate) handler: Box<dyn Callable>,
8697
pub(crate) arguments: Vec<Argument>,
98+
pub(crate) visibility: Option<Visibility>,
99+
pub(crate) r#static: Option<bool>,
87100
}
88101

89102
impl FunctionEntity {
90103
pub(crate) fn new(
91104
name: impl ToString,
92105
handler: Box<dyn Callable>,
93106
arguments: Vec<Argument>,
107+
visibility: Option<Visibility>,
108+
r#static: Option<bool>,
94109
) -> Self {
95110
let name = ensure_end_with_zero(name);
96111
FunctionEntity {
97112
name,
98113
handler,
99114
arguments,
115+
visibility,
116+
r#static,
100117
}
101118
}
102119

103-
// Leak memory
120+
/// Will leak memory
104121
pub(crate) unsafe fn entry(&self) -> zend_function_entry {
105122
let mut infos = Vec::new();
106123

@@ -125,12 +142,18 @@ impl FunctionEntity {
125142
let last_arg_info: zend_internal_arg_info = translator.internal_arg_info;
126143
infos.push(last_arg_info);
127144

145+
let flags = self.visibility.map(|v| v as u32).unwrap_or_default()
146+
| self
147+
.r#static
148+
.and_then(|v| if v { Some(ZEND_ACC_STATIC) } else { None })
149+
.unwrap_or_default();
150+
128151
zend_function_entry {
129152
fname: self.name.as_ptr().cast(),
130153
handler: Some(invoke),
131154
arg_info: Box::into_raw(infos.into_boxed_slice()).cast(),
132155
num_args: self.arguments.len() as u32,
133-
flags: 0,
156+
flags,
134157
}
135158
}
136159
}

phper/src/modules.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,8 +211,10 @@ impl Module {
211211
{
212212
self.function_entities.push(FunctionEntity::new(
213213
name,
214-
Box::new(Function(handler)),
214+
Box::new(Function::new(handler)),
215215
arguments,
216+
None,
217+
None,
216218
));
217219
}
218220

tests/integration/src/classes.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
use phper::{classes::DynamicClass, modules::Module};
2+
3+
pub fn integrate(module: &mut Module) {
4+
integrate_a(module);
5+
}
6+
7+
fn integrate_a(module: &mut Module) {
8+
// let class = DynamicClass::new_with_constructor("IntegrationTest\\A", ||);
9+
}

tests/integration/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
mod arguments;
44
mod arrays;
5+
mod classes;
56
mod objects;
67
mod strings;
78
mod values;
@@ -18,6 +19,7 @@ pub fn get_module() -> Module {
1819

1920
arguments::integrate(&mut module);
2021
arrays::integrate(&mut module);
22+
classes::integrate(&mut module);
2123
objects::integrate(&mut module);
2224
values::integrate(&mut module);
2325
strings::integrate(&mut module);

0 commit comments

Comments
 (0)