use crate::{
boxed::ZBox,
error::Result,
exception::PhpException,
flags::DataType,
types::{ZendObject, Zval},
};
pub trait FromZval<'a>: Sized {
const TYPE: DataType;
fn from_zval(zval: &'a Zval) -> Option<Self>;
}
impl<'a, T> FromZval<'a> for Option<T>
where
T: FromZval<'a>,
{
const TYPE: DataType = T::TYPE;
fn from_zval(zval: &'a Zval) -> Option<Self> {
Some(T::from_zval(zval))
}
}
pub trait FromZvalMut<'a>: Sized {
const TYPE: DataType;
fn from_zval_mut(zval: &'a mut Zval) -> Option<Self>;
}
impl<'a, T> FromZvalMut<'a> for T
where
T: FromZval<'a>,
{
const TYPE: DataType = <T as FromZval>::TYPE;
#[inline]
fn from_zval_mut(zval: &'a mut Zval) -> Option<Self> {
Self::from_zval(zval)
}
}
pub trait FromZendObject<'a>: Sized {
fn from_zend_object(obj: &'a ZendObject) -> Result<Self>;
}
pub trait FromZendObjectMut<'a>: Sized {
fn from_zend_object_mut(obj: &'a mut ZendObject) -> Result<Self>;
}
impl<'a, T> FromZendObjectMut<'a> for T
where
T: FromZendObject<'a>,
{
#[inline]
fn from_zend_object_mut(obj: &'a mut ZendObject) -> Result<Self> {
Self::from_zend_object(obj)
}
}
pub trait IntoZendObject {
fn into_zend_object(self) -> Result<ZBox<ZendObject>>;
}
pub trait IntoZval: Sized {
const TYPE: DataType;
fn into_zval(self, persistent: bool) -> Result<Zval> {
let mut zval = Zval::new();
self.set_zval(&mut zval, persistent)?;
Ok(zval)
}
fn set_zval(self, zv: &mut Zval, persistent: bool) -> Result<()>;
}
impl IntoZval for () {
const TYPE: DataType = DataType::Void;
#[inline]
fn set_zval(self, zv: &mut Zval, _: bool) -> Result<()> {
zv.set_null();
Ok(())
}
}
impl<T> IntoZval for Option<T>
where
T: IntoZval,
{
const TYPE: DataType = T::TYPE;
#[inline]
fn set_zval(self, zv: &mut Zval, persistent: bool) -> Result<()> {
match self {
Some(val) => val.set_zval(zv, persistent),
None => {
zv.set_null();
Ok(())
}
}
}
}
impl<T, E> IntoZval for std::result::Result<T, E>
where
T: IntoZval,
E: Into<PhpException>,
{
const TYPE: DataType = T::TYPE;
fn set_zval(self, zv: &mut Zval, persistent: bool) -> Result<()> {
match self {
Ok(val) => val.set_zval(zv, persistent),
Err(e) => {
let ex: PhpException = e.into();
ex.throw()
}
}
}
}
pub trait IntoZvalDyn {
fn as_zval(&self, persistent: bool) -> Result<Zval>;
fn get_type(&self) -> DataType;
}
impl<T: IntoZval + Clone> IntoZvalDyn for T {
fn as_zval(&self, persistent: bool) -> Result<Zval> {
self.clone().into_zval(persistent)
}
fn get_type(&self) -> DataType {
Self::TYPE
}
}
impl IntoZvalDyn for Zval {
fn as_zval(&self, _persistent: bool) -> Result<Zval> {
Ok(self.shallow_clone())
}
fn get_type(&self) -> DataType {
self.get_type()
}
}