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