Skip to content

Commit 472e26e

Browse files
Added ability to register constants (#22)
1 parent 349d497 commit 472e26e

File tree

6 files changed

+196
-14
lines changed

6 files changed

+196
-14
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ This is not a set feature list, but these are the features on my roadmap. Create
1414
- [x] Class methods
1515
- [ ] Class properties
1616
- [x] Class constants
17-
- [ ] Module constants
17+
- [x] Module constants
1818
- [x] Calling PHP functions
1919

2020
## Requirements

example/skel/src/lib.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use ext_php_rs::{
33
php::{
44
args::{Arg, ArgParser},
55
class::{ClassBuilder, ClassEntry},
6+
constants::IntoConst,
67
enums::DataType,
78
exceptions::throw,
89
execution_data::ExecutionData,
@@ -79,7 +80,7 @@ impl Default for Test {
7980
}
8081

8182
#[no_mangle]
82-
pub extern "C" fn module_init(_type: i32, _module_number: i32) -> i32 {
83+
pub extern "C" fn module_init(_type: i32, module_number: i32) -> i32 {
8384
// object_handlers_init!(Test);
8485

8586
ClassBuilder::new("TestClass")
@@ -106,6 +107,9 @@ pub extern "C" fn module_init(_type: i32, _module_number: i32) -> i32 {
106107
.object_override::<Test>()
107108
.build();
108109

110+
"Test constant".register_constant("SKEL_TEST_CONST", module_number);
111+
1234.register_constant("SKEL_TEST_LONG_CONST", module_number);
112+
109113
0
110114
}
111115

example/skel/test.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
<?php
22

3+
var_dump(SKEL_TEST_CONST, SKEL_TEST_LONG_CONST);
4+
die;
5+
36
$x = new TestClass();
47

58
skeleton_version(1, 2);

src/php/constants.rs

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
use super::flags::GlobalConstantFlags;
2+
use crate::{
3+
bindings::{
4+
zend_register_bool_constant, zend_register_double_constant, zend_register_long_constant,
5+
zend_register_string_constant,
6+
},
7+
functions::c_str,
8+
};
9+
10+
pub trait IntoConst: Sized {
11+
/// Registers a global module constant in PHP, with the value as the content of self.
12+
/// This function _must_ be called in the module startup function, which is called after
13+
/// the module is initialized. The second parameter of the startup function will be the
14+
/// module number. By default, the case-insensitive and persistent flags are set when
15+
/// registering the constant.
16+
///
17+
/// # Parameters
18+
///
19+
/// * `name` - The name of the constant.
20+
/// * `module_number` - The module number that we are registering the constant under.
21+
///
22+
/// # Examples
23+
///
24+
/// ```no_run
25+
/// use ext_php_rs::php::{constants::IntoConst, flags::ZendResult};
26+
///
27+
/// pub extern "C" fn startup_function(_type: i32, module_number: i32) -> i32 {
28+
/// 5.register_constant("MY_CONST_NAME", module_number); // MY_CONST_NAME == 5
29+
/// "Hello, world!".register_constant("STRING_CONSTANT", module_number); // STRING_CONSTANT == "Hello, world!"
30+
/// 0
31+
/// }
32+
/// ```
33+
fn register_constant<N: AsRef<str>>(&self, name: N, module_number: i32) {
34+
self.register_constant_flags(
35+
name,
36+
module_number,
37+
GlobalConstantFlags::CaseSensitive | GlobalConstantFlags::Persistent,
38+
)
39+
}
40+
41+
/// Registers a global module constant in PHP, with the value as the content of self.
42+
/// This function _must_ be called in the module startup function, which is called after
43+
/// the module is initialized. The second parameter of the startup function will be the
44+
/// module number. This function allows you to pass any extra flags in if you require.
45+
/// Note that the case-sensitive and persistent flags *are not* set when you use this function,
46+
/// you must set these yourself.
47+
///
48+
/// # Parameters
49+
///
50+
/// * `name` - The name of the constant.
51+
/// * `module_number` - The module number that we are registering the constant under.
52+
/// * `flags` - Flags to register the constant with.
53+
///
54+
/// # Examples
55+
///
56+
/// ```no_run
57+
/// use ext_php_rs::php::{constants::IntoConst, flags::{GlobalConstantFlags, ZendResult}};
58+
///
59+
/// pub extern "C" fn startup_function(_type: i32, module_number: i32) -> i32 {
60+
/// 42.register_constant_flags("MY_CONST_NAME", module_number, GlobalConstantFlags::Persistent | GlobalConstantFlags::Deprecated);
61+
/// 0
62+
/// }
63+
/// ```
64+
fn register_constant_flags<N: AsRef<str>>(
65+
&self,
66+
name: N,
67+
module_number: i32,
68+
flags: GlobalConstantFlags,
69+
);
70+
}
71+
72+
impl IntoConst for String {
73+
fn register_constant_flags<N: AsRef<str>>(
74+
&self,
75+
name: N,
76+
module_number: i32,
77+
flags: GlobalConstantFlags,
78+
) {
79+
self.as_str()
80+
.register_constant_flags(name, module_number, flags);
81+
}
82+
}
83+
84+
impl IntoConst for &str {
85+
fn register_constant_flags<N: AsRef<str>>(
86+
&self,
87+
name: N,
88+
module_number: i32,
89+
flags: GlobalConstantFlags,
90+
) {
91+
let name = name.as_ref();
92+
unsafe {
93+
zend_register_string_constant(
94+
c_str(name),
95+
name.len() as _,
96+
c_str(self),
97+
flags.bits() as _,
98+
module_number,
99+
)
100+
};
101+
}
102+
}
103+
104+
impl IntoConst for bool {
105+
fn register_constant_flags<N: AsRef<str>>(
106+
&self,
107+
name: N,
108+
module_number: i32,
109+
flags: GlobalConstantFlags,
110+
) {
111+
let name = name.as_ref();
112+
unsafe {
113+
zend_register_bool_constant(
114+
c_str(name),
115+
name.len() as _,
116+
*self,
117+
flags.bits() as _,
118+
module_number,
119+
)
120+
}
121+
}
122+
}
123+
124+
/// Implements the `IntoConst` trait for a given number type using a given function.
125+
#[macro_use]
126+
macro_rules! into_const_num {
127+
($type: ty, $fn: expr) => {
128+
impl IntoConst for $type {
129+
fn register_constant_flags<N: AsRef<str>>(
130+
&self,
131+
name: N,
132+
module_number: i32,
133+
flags: GlobalConstantFlags,
134+
) {
135+
let name = name.as_ref();
136+
unsafe {
137+
$fn(
138+
c_str(name),
139+
name.len() as _,
140+
*self as _,
141+
flags.bits() as _,
142+
module_number,
143+
)
144+
};
145+
}
146+
}
147+
};
148+
}
149+
150+
into_const_num!(i8, zend_register_long_constant);
151+
into_const_num!(i16, zend_register_long_constant);
152+
into_const_num!(i32, zend_register_long_constant);
153+
into_const_num!(i64, zend_register_long_constant);
154+
into_const_num!(f32, zend_register_double_constant);
155+
into_const_num!(f64, zend_register_double_constant);

src/php/flags.rs

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,19 @@
33
use bitflags::bitflags;
44

55
use crate::bindings::{
6-
ZEND_ACC_ABSTRACT, ZEND_ACC_ANON_CLASS, ZEND_ACC_CALL_VIA_TRAMPOLINE, ZEND_ACC_CHANGED,
7-
ZEND_ACC_CLOSURE, ZEND_ACC_CONSTANTS_UPDATED, ZEND_ACC_CTOR, ZEND_ACC_DEPRECATED,
8-
ZEND_ACC_DONE_PASS_TWO, ZEND_ACC_EARLY_BINDING, ZEND_ACC_FAKE_CLOSURE, ZEND_ACC_FINAL,
9-
ZEND_ACC_GENERATOR, ZEND_ACC_HAS_FINALLY_BLOCK, ZEND_ACC_HAS_RETURN_TYPE,
10-
ZEND_ACC_HAS_TYPE_HINTS, ZEND_ACC_HAS_UNLINKED_USES, ZEND_ACC_HEAP_RT_CACHE,
11-
ZEND_ACC_IMMUTABLE, ZEND_ACC_IMPLICIT_ABSTRACT_CLASS, ZEND_ACC_INTERFACE, ZEND_ACC_LINKED,
12-
ZEND_ACC_NEARLY_LINKED, ZEND_ACC_NEVER_CACHE, ZEND_ACC_NO_DYNAMIC_PROPERTIES,
13-
ZEND_ACC_PRELOADED, ZEND_ACC_PRIVATE, ZEND_ACC_PROMOTED, ZEND_ACC_PROPERTY_TYPES_RESOLVED,
14-
ZEND_ACC_PROTECTED, ZEND_ACC_PUBLIC, ZEND_ACC_RESOLVED_INTERFACES, ZEND_ACC_RESOLVED_PARENT,
15-
ZEND_ACC_RETURN_REFERENCE, ZEND_ACC_REUSE_GET_ITERATOR, ZEND_ACC_STATIC, ZEND_ACC_STRICT_TYPES,
16-
ZEND_ACC_TOP_LEVEL, ZEND_ACC_TRAIT, ZEND_ACC_TRAIT_CLONE, ZEND_ACC_UNRESOLVED_VARIANCE,
17-
ZEND_ACC_USES_THIS, ZEND_ACC_USE_GUARDS, ZEND_ACC_VARIADIC, ZEND_HAS_STATIC_IN_METHODS,
6+
CONST_CS, CONST_DEPRECATED, CONST_NO_FILE_CACHE, CONST_PERSISTENT, ZEND_ACC_ABSTRACT,
7+
ZEND_ACC_ANON_CLASS, ZEND_ACC_CALL_VIA_TRAMPOLINE, ZEND_ACC_CHANGED, ZEND_ACC_CLOSURE,
8+
ZEND_ACC_CONSTANTS_UPDATED, ZEND_ACC_CTOR, ZEND_ACC_DEPRECATED, ZEND_ACC_DONE_PASS_TWO,
9+
ZEND_ACC_EARLY_BINDING, ZEND_ACC_FAKE_CLOSURE, ZEND_ACC_FINAL, ZEND_ACC_GENERATOR,
10+
ZEND_ACC_HAS_FINALLY_BLOCK, ZEND_ACC_HAS_RETURN_TYPE, ZEND_ACC_HAS_TYPE_HINTS,
11+
ZEND_ACC_HAS_UNLINKED_USES, ZEND_ACC_HEAP_RT_CACHE, ZEND_ACC_IMMUTABLE,
12+
ZEND_ACC_IMPLICIT_ABSTRACT_CLASS, ZEND_ACC_INTERFACE, ZEND_ACC_LINKED, ZEND_ACC_NEARLY_LINKED,
13+
ZEND_ACC_NEVER_CACHE, ZEND_ACC_NO_DYNAMIC_PROPERTIES, ZEND_ACC_PRELOADED, ZEND_ACC_PRIVATE,
14+
ZEND_ACC_PROMOTED, ZEND_ACC_PROPERTY_TYPES_RESOLVED, ZEND_ACC_PROTECTED, ZEND_ACC_PUBLIC,
15+
ZEND_ACC_RESOLVED_INTERFACES, ZEND_ACC_RESOLVED_PARENT, ZEND_ACC_RETURN_REFERENCE,
16+
ZEND_ACC_REUSE_GET_ITERATOR, ZEND_ACC_STATIC, ZEND_ACC_STRICT_TYPES, ZEND_ACC_TOP_LEVEL,
17+
ZEND_ACC_TRAIT, ZEND_ACC_TRAIT_CLONE, ZEND_ACC_UNRESOLVED_VARIANCE, ZEND_ACC_USES_THIS,
18+
ZEND_ACC_USE_GUARDS, ZEND_ACC_VARIADIC, ZEND_HAS_STATIC_IN_METHODS,
1819
};
1920

2021
bitflags! {
@@ -102,3 +103,21 @@ bitflags! {
102103
const Promoted = ZEND_ACC_PROMOTED;
103104
}
104105
}
106+
107+
bitflags! {
108+
/// Flags for building module global constants.
109+
pub struct GlobalConstantFlags: u32 {
110+
const CaseSensitive = CONST_CS;
111+
const Persistent = CONST_PERSISTENT;
112+
const NoFileCache = CONST_NO_FILE_CACHE;
113+
const Deprecated = CONST_DEPRECATED;
114+
}
115+
}
116+
117+
bitflags! {
118+
/// Represents the result of a function.
119+
pub struct ZendResult: i32 {
120+
const Success = 0;
121+
const Failure = -1;
122+
}
123+
}

src/php/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
pub mod args;
44
pub mod class;
5+
pub mod constants;
56
pub mod enums;
67
pub mod exceptions;
78
pub mod execution_data;

0 commit comments

Comments
 (0)