split off phpval code

This commit is contained in:
Robin Appelman 2019-04-06 13:36:41 +02:00
commit aecef495de
5 changed files with 165 additions and 161 deletions

View file

@ -90,7 +90,7 @@ fn export_fn(item: ItemFn) -> TokenStream {
#(#arg_cast);*
let result = #body;
let php_val = ::ivory::zend::PhpVal::from(result);
let php_val = ::ivory::PhpVal::from(result);
let zval = ::ivory::zend::ZVal::from(php_val);
unsafe {
*retval = zval

View file

@ -4,7 +4,8 @@ pub mod error;
pub mod externs;
pub mod info;
mod phpval;
pub mod zend;
pub use crate::error::{ArgError, CastError};
pub use crate::zend::{ArrayKey, PhpVal};
pub use crate::phpval::{ArrayKey, PhpVal};
pub use ivory_macro::{ivory_export, ivory_module};

160
ivory/src/phpval.rs Normal file
View file

@ -0,0 +1,160 @@
use std::collections::HashMap;
use std::hash::Hash;
use crate::zend::ZValType;
use crate::CastError;
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub enum ArrayKey {
String(String),
Int(u64),
}
macro_rules! impl_from_array_key {
($type:ty, $variant:ident, $type2:ty) => {
impl From<$type> for ArrayKey {
fn from(input: $type) -> Self {
ArrayKey::$variant(input as $type2)
}
}
};
}
impl_from_array_key!(String, String, String);
impl_from_array_key!(u64, Int, u64);
impl_from_array_key!(u32, Int, u64);
impl_from_array_key!(u16, Int, u64);
impl_from_array_key!(u8, Int, u64);
impl_from_array_key!(usize, Int, u64);
#[derive(Debug, PartialEq, Clone)]
pub enum PhpVal {
Undef,
Null,
Bool(bool),
Long(i64),
Double(f64),
String(String),
Array(Vec<(ArrayKey, PhpVal)>),
Object(HashMap<String, PhpVal>),
Resource(u64),
Reference(),
}
impl PhpVal {
pub fn get_type(&self) -> ZValType {
match self {
PhpVal::Undef => ZValType::Undef,
PhpVal::Null => ZValType::Null,
PhpVal::Bool(true) => ZValType::True,
PhpVal::Bool(false) => ZValType::False,
PhpVal::Long(_) => ZValType::Long,
PhpVal::Double(_) => ZValType::Double,
PhpVal::String(_) => ZValType::String,
PhpVal::Array(_) => ZValType::Array,
PhpVal::Object(_) => ZValType::Object,
PhpVal::Resource(_) => ZValType::Resource,
PhpVal::Reference() => ZValType::Reference,
}
}
}
impl Default for PhpVal {
fn default() -> Self {
PhpVal::Undef
}
}
impl From<PhpVal> for Result<PhpVal, CastError> {
fn from(val: PhpVal) -> Self {
Ok(val)
}
}
macro_rules! impl_from_phpval {
($type:ty, $variant:ident) => {
// non nullable version
impl From<PhpVal> for Result<$type, CastError> {
fn from(val: PhpVal) -> Self {
match val {
PhpVal::$variant(val) => Ok(val),
_ => Err(CastError {
actual: val.get_type(),
}),
}
}
}
// nullable version
impl From<PhpVal> for Result<Option<$type>, CastError> {
fn from(val: PhpVal) -> Self {
match val {
PhpVal::Null => Ok(None),
PhpVal::Undef => Ok(None),
PhpVal::$variant(val) => Ok(Some(val)),
_ => Err(CastError {
actual: val.get_type(),
}),
}
}
}
impl From<$type> for PhpVal {
fn from(input: $type) -> Self {
PhpVal::$variant(input)
}
}
};
}
impl_from_phpval!(i64, Long);
impl_from_phpval!(f64, Double);
impl_from_phpval!(bool, Bool);
impl_from_phpval!(String, String);
impl From<()> for PhpVal {
fn from(_input: ()) -> Self {
PhpVal::Null
}
}
impl<T: Into<PhpVal>> From<Option<T>> for PhpVal {
fn from(input: Option<T>) -> Self {
match input {
Some(inner) => inner.into(),
None => PhpVal::Null,
}
}
}
impl<T: Into<PhpVal>> From<Vec<T>> for PhpVal {
fn from(input: Vec<T>) -> Self {
PhpVal::Array(
input
.into_iter()
.enumerate()
.map(|(key, value)| (key.into(), value.into()))
.collect(),
)
}
}
impl<K: Into<ArrayKey>, T: Into<PhpVal>> From<Vec<(K, T)>> for PhpVal {
fn from(input: Vec<(K, T)>) -> Self {
PhpVal::Array(
input
.into_iter()
.map(|(key, value)| (key.into(), value.into()))
.collect(),
)
}
}
impl<K: Into<ArrayKey> + Hash + Eq + Ord, T: Into<PhpVal>> From<HashMap<K, T>> for PhpVal {
fn from(input: HashMap<K, T>) -> Self {
let mut vec: Vec<(K, T)> = input.into_iter().collect();
// since hashmap doesn't contain any stable order we sort it to get predictable results
vec.sort_unstable_by(|(a, _), (b, _)| a.cmp(b));
vec.into()
}
}

View file

@ -1,6 +1,6 @@
pub use self::function::*;
pub use self::module::*;
pub use self::zval::{ArrayKey, ExecuteData, PhpVal, ZVal, ZValType};
pub use self::zval::{ExecuteData, ZVal, ZValType};
mod function;
mod module;

View file

@ -1,14 +1,12 @@
use std::collections::HashMap;
use std::fmt;
use std::fmt::Display;
use std::hash::Hash;
use std::intrinsics::transmute;
use std::mem::{forget, size_of};
use std::str;
use ivory_sys::*;
use crate::CastError;
use crate::{ArrayKey, PhpVal};
#[repr(transparent)]
pub struct ExecuteData(zend_execute_data);
@ -204,161 +202,6 @@ impl From<u8> for ZValType {
}
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub enum ArrayKey {
String(String),
Int(u64),
}
macro_rules! impl_from_array_key {
($type:ty, $variant:ident, $type2:ty) => {
impl From<$type> for ArrayKey {
fn from(input: $type) -> Self {
ArrayKey::$variant(input as $type2)
}
}
};
}
impl_from_array_key!(String, String, String);
impl_from_array_key!(u64, Int, u64);
impl_from_array_key!(u32, Int, u64);
impl_from_array_key!(u16, Int, u64);
impl_from_array_key!(u8, Int, u64);
impl_from_array_key!(usize, Int, u64);
#[derive(Debug, PartialEq, Clone)]
pub enum PhpVal {
Undef,
Null,
Bool(bool),
Long(i64),
Double(f64),
String(String),
Array(Vec<(ArrayKey, PhpVal)>),
Object(HashMap<String, PhpVal>),
Resource(u64),
Reference(),
}
impl PhpVal {
pub fn get_type(&self) -> ZValType {
match self {
PhpVal::Undef => ZValType::Undef,
PhpVal::Null => ZValType::Null,
PhpVal::Bool(true) => ZValType::True,
PhpVal::Bool(false) => ZValType::False,
PhpVal::Long(_) => ZValType::Long,
PhpVal::Double(_) => ZValType::Double,
PhpVal::String(_) => ZValType::String,
PhpVal::Array(_) => ZValType::Array,
PhpVal::Object(_) => ZValType::Object,
PhpVal::Resource(_) => ZValType::Resource,
PhpVal::Reference() => ZValType::Reference,
}
}
}
impl Default for PhpVal {
fn default() -> Self {
PhpVal::Undef
}
}
impl From<PhpVal> for Result<PhpVal, CastError> {
fn from(val: PhpVal) -> Self {
Ok(val)
}
}
macro_rules! impl_from_phpval {
($type:ty, $variant:ident) => {
// non nullable version
impl From<PhpVal> for Result<$type, CastError> {
fn from(val: PhpVal) -> Self {
match val {
PhpVal::$variant(val) => Ok(val),
_ => Err(CastError {
actual: val.get_type(),
}),
}
}
}
// nullable version
impl From<PhpVal> for Result<Option<$type>, CastError> {
fn from(val: PhpVal) -> Self {
match val {
PhpVal::Null => Ok(None),
PhpVal::Undef => Ok(None),
PhpVal::$variant(val) => Ok(Some(val)),
_ => Err(CastError {
actual: val.get_type(),
}),
}
}
}
impl From<$type> for PhpVal {
fn from(input: $type) -> Self {
PhpVal::$variant(input)
}
}
};
}
impl_from_phpval!(i64, Long);
impl_from_phpval!(f64, Double);
impl_from_phpval!(bool, Bool);
impl_from_phpval!(String, String);
impl From<()> for PhpVal {
fn from(_input: ()) -> Self {
PhpVal::Null
}
}
impl<T: Into<PhpVal>> From<Option<T>> for PhpVal {
fn from(input: Option<T>) -> Self {
match input {
Some(inner) => inner.into(),
None => PhpVal::Null,
}
}
}
impl<T: Into<PhpVal>> From<Vec<T>> for PhpVal {
fn from(input: Vec<T>) -> Self {
PhpVal::Array(
input
.into_iter()
.enumerate()
.map(|(key, value)| (key.into(), value.into()))
.collect(),
)
}
}
impl<K: Into<ArrayKey>, T: Into<PhpVal>> From<Vec<(K, T)>> for PhpVal {
fn from(input: Vec<(K, T)>) -> Self {
PhpVal::Array(
input
.into_iter()
.map(|(key, value)| (key.into(), value.into()))
.collect(),
)
}
}
impl<K: Into<ArrayKey> + Hash + Eq + Ord, T: Into<PhpVal>> From<HashMap<K, T>> for PhpVal {
fn from(input: HashMap<K, T>) -> Self {
let mut vec: Vec<(K, T)> = input.into_iter().collect();
// since hashmap doesn't contain any stable order we sort it to get predictable results
vec.sort_unstable_by(|(a, _), (b, _)| a.cmp(b));
vec.into()
}
}
impl From<ZValType> for _zval_struct__bindgen_ty_1 {
fn from(ty: ZValType) -> Self {
_zval_struct__bindgen_ty_1 {