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