Skip to content

Commit 50338e3

Browse files
committed
Refactor Type, and add Array Iterator.
1 parent 8c5894a commit 50338e3

File tree

11 files changed

+213
-57
lines changed

11 files changed

+213
-57
lines changed

phper-macros/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ pub fn php_get_module(attr: TokenStream, input: TokenStream) -> TokenStream {
7373
inner::php_get_module(attr, input)
7474
}
7575

76-
/// Auto derive for [phper::errors::Throwable].
76+
/// Auto derive for `phper::errors::Throwable`.
7777
///
7878
/// # Examples
7979
///

phper/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ clap = "3.0.0-beta.2"
1818
dashmap = "4.0.2"
1919
derive_more = "0.99.13"
2020
indexmap = "1.6.2"
21-
num-derive = "0.3"
22-
num-traits = "0.2"
21+
#num-derive = "0.3"
22+
#num-traits = "0.2"
2323
once_cell = "1.7.2"
2424
phper-alloc = { version = "0.2.0-alpha.3", path = "../phper-alloc" }
2525
phper-macros = { version = "0.2.0-alpha.3", path = "../phper-macros" }

phper/src/arrays.rs

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,17 @@
22
33
use crate::{
44
alloc::{EAllocatable, EBox},
5+
strings::ZendString,
56
sys::*,
67
values::Val,
78
};
8-
use std::mem::zeroed;
9+
use std::{borrow::Cow, mem::zeroed};
910

1011
/// Key for [Array].
12+
#[derive(Debug, Clone, PartialEq)]
1113
pub enum Key<'a> {
1214
Index(u64),
13-
Str(&'a str),
15+
Str(Cow<'a, str>),
1416
}
1517

1618
impl From<u64> for Key<'_> {
@@ -21,7 +23,13 @@ impl From<u64> for Key<'_> {
2123

2224
impl<'a> From<&'a str> for Key<'a> {
2325
fn from(s: &'a str) -> Self {
24-
Key::Str(s)
26+
Key::Str(Cow::Borrowed(s))
27+
}
28+
}
29+
30+
impl From<String> for Key<'_> {
31+
fn from(s: String) -> Self {
32+
Key::Str(Cow::Owned(s))
2533
}
2634
}
2735

@@ -107,6 +115,13 @@ impl Array {
107115
}
108116
other
109117
}
118+
119+
pub fn iter(&self) -> Iter<'_> {
120+
Iter {
121+
index: 0,
122+
array: &self,
123+
}
124+
}
110125
}
111126

112127
impl EAllocatable for Array {
@@ -125,3 +140,45 @@ impl Drop for Array {
125140
unreachable!("Allocation on the stack is not allowed")
126141
}
127142
}
143+
144+
pub struct Iter<'a> {
145+
index: isize,
146+
array: &'a Array,
147+
}
148+
149+
impl<'a> Iterator for Iter<'a> {
150+
type Item = (Key<'a>, &'a Val);
151+
152+
fn next(&mut self) -> Option<Self::Item> {
153+
loop {
154+
if self.index >= self.array.inner.nNumUsed as isize {
155+
break None;
156+
}
157+
158+
unsafe {
159+
let bucket = self.array.inner.arData.offset(self.index);
160+
161+
let key = if (*bucket).key.is_null() {
162+
Key::Index((*bucket).h)
163+
} else {
164+
let s = ZendString::from_ptr((*bucket).key);
165+
let s = s.to_string().unwrap();
166+
Key::Str(Cow::Owned(s))
167+
};
168+
169+
let val = &mut (*bucket).val;
170+
let mut val = Val::from_mut_ptr(val);
171+
if val.get_type().is_indirect() {
172+
val = Val::from_mut_ptr((*val.as_mut_ptr()).value.zv);
173+
}
174+
175+
self.index += 1;
176+
177+
if val.get_type().is_undef() {
178+
continue;
179+
}
180+
break Some((key, val));
181+
}
182+
}
183+
}
184+
}

phper/src/classes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ impl<T: 'static> ClassEntry<T> {
190190
r
191191
}
192192

193-
fn check_type_id(this: *mut Self) -> Result<(), StateTypeError> {
193+
pub(crate) fn check_type_id(this: *const Self) -> Result<(), StateTypeError> {
194194
if TypeId::of::<T>() == TypeId::of::<()>() {
195195
return Ok(());
196196
}

phper/src/functions.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,6 @@ where
7979
fn call(&self, execute_data: &mut ExecuteData, arguments: &mut [Val], return_value: &mut Val) {
8080
unsafe {
8181
let this = execute_data.get_this::<T>().unwrap();
82-
// TODO Fix the object type assertion.
83-
// assert!(this.get_type().is_object());
8482
let r = (self.f)(this, arguments);
8583
r.set_val(return_value);
8684
}

phper/src/lib.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,6 @@ See [examples](https://github.com/jmjoy/phper/tree/master/examples).
8787
[Unlicense](https://github.com/jmjoy/phper/blob/master/LICENSE).
8888
*/
8989

90-
#[macro_use]
91-
extern crate num_derive;
92-
9390
#[macro_use]
9491
mod macros;
9592

phper/src/objects.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@ impl<T: 'static> Object<T> {
136136
EBox::from_raw(new_obj)
137137
}
138138
}
139+
140+
pub fn get_class(&self) -> &ClassEntry<T> {
141+
ClassEntry::from_ptr(self.inner.ce)
142+
}
139143
}
140144

141145
impl Object<()> {

phper/src/types.rs

Lines changed: 96 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,91 +2,136 @@
22
33
use crate::sys::*;
44
use derive_more::From;
5-
use num_traits::cast::FromPrimitive;
65
use std::{ffi::CStr, os::raw::c_int};
76

8-
/// TODO Refactor to a struct rather than enum, because it's so complex than the type have bit flag.
9-
#[derive(FromPrimitive, PartialEq, Clone, Copy)]
10-
#[repr(u32)]
11-
#[non_exhaustive]
12-
pub enum Type {
13-
Undef = IS_UNDEF,
14-
Null = IS_NULL,
15-
False = IS_FALSE,
16-
True = IS_TRUE,
17-
Long = IS_LONG,
18-
Double = IS_DOUBLE,
19-
String = IS_STRING,
20-
StringEx = IS_STRING_EX,
21-
Array = IS_ARRAY,
22-
ArrayEx = IS_ARRAY_EX,
23-
Object = IS_OBJECT,
24-
ObjectEx = IS_OBJECT_EX,
25-
Resource = IS_RESOURCE,
26-
Reference = IS_REFERENCE,
27-
ConstantAst = IS_CONSTANT_AST,
28-
IsCallable = IS_CALLABLE,
7+
/// Wrapper of PHP type.
8+
#[derive(PartialEq, Clone, Copy, Debug)]
9+
pub struct Type {
10+
t: u32,
2911
}
3012

3113
impl Type {
14+
pub const fn from_raw(t: u32) -> Self {
15+
Self { t }
16+
}
17+
18+
pub const fn into_raw(self) -> u32 {
19+
self.t
20+
}
21+
22+
#[inline]
23+
pub fn null() -> Type {
24+
Self::from_raw(IS_NULL)
25+
}
26+
27+
#[inline]
28+
pub fn bool(b: bool) -> Type {
29+
Self::from_raw(if b { IS_TRUE } else { IS_FALSE })
30+
}
31+
32+
#[inline]
33+
pub fn long() -> Type {
34+
Self::from_raw(IS_LONG)
35+
}
36+
37+
#[inline]
38+
pub fn double() -> Type {
39+
Self::from_raw(IS_DOUBLE)
40+
}
41+
42+
#[inline]
43+
pub fn array() -> Type {
44+
Self::from_raw(IS_ARRAY)
45+
}
46+
47+
#[inline]
48+
pub fn array_ex() -> Type {
49+
Self::from_raw(IS_ARRAY_EX)
50+
}
51+
52+
#[inline]
53+
pub fn object() -> Type {
54+
Self::from_raw(IS_OBJECT)
55+
}
56+
57+
#[inline]
58+
pub fn object_ex() -> Type {
59+
Self::from_raw(IS_OBJECT_EX)
60+
}
61+
62+
#[inline]
63+
pub fn is_undef(self) -> bool {
64+
self.t == IS_UNDEF
65+
}
66+
3267
#[inline]
3368
pub fn is_null(self) -> bool {
34-
self == Type::Null
69+
self.t == IS_NULL
3570
}
3671

3772
#[inline]
3873
pub fn is_bool(self) -> bool {
39-
matches!(self, Type::True | Type::False)
74+
self.is_true() || self.is_false()
4075
}
4176

4277
#[inline]
4378
pub fn is_true(self) -> bool {
44-
self == Type::True
79+
get_base_type_by_raw(self.t) == IS_TRUE
4580
}
4681

4782
#[inline]
4883
pub fn is_false(self) -> bool {
49-
self == Type::False
84+
get_base_type_by_raw(self.t) == IS_FALSE
5085
}
5186

5287
#[inline]
5388
pub fn is_long(self) -> bool {
54-
self == Type::Long
89+
get_base_type_by_raw(self.t) == IS_LONG
5590
}
5691

5792
#[inline]
5893
pub fn is_double(self) -> bool {
59-
self == Type::Double
94+
get_base_type_by_raw(self.t) == IS_DOUBLE
6095
}
6196

6297
#[inline]
6398
pub fn is_string(self) -> bool {
64-
matches!(self, Type::String | Type::StringEx)
99+
get_base_type_by_raw(self.t) == IS_STRING
65100
}
66101

67102
#[inline]
68103
pub fn is_array(self) -> bool {
69-
matches!(self, Type::Array | Type::ArrayEx)
104+
get_base_type_by_raw(self.t) == IS_ARRAY
70105
}
71106

72107
#[inline]
73108
pub fn is_object(self) -> bool {
74-
matches!(self, Type::Object | Type::ObjectEx)
109+
get_base_type_by_raw(self.t) == IS_OBJECT
110+
}
111+
112+
#[inline]
113+
pub fn is_indirect(self) -> bool {
114+
self.t == IS_INDIRECT
115+
}
116+
117+
pub fn get_base_type(self) -> Type {
118+
Self::from_raw(get_base_type_by_raw(self.t))
119+
}
120+
121+
pub fn get_base_type_name(self) -> crate::Result<String> {
122+
get_type_by_const(self.t)
75123
}
76124
}
77125

78126
impl From<u32> for Type {
79127
fn from(n: u32) -> Self {
80-
match FromPrimitive::from_u32(n) {
81-
Some(t) => t,
82-
None => unreachable!("Type is not exhaustive, should contains: {}", n),
83-
}
128+
Self::from_raw(n)
84129
}
85130
}
86131

87132
pub(crate) fn get_type_by_const(mut t: u32) -> crate::Result<String> {
88133
unsafe {
89-
t &= !(IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT);
134+
t = get_base_type_by_raw(t);
90135
let s = zend_get_type_by_const(t as c_int);
91136
let mut s = CStr::from_ptr(s).to_str()?.to_string();
92137

@@ -101,6 +146,21 @@ pub(crate) fn get_type_by_const(mut t: u32) -> crate::Result<String> {
101146
}
102147
}
103148

149+
#[inline]
150+
pub fn get_base_type_by_raw(mut t: u32) -> u32 {
151+
t &= !(IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT);
152+
153+
#[cfg(any(
154+
phper_major_version = "8",
155+
all(phper_major_version = "7", phper_minor_version = "4")
156+
))]
157+
{
158+
t &= !(IS_TYPE_COLLECTABLE << Z_TYPE_FLAGS_SHIFT);
159+
}
160+
161+
t
162+
}
163+
104164
#[derive(From)]
105165
pub enum Scalar {
106166
Null,

0 commit comments

Comments
 (0)