ext_php_rs/zend/
ini_entry_def.rs

1//! Builder for creating inis and methods in PHP.
2//! See <https://www.phpinternalsbook.com/php7/extensions_design/ini_settings.html> for details.
3
4use std::{ffi::CString, os::raw::c_char, ptr};
5
6use crate::{ffi::zend_ini_entry_def, ffi::zend_register_ini_entries, flags::IniEntryPermission};
7
8/// A Zend ini entry definition.
9///
10/// To register ini definitions for extensions, the [`IniEntryDef`] builder
11/// should be used. Ini entries should be registered in your module's
12/// `startup_function` via `IniEntryDef::register(Vec<IniEntryDef>)`.
13pub type IniEntryDef = zend_ini_entry_def;
14
15impl IniEntryDef {
16    /// Creates a new ini entry definition.
17    ///
18    /// # Panics
19    ///
20    /// * If the name or value cannot be converted to a C string
21    /// * If the name or value length is > `65_535`
22    /// * If the permission bits are invalid
23    #[must_use]
24    pub fn new(name: String, default_value: String, permission: &IniEntryPermission) -> Self {
25        let mut template = Self::end();
26        let name = CString::new(name).expect("Unable to create CString from name");
27        let value = CString::new(default_value).expect("Unable to create CString from value");
28        template.name_length = name
29            .as_bytes()
30            .len()
31            .try_into()
32            .expect("Invalid name length");
33        template.name = name.into_raw();
34        template.value_length = value
35            .as_bytes()
36            .len()
37            .try_into()
38            .expect("Invalid value length");
39        template.value = value.into_raw();
40        // FIXME: Double assignment of modifiable
41        template.modifiable = IniEntryPermission::PerDir
42            .bits()
43            .try_into()
44            .expect("Invalid permission bits");
45        template.modifiable = permission
46            .bits()
47            .try_into()
48            .expect("Invalid permission bits");
49        template
50    }
51
52    /// Returns an empty ini entry def, signifying the end of a ini list.
53    #[must_use]
54    pub fn end() -> Self {
55        Self {
56            name: ptr::null::<c_char>(),
57            on_modify: None,
58            mh_arg1: std::ptr::null_mut(),
59            mh_arg2: std::ptr::null_mut(),
60            mh_arg3: std::ptr::null_mut(),
61            value: std::ptr::null_mut(),
62            displayer: None,
63            modifiable: 0,
64            value_length: 0,
65            name_length: 0,
66        }
67    }
68
69    /// Converts the ini entry into a raw and pointer, releasing it to the
70    /// C world.
71    #[must_use]
72    pub fn into_raw(self) -> *mut Self {
73        Box::into_raw(Box::new(self))
74    }
75
76    /// Registers a list of ini entries.
77    pub fn register(mut entries: Vec<Self>, module_number: i32) {
78        entries.push(Self::end());
79        let entries = Box::into_raw(entries.into_boxed_slice()) as *const Self;
80
81        unsafe { zend_register_ini_entries(entries, module_number) };
82    }
83}