mirror of
https://github.com/icewind1991/ivory.git
synced 2026-06-03 18:54:07 +02:00
string return value casting
also fix for argument strings >8 bytes
This commit is contained in:
parent
938558c87a
commit
db1ce0dcd4
2 changed files with 61 additions and 8 deletions
|
|
@ -3,8 +3,7 @@ use std::fmt;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::intrinsics::transmute;
|
use std::intrinsics::transmute;
|
||||||
use std::mem::size_of;
|
use std::mem::{forget, size_of};
|
||||||
use std::os::raw::c_char;
|
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
use ivory_sys::*;
|
use ivory_sys::*;
|
||||||
|
|
@ -60,13 +59,53 @@ impl Iterator for IntoArgIterator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn zend_str_as_string(str: &zend_string) -> String {
|
unsafe fn zend_str_as_string(string: *const zend_string) -> String {
|
||||||
let len = str.len;
|
let len = (*string).len;
|
||||||
let base: *const c_char = &str.val[0];
|
let base: *const u8 = transmute(string);
|
||||||
let slice: &[u8] = std::slice::from_raw_parts(base as *const u8, len);
|
let str_start = base.add(size_of::<ZendStringHeader>());
|
||||||
|
|
||||||
|
let slice: &[u8] = std::slice::from_raw_parts(str_start, len);
|
||||||
str::from_utf8_unchecked(slice).to_string()
|
str::from_utf8_unchecked(slice).to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct ZendStringHeader {
|
||||||
|
gc: zend_refcounted_h,
|
||||||
|
h: zend_ulong,
|
||||||
|
len: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn string_into_zend_str(string: String) -> *mut zend_string {
|
||||||
|
let len = string.len();
|
||||||
|
|
||||||
|
let mut mem: Vec<u8> = Vec::with_capacity(len + size_of::<ZendStringHeader>());
|
||||||
|
|
||||||
|
let header = ZendStringHeader {
|
||||||
|
gc: zend_refcounted_h {
|
||||||
|
refcount: 1, // ?? no clue actually,
|
||||||
|
u: _zend_refcounted_h__bindgen_ty_1 { type_info: 0 },
|
||||||
|
},
|
||||||
|
h: 0,
|
||||||
|
len,
|
||||||
|
};
|
||||||
|
let header_bytes: [u8; size_of::<ZendStringHeader>()] = unsafe { transmute(header) };
|
||||||
|
mem.extend_from_slice(&header_bytes);
|
||||||
|
|
||||||
|
let bytes = string.into_bytes();
|
||||||
|
|
||||||
|
mem.extend_from_slice(bytes.as_slice());
|
||||||
|
|
||||||
|
let ptr = mem.as_ptr();
|
||||||
|
|
||||||
|
// rust shouldn't deallocate the data
|
||||||
|
// this isn't perfect since all the extra vec bits (length, capacity)
|
||||||
|
// will be leaked
|
||||||
|
// maybe this should be copied instead
|
||||||
|
forget(mem);
|
||||||
|
|
||||||
|
unsafe { transmute(ptr) }
|
||||||
|
}
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct ZVal(zval);
|
pub struct ZVal(zval);
|
||||||
|
|
||||||
|
|
@ -84,8 +123,7 @@ impl ZVal {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn as_str(&self) -> String {
|
pub unsafe fn as_str(&self) -> String {
|
||||||
let str = *self.0.value.str;
|
zend_str_as_string(self.0.value.str)
|
||||||
zend_str_as_string(&str)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn as_array(&self) -> Vec<(ArrayKey, PhpVal)> {
|
pub unsafe fn as_array(&self) -> Vec<(ArrayKey, PhpVal)> {
|
||||||
|
|
@ -352,6 +390,13 @@ impl From<ZValType> for _zval_struct__bindgen_ty_1 {
|
||||||
u: _zval_struct__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1 { extra: 0 },
|
u: _zval_struct__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1 { extra: 0 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
ZValType::String => _zval_struct__bindgen_ty_1 {
|
||||||
|
v: _zval_struct__bindgen_ty_1__bindgen_ty_1 {
|
||||||
|
type_: ZValType::String as zend_uchar,
|
||||||
|
type_flags: 0,
|
||||||
|
u: _zval_struct__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1 { extra: 0 },
|
||||||
|
},
|
||||||
|
},
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -398,6 +443,13 @@ impl From<PhpVal> for ZVal {
|
||||||
},
|
},
|
||||||
u2: _zval_struct__bindgen_ty_2 { extra: 0 },
|
u2: _zval_struct__bindgen_ty_2 { extra: 0 },
|
||||||
}),
|
}),
|
||||||
|
PhpVal::String(val) => ZVal(zval {
|
||||||
|
value: zend_value {
|
||||||
|
str: string_into_zend_str(val),
|
||||||
|
},
|
||||||
|
u1: ty.into(),
|
||||||
|
u2: _zval_struct__bindgen_ty_2 { extra: 0 },
|
||||||
|
}),
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ fn zval_parsing() {
|
||||||
"1" => PhpVal::Long(1),
|
"1" => PhpVal::Long(1),
|
||||||
"1.1" => PhpVal::Double(1.1),
|
"1.1" => PhpVal::Double(1.1),
|
||||||
"\"test\"" => PhpVal::String("test".into()),
|
"\"test\"" => PhpVal::String("test".into()),
|
||||||
|
"\"longer_string_to_cover_some_more_bytes\"" => PhpVal::String("longer_string_to_cover_some_more_bytes".into()),
|
||||||
"true" => PhpVal::Bool(true),
|
"true" => PhpVal::Bool(true),
|
||||||
"false" => PhpVal::Bool(false),
|
"false" => PhpVal::Bool(false),
|
||||||
"null" => PhpVal::Null,
|
"null" => PhpVal::Null,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue