Skip to content

Commit 292dd4f

Browse files
committed
Add some ZendString methods.
1 parent 4efb8ed commit 292dd4f

File tree

10 files changed

+105
-23
lines changed

10 files changed

+105
-23
lines changed

phper/src/cmd.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ struct InstallCommand {}
2828
/// Make.
2929
///
3030
/// # Examples
31-
/// ```
31+
///
32+
/// ```no_run
3233
/// use phper::cmd::make;
3334
///
3435
/// fn main() {

phper/src/objects.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ impl Object {
6060
&self.inner as *const _ as *mut _,
6161
name.as_ptr().cast(),
6262
name.len(),
63-
false.into(),
63+
true.into(),
6464
null_mut(),
6565
)
6666
}
@@ -73,7 +73,7 @@ impl Object {
7373
&mut zv,
7474
name.as_ptr().cast(),
7575
name.len(),
76-
false.into(),
76+
true.into(),
7777
null_mut(),
7878
)
7979
}

phper/src/strings.rs

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
use crate::{alloc::EBox, sys::*};
2-
use std::{slice::from_raw_parts, str::Utf8Error};
1+
use crate::{
2+
alloc::{EAllocatable, EBox},
3+
sys::*,
4+
};
5+
use std::{ffi::CString, os::raw::c_char, slice::from_raw_parts, str, str::Utf8Error};
36

47
/// Wrapper of [crate::sys::zend_string].
58
#[repr(transparent)]
@@ -8,11 +11,18 @@ pub struct ZendString {
811
}
912

1013
impl ZendString {
11-
// TODO Remove dead_code tag
12-
#[allow(dead_code)]
13-
pub(crate) unsafe fn from_mut_ptr<'a>(ptr: *mut zend_string) -> &'a mut Self {
14-
let ptr = ptr as *mut Self;
15-
ptr.as_mut().expect("ptr shouldn't be null")
14+
pub fn new(s: &str) -> EBox<Self> {
15+
unsafe {
16+
let ptr = phper_zend_string_init(s.as_ptr().cast(), s.len(), false.into()).cast();
17+
EBox::from_raw(ptr)
18+
}
19+
}
20+
21+
pub(crate) fn from_ptr<'a>(ptr: *mut zend_string) -> &'a Self {
22+
unsafe {
23+
let ptr = ptr as *mut Self;
24+
ptr.as_ref().unwrap()
25+
}
1626
}
1727

1828
pub fn as_ptr(&self) -> *const zend_string {
@@ -22,4 +32,29 @@ impl ZendString {
2232
pub fn as_mut_ptr(&mut self) -> *mut zend_string {
2333
&mut self.inner
2434
}
35+
36+
pub fn as_string(&self) -> Result<String, Utf8Error> {
37+
unsafe {
38+
let buf = from_raw_parts(
39+
&self.inner.val as *const c_char as *const u8,
40+
self.inner.len,
41+
);
42+
let string = str::from_utf8(buf)?.to_string();
43+
Ok(string)
44+
}
45+
}
46+
}
47+
48+
impl EAllocatable for ZendString {
49+
fn free(ptr: *mut Self) {
50+
unsafe {
51+
phper_zend_string_release(ptr.cast());
52+
}
53+
}
54+
}
55+
56+
impl Drop for ZendString {
57+
fn drop(&mut self) {
58+
unreachable!("Allocation on the stack is not allowed")
59+
}
2560
}

phper/src/values.rs

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::{
66
errors::{Throwable, TypeError},
77
functions::ZendFunction,
88
objects::Object,
9+
strings::ZendString,
910
sys::*,
1011
types::{get_type_by_const, Type},
1112
utils::ensure_end_with_zero,
@@ -162,10 +163,8 @@ impl Val {
162163
pub fn as_string(&self) -> crate::Result<String> {
163164
if self.get_type().is_string() {
164165
unsafe {
165-
let s = self.inner.value.str;
166-
let buf = from_raw_parts(&(*s).val as *const c_char as *const u8, (*s).len);
167-
let string = str::from_utf8(buf)?.to_string();
168-
Ok(string)
166+
let zs = ZendString::from_ptr(self.inner.value.str);
167+
Ok(zs.as_string()?)
169168
}
170169
} else {
171170
Err(self.must_be_type_error("string").into())
@@ -175,10 +174,8 @@ impl Val {
175174
pub fn as_string_value(&self) -> Result<String, Utf8Error> {
176175
unsafe {
177176
let s = phper_zval_get_string(&self.inner as *const _ as *mut _);
178-
let buf = from_raw_parts(&(*s).val as *const c_char as *const u8, (*s).len);
179-
let result = str::from_utf8(buf).map(ToString::to_string);
180-
phper_zend_string_release(s);
181-
result
177+
let zs = EBox::from_raw(s as *mut ZendString);
178+
zs.as_string()
182179
}
183180
}
184181

@@ -218,12 +215,8 @@ impl Val {
218215
Err(e) => e.into(),
219216
}
220217
}
221-
}
222-
223-
impl EAllocatable for Val {}
224218

225-
impl Drop for Val {
226-
fn drop(&mut self) {
219+
fn drop_me(&mut self) {
227220
let t = self.get_type();
228221
unsafe {
229222
if t.is_string() {
@@ -237,6 +230,21 @@ impl Drop for Val {
237230
}
238231
}
239232

233+
impl EAllocatable for Val {
234+
fn free(ptr: *mut Self) {
235+
unsafe {
236+
ptr.as_mut().unwrap().drop_me();
237+
_efree(ptr.cast());
238+
}
239+
}
240+
}
241+
242+
impl Drop for Val {
243+
fn drop(&mut self) {
244+
self.drop_me();
245+
}
246+
}
247+
240248
/// The trait for setting the value of [Val], mainly as the return value of
241249
/// [crate::functions::Function] and [crate::functions::Method], and initializer of [Val].
242250
pub trait SetVal {

tests/integration/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
mod arguments;
44
mod arrays;
55
mod objects;
6+
mod strings;
67
mod values;
78

89
use phper::{modules::Module, php_get_module};
@@ -19,6 +20,7 @@ pub fn get_module() -> Module {
1920
arrays::integrate(&mut module);
2021
objects::integrate(&mut module);
2122
values::integrate(&mut module);
23+
strings::integrate(&mut module);
2224

2325
module
2426
}

tests/integration/src/objects.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,22 @@ pub fn integrate(module: &mut Module) {
66
|arguments: &mut [Val]| -> phper::Result<()> {
77
let o = Object::new_by_std_class();
88
drop(o);
9+
Ok(())
10+
},
11+
vec![],
12+
);
13+
14+
module.add_function(
15+
"integrate_objects_get_set",
16+
|arguments: &mut [Val]| -> phper::Result<()> {
17+
let mut o = Object::new_by_std_class();
18+
19+
o.set_property("foo", Val::new("bar"));
20+
let foo = o.get_property("foo");
21+
assert_eq!(foo.as_string()?, "bar");
22+
23+
let not_exists = o.get_property("no_exists");
24+
not_exists.as_null()?;
925

1026
Ok(())
1127
},

tests/integration/src/strings.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
use phper::{modules::Module, strings::ZendString, values::Val};
2+
3+
pub fn integrate(module: &mut Module) {
4+
module.add_function(
5+
"integrate_strings_as_string",
6+
|arguments: &mut [Val]| -> phper::Result<()> {
7+
let zs = ZendString::new("hello");
8+
assert_eq!(zs.as_string()?, "hello");
9+
Ok(())
10+
},
11+
vec![],
12+
);
13+
}

tests/integration/tests/integration.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ fn test_php() {
1313
&tests_php_dir.join("arguments.php"),
1414
&tests_php_dir.join("arrays.php"),
1515
&tests_php_dir.join("objects.php"),
16+
&tests_php_dir.join("strings.php"),
1617
&tests_php_dir.join("values.php"),
1718
],
1819
);

tests/integration/tests/php/objects.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
require_once __DIR__ . '/_common.php';
44

55
integrate_objects_new_drop();
6+
integrate_objects_get_set();
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?php
2+
3+
require_once __DIR__ . '/_common.php';
4+
5+
integrate_strings_as_string();

0 commit comments

Comments
 (0)