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