Skip to content

Commit 4e2cc46

Browse files
committed
Add IniBuilder
1 parent 96555c4 commit 4e2cc46

File tree

4 files changed

+236
-1
lines changed

4 files changed

+236
-1
lines changed

allowed_bindings.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,5 +311,10 @@ bind! {
311311
php_module_shutdown,
312312
php_request_startup,
313313
php_request_shutdown,
314-
instanceof_function_slow
314+
instanceof_function_slow,
315+
php_ini_builder,
316+
php_ini_builder_prepend,
317+
php_ini_builder_unquoted,
318+
php_ini_builder_quoted,
319+
php_ini_builder_define
315320
}

src/builders/ini.rs

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
use std::ops::Deref;
2+
use std::ffi::{c_char, CStr, CString, NulError};
3+
use crate::ffi::{
4+
php_ini_builder,
5+
php_ini_builder_prepend,
6+
php_ini_builder_unquoted,
7+
php_ini_builder_quoted,
8+
php_ini_builder_define
9+
};
10+
11+
// Helpful for CString which only needs to live until immediately after C call.
12+
struct CStringScope(*mut c_char);
13+
14+
impl CStringScope {
15+
fn new<T: Into<Vec<u8>>>(string: T) -> Result<Self, NulError> {
16+
Ok(Self(CString::new(string)?.into_raw()))
17+
}
18+
}
19+
20+
impl Deref for CStringScope {
21+
type Target = *mut c_char;
22+
23+
fn deref(&self) -> &Self::Target {
24+
&self.0
25+
}
26+
}
27+
28+
impl Drop for CStringScope {
29+
fn drop(&mut self) {
30+
// Convert back to a CString to ensure it gets dropped
31+
drop(unsafe { CString::from_raw(self.0) })
32+
}
33+
}
34+
35+
/// A builder for creating INI configurations.
36+
pub type IniBuilder = php_ini_builder;
37+
38+
impl IniBuilder {
39+
/// Creates a new INI builder.
40+
///
41+
/// # Examples
42+
///
43+
/// ```
44+
/// # use ext_php_rs::builders::IniBuilder;
45+
/// let mut builder = IniBuilder::new();
46+
/// ```
47+
pub fn new() -> IniBuilder {
48+
IniBuilder {
49+
value: std::ptr::null_mut(),
50+
length: 0,
51+
}
52+
}
53+
54+
/// Appends a value to the INI builder.
55+
///
56+
/// # Arguments
57+
///
58+
/// * `value` - The value to append.
59+
///
60+
/// # Examples
61+
///
62+
/// ```
63+
/// # use ext_php_rs::builders::IniBuilder;
64+
/// let mut builder = IniBuilder::new();
65+
/// builder.prepend("foo=bar");
66+
/// ```
67+
pub fn prepend<V: AsRef<str>>(&mut self, value: V) -> Result<(), NulError> {
68+
let value = value.as_ref();
69+
let raw = CStringScope::new(value)?;
70+
71+
unsafe {
72+
php_ini_builder_prepend(self, *raw, value.len());
73+
}
74+
75+
Ok(())
76+
}
77+
78+
/// Appends an unquoted name-value pair to the INI builder.
79+
///
80+
/// # Arguments
81+
///
82+
/// * `name` - The name of the pair.
83+
/// * `value` - The value of the pair.
84+
///
85+
/// # Examples
86+
///
87+
/// ```
88+
/// # use ext_php_rs::builders::IniBuilder;
89+
/// let mut builder = IniBuilder::new();
90+
/// builder.unquoted("foo", "bar");
91+
/// ```
92+
pub fn unquoted<N, V>(&mut self, name: N, value: V) -> Result<(), NulError>
93+
where
94+
N: AsRef<str>,
95+
V: AsRef<str>,
96+
{
97+
let name = name.as_ref();
98+
let value = value.as_ref();
99+
100+
let raw_name = CStringScope::new(name)?;
101+
let raw_value = CStringScope::new(value)?;
102+
103+
unsafe {
104+
php_ini_builder_unquoted(self, *raw_name, name.len(), *raw_value, value.len());
105+
}
106+
107+
Ok(())
108+
}
109+
110+
/// Appends a quoted name-value pair to the INI builder.
111+
///
112+
/// # Arguments
113+
///
114+
/// * `name` - The name of the pair.
115+
/// * `value` - The value of the pair.
116+
///
117+
/// # Examples
118+
///
119+
/// ```
120+
/// # use ext_php_rs::builders::IniBuilder;
121+
/// let mut builder = IniBuilder::new();
122+
/// builder.quoted("foo", "bar");
123+
/// ```
124+
pub fn quoted<N, V>(&mut self, name: N, value: V) -> Result<(), NulError>
125+
where
126+
N: AsRef<str>,
127+
V: AsRef<str>,
128+
{
129+
let name = name.as_ref();
130+
let value = value.as_ref();
131+
132+
let raw_name = CStringScope::new(name)?;
133+
let raw_value = CStringScope::new(value)?;
134+
135+
unsafe {
136+
php_ini_builder_quoted(self, *raw_name, name.len(), *raw_value, value.len());
137+
}
138+
139+
Ok(())
140+
}
141+
142+
/// Defines a value in the INI builder.
143+
///
144+
/// # Arguments
145+
///
146+
/// * `value` - The value to define.
147+
///
148+
/// # Examples
149+
///
150+
/// ```
151+
/// # use ext_php_rs::builders::IniBuilder;
152+
/// let mut builder = IniBuilder::new();
153+
/// builder.define("foo=bar");
154+
/// ```
155+
pub fn define<V: AsRef<str>>(&mut self, value: V) -> Result<(), NulError> {
156+
let value = value.as_ref();
157+
let raw = CStringScope::new(value)?;
158+
159+
unsafe {
160+
php_ini_builder_define(self, *raw);
161+
}
162+
163+
Ok(())
164+
}
165+
166+
/// Finishes building the INI configuration.
167+
///
168+
/// # Examples
169+
///
170+
/// ```
171+
/// # use ext_php_rs::builders::IniBuilder;
172+
/// let mut builder = IniBuilder::new();
173+
/// let ini = builder.finish();
174+
/// ```
175+
pub fn finish(&mut self) -> *mut i8 {
176+
if self.value.is_null() {
177+
return std::ptr::null_mut();
178+
}
179+
180+
unsafe { CStr::from_ptr(self.value) }.as_ptr() as *mut c_char
181+
}
182+
}
183+
184+
#[cfg(test)]
185+
mod tests {
186+
use super::*;
187+
188+
#[test]
189+
fn test_ini_builder_prepend() {
190+
let mut builder = IniBuilder::new();
191+
builder.prepend("foo=bar").unwrap();
192+
193+
let ini = builder.finish();
194+
assert!(!ini.is_null());
195+
assert_eq!(unsafe { CStr::from_ptr(ini) }.to_str().unwrap(), "foo=bar");
196+
}
197+
198+
#[test]
199+
fn test_ini_builder_unquoted() {
200+
let mut builder = IniBuilder::new();
201+
builder.unquoted("baz", "qux").unwrap();
202+
203+
let ini = builder.finish();
204+
assert!(!ini.is_null());
205+
assert_eq!(unsafe { CStr::from_ptr(ini) }.to_str().unwrap(), "baz=qux\n");
206+
}
207+
208+
#[test]
209+
fn test_ini_builder_quoted() {
210+
let mut builder = IniBuilder::new();
211+
builder.quoted("quux", "corge").unwrap();
212+
213+
let ini = builder.finish();
214+
assert!(!ini.is_null());
215+
assert_eq!(unsafe { CStr::from_ptr(ini) }.to_str().unwrap(), "quux=\"corge\"\n");
216+
}
217+
218+
#[test]
219+
fn test_ini_builder_define() {
220+
let mut builder = IniBuilder::new();
221+
builder.define("grault=garply").unwrap();
222+
223+
let ini = builder.finish();
224+
assert!(!ini.is_null());
225+
assert_eq!(unsafe { CStr::from_ptr(ini) }.to_str().unwrap(), "grault=garply\n");
226+
}
227+
}

src/builders/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
44
mod class;
55
mod function;
6+
mod ini;
67
mod module;
78
#[cfg(feature = "embed")]
89
mod sapi;
910

1011
pub use class::ClassBuilder;
1112
pub use function::FunctionBuilder;
13+
pub use ini::{IniBuilder};
1214
pub use module::{ModuleBuilder, ModuleStartup};
1315
#[cfg(feature = "embed")]
1416
pub use sapi::SapiBuilder;

src/wrapper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "zend_inheritance.h"
2424
#include "zend_interfaces.h"
2525
#include "php_variables.h"
26+
#include "php_ini_builder.h"
2627
#include "zend_ini.h"
2728
#include "main/SAPI.h"
2829

0 commit comments

Comments
 (0)