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);