mirror of
https://github.com/icewind1991/ivory.git
synced 2026-06-03 10:44:09 +02:00
more casting
This commit is contained in:
parent
b8cd60fff5
commit
4a597c8330
8 changed files with 175 additions and 85 deletions
|
|
@ -12,6 +12,10 @@ edition = "2018"
|
|||
ivory-macro = { version = "0.1", path = "macro" }
|
||||
ivory-sys = { version = "7.3", path = "sys" }
|
||||
|
||||
[dev-dependencies]
|
||||
maplit = "1.0"
|
||||
pretty_assertions = "0.6"
|
||||
|
||||
[lib]
|
||||
name = "ivory"
|
||||
|
||||
|
|
|
|||
3
ivory/macro/.gitignore
vendored
Normal file
3
ivory/macro/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
target/
|
||||
**/*.rs.bk
|
||||
Cargo.lock
|
||||
51
ivory/src/error.rs
Normal file
51
ivory/src/error.rs
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
use crate::zend::ZValType;
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::fmt::Display;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CastError {
|
||||
pub actual: ZValType,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ArgError {
|
||||
CastError(CastError),
|
||||
NotEnoughArguments,
|
||||
}
|
||||
|
||||
impl From<CastError> for ArgError {
|
||||
fn from(from: CastError) -> Self {
|
||||
ArgError::CastError(from)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for CastError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Incorrect variable type, got {}", self.actual)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ArgError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
ArgError::CastError(err) => err.fmt(f),
|
||||
ArgError::NotEnoughArguments => write!(f, "Not enough arugments"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for CastError {
|
||||
fn cause(&self) -> Option<&Error> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for ArgError {
|
||||
fn cause(&self) -> Option<&Error> {
|
||||
match self {
|
||||
ArgError::CastError(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,10 @@
|
|||
#[macro_use]
|
||||
pub mod macros;
|
||||
pub mod error;
|
||||
|
||||
pub mod externs;
|
||||
pub mod info;
|
||||
pub mod zend;
|
||||
pub use crate::zend::{ArgError, ArrayKey, CastError, PhpVal};
|
||||
pub use crate::error::{ArgError, CastError};
|
||||
pub use crate::zend::{ArrayKey, PhpVal};
|
||||
pub use ivory_macro::{ivory_export, ivory_module};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
pub use self::function::*;
|
||||
pub use self::module::*;
|
||||
pub use self::zval::{ArgError, ArrayKey, CastError, ExecuteData, PhpVal, ZVal};
|
||||
pub use self::zval::{ArrayKey, ExecuteData, PhpVal, ZVal, ZValType};
|
||||
|
||||
mod function;
|
||||
mod module;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
use std::collections::HashMap;
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::fmt::Display;
|
||||
use std::intrinsics::transmute;
|
||||
use std::mem::size_of;
|
||||
use std::os::raw::c_char;
|
||||
|
|
@ -9,6 +7,10 @@ use std::str;
|
|||
|
||||
use ivory_sys::{zend_execute_data, zend_string, zval};
|
||||
|
||||
use crate::CastError;
|
||||
use std::fmt::Display;
|
||||
use std::hash::Hash;
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct ExecuteData(zend_execute_data);
|
||||
|
||||
|
|
@ -121,7 +123,7 @@ impl ZVal {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[repr(u8)]
|
||||
pub enum ZValType {
|
||||
Undef = 0,
|
||||
|
|
@ -164,31 +166,30 @@ impl From<u8> for ZValType {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum ArrayKey {
|
||||
String(String),
|
||||
Int(u64),
|
||||
}
|
||||
|
||||
impl From<String> for ArrayKey {
|
||||
fn from(input: String) -> Self {
|
||||
ArrayKey::String(input)
|
||||
}
|
||||
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<u64> for ArrayKey {
|
||||
fn from(input: u64) -> Self {
|
||||
ArrayKey::Int(input)
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
||||
impl From<usize> for ArrayKey {
|
||||
fn from(input: usize) -> Self {
|
||||
ArrayKey::Int(input as u64)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum PhpVal {
|
||||
Undef,
|
||||
Null,
|
||||
|
|
@ -259,6 +260,12 @@ macro_rules! impl_from_phpval {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$type> for PhpVal {
|
||||
fn from(input: $type) -> Self {
|
||||
PhpVal::$variant(input)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -267,24 +274,6 @@ impl_from_phpval!(f64, Double);
|
|||
impl_from_phpval!(bool, Bool);
|
||||
impl_from_phpval!(String, String);
|
||||
|
||||
impl From<i64> for PhpVal {
|
||||
fn from(input: i64) -> Self {
|
||||
PhpVal::Long(input)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for PhpVal {
|
||||
fn from(input: String) -> Self {
|
||||
PhpVal::String(input)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<bool> for PhpVal {
|
||||
fn from(input: bool) -> Self {
|
||||
PhpVal::Bool(input)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Into<PhpVal>> From<Option<T>> for PhpVal {
|
||||
fn from(input: Option<T>) -> Self {
|
||||
match input {
|
||||
|
|
@ -317,49 +306,13 @@ impl<K: Into<ArrayKey>, T: Into<PhpVal>> From<Vec<(K, T)>> for PhpVal {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CastError {
|
||||
actual: ZValType,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ArgError {
|
||||
CastError(CastError),
|
||||
NotEnoughArguments,
|
||||
}
|
||||
|
||||
impl From<CastError> for ArgError {
|
||||
fn from(from: CastError) -> Self {
|
||||
ArgError::CastError(from)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for CastError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Incorrect variable type, got {}", self.actual)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ArgError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
ArgError::CastError(err) => err.fmt(f),
|
||||
ArgError::NotEnoughArguments => write!(f, "Not enough arugments"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for CastError {
|
||||
fn cause(&self) -> Option<&Error> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for ArgError {
|
||||
fn cause(&self) -> Option<&Error> {
|
||||
match self {
|
||||
ArgError::CastError(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
impl<K: Into<ArrayKey> + Hash + Eq, T: Into<PhpVal>> From<HashMap<K, T>> for PhpVal {
|
||||
fn from(input: HashMap<K, T>) -> Self {
|
||||
PhpVal::Array(
|
||||
input
|
||||
.into_iter()
|
||||
.map(|(key, value)| (key.into(), value.into()))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
68
ivory/tests/tests.rs
Normal file
68
ivory/tests/tests.rs
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
use maplit::hashmap;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
use ivory::{ArrayKey, PhpVal};
|
||||
|
||||
#[test]
|
||||
fn cast_into_php_val() {
|
||||
assert_eq!(PhpVal::Long(1), 1.into());
|
||||
assert_eq!(PhpVal::Double(1.1), (1.1).into());
|
||||
assert_eq!(PhpVal::String("foo".to_string()), "foo".to_string().into());
|
||||
assert_eq!(PhpVal::Bool(true), true.into());
|
||||
assert_eq!(PhpVal::Bool(false), false.into());
|
||||
assert_eq!(
|
||||
PhpVal::Array(vec![
|
||||
(ArrayKey::Int(0), PhpVal::Long(1)),
|
||||
(ArrayKey::Int(1), PhpVal::Long(2)),
|
||||
(ArrayKey::Int(2), PhpVal::Long(3))
|
||||
]),
|
||||
vec![1, 2, 3].into()
|
||||
);
|
||||
assert_eq!(
|
||||
PhpVal::Array(vec![
|
||||
(ArrayKey::Int(0), PhpVal::Long(1)),
|
||||
(ArrayKey::Int(1), PhpVal::Double(2.1)),
|
||||
(ArrayKey::Int(2), PhpVal::String("3".to_string()))
|
||||
]),
|
||||
vec![
|
||||
PhpVal::Long(1),
|
||||
PhpVal::Double(2.1),
|
||||
PhpVal::String("3".to_string())
|
||||
]
|
||||
.into()
|
||||
);
|
||||
assert_eq!(
|
||||
PhpVal::Array(vec![
|
||||
(ArrayKey::Int(0), PhpVal::Long(1)),
|
||||
(ArrayKey::Int(3), PhpVal::Long(2)),
|
||||
(ArrayKey::Int(6), PhpVal::Long(3))
|
||||
]),
|
||||
vec![(0u8, 1), (3, 2), (6, 3)].into()
|
||||
);
|
||||
assert_eq!(
|
||||
PhpVal::Array(vec![
|
||||
(ArrayKey::Int(0), PhpVal::Long(1)),
|
||||
(ArrayKey::Int(3), PhpVal::Long(2)),
|
||||
(ArrayKey::String("foo".to_string()), PhpVal::Long(3))
|
||||
]),
|
||||
vec![
|
||||
(ArrayKey::Int(0), 1),
|
||||
(ArrayKey::Int(3), 2),
|
||||
(ArrayKey::String("foo".to_string()), 3)
|
||||
]
|
||||
.into()
|
||||
);
|
||||
assert_eq!(
|
||||
PhpVal::Array(vec![
|
||||
(ArrayKey::Int(0), PhpVal::Long(1)),
|
||||
(ArrayKey::Int(3), PhpVal::Long(2)),
|
||||
(ArrayKey::Int(6), PhpVal::Long(3))
|
||||
]),
|
||||
hashmap! {
|
||||
0u8 => 1,
|
||||
3 => 2,
|
||||
6 => 3
|
||||
}
|
||||
.into()
|
||||
);
|
||||
}
|
||||
|
|
@ -1 +1,10 @@
|
|||
# Tests
|
||||
# Ivory integration tests
|
||||
|
||||
A basic php module to test the transition between php and rust
|
||||
|
||||
# Usage
|
||||
|
||||
Due to the particularities with loading dynamic libraries in rust tests, the tests have to be rebuild *before* running the tests after making changes.
|
||||
|
||||
- `cargo build`
|
||||
- `cargo test`
|
||||
Loading…
Add table
Add a link
Reference in a new issue