Skip to content

Commit d783c21

Browse files
committed
Implement SetVal for Indexmap.
1 parent a425c50 commit d783c21

File tree

6 files changed

+69
-8
lines changed

6 files changed

+69
-8
lines changed

phper/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ keywords = ["php", "binding", "extension"]
1515
[dependencies]
1616
anyhow = "1.0.40"
1717
clap = "3.0.0-beta.2"
18+
indexmap = "1.6.2"
1819
num-derive = "0.3"
1920
num-traits = "0.2"
2021
once_cell = "1.7.2"

phper/src/values.rs

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::{
77
utils::ensure_end_with_zero,
88
TypeError,
99
};
10+
use indexmap::map::IndexMap;
1011
use std::{
1112
collections::HashMap, mem::zeroed, os::raw::c_char, slice::from_raw_parts, str, str::Utf8Error,
1213
sync::atomic::Ordering,
@@ -227,6 +228,10 @@ impl Val {
227228
}
228229
}
229230

231+
/// The trait for setting the value of [Val], mainly as the return value of
232+
/// [crate::functions::Function] and [crate::functions::Method], and initializer of [Val].
233+
///
234+
/// TODO Fix the possibility of leak memory.
230235
pub trait SetVal {
231236
fn set_val(self, val: &mut Val);
232237
}
@@ -304,6 +309,8 @@ impl<T: SetVal> SetVal for Vec<T> {
304309
}
305310
}
306311

312+
/// Setting the val to an array, Because of the feature of [std::collections::HashMap], the item
313+
/// order of array is not guarantee.
307314
impl<K: AsRef<str>, V: SetVal> SetVal for HashMap<K, V> {
308315
fn set_val(self, val: &mut Val) {
309316
unsafe {
@@ -321,6 +328,24 @@ impl<K: AsRef<str>, V: SetVal> SetVal for HashMap<K, V> {
321328
}
322329
}
323330

331+
/// Setting the val to an array, which preserves item order.
332+
impl<K: AsRef<str>, V: SetVal> SetVal for IndexMap<K, V> {
333+
fn set_val(self, val: &mut Val) {
334+
unsafe {
335+
phper_array_init(val.as_mut_ptr());
336+
for (k, v) in self {
337+
let k = k.as_ref();
338+
zend_hash_str_update(
339+
(*val.as_mut_ptr()).value.arr,
340+
k.as_ptr().cast(),
341+
k.len(),
342+
Val::new(v).as_mut_ptr(),
343+
);
344+
}
345+
}
346+
}
347+
}
348+
324349
impl SetVal for Array {
325350
fn set_val(mut self, val: &mut Val) {
326351
unsafe {
@@ -330,12 +355,6 @@ impl SetVal for Array {
330355
}
331356
}
332357

333-
extern "C" fn array_copy_ctor(zv: *mut zval) {
334-
let val = unsafe { Val::from_mut(zv) };
335-
let other = unsafe { Val::from_mut(zv) };
336-
val.deep_copy(other).expect("deep copy failed");
337-
}
338-
339358
impl<T: SetVal> SetVal for Option<T> {
340359
fn set_val(self, val: &mut Val) {
341360
match self {

tests/integration/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ license = "Unlicense"
1212
crate-type = ["cdylib"]
1313

1414
[dependencies]
15+
indexmap = "1.6.2"
1516
phper = { version = "0.2.0-alpha.2", path = "../../phper" }
1617

1718
[dev-dependencies]

tests/integration/src/values.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use indexmap::map::IndexMap;
12
use phper::{arrays::Array, modules::Module, values::Val};
23
use std::collections::HashMap;
34

@@ -71,11 +72,26 @@ fn integrate_returns(module: &mut Module) {
7172
integration_values_return_string_map,
7273
vec![],
7374
);
75+
module.add_function(
76+
"integration_values_return_i64_index_map",
77+
integration_values_return_i64_index_map,
78+
vec![],
79+
);
7480
module.add_function(
7581
"integration_values_return_array",
7682
integration_values_return_array,
7783
vec![],
7884
);
85+
module.add_function(
86+
"integration_values_return_option_i64_some",
87+
integration_values_return_option_i64_some,
88+
vec![],
89+
);
90+
module.add_function(
91+
"integration_values_return_option_i64_none",
92+
integration_values_return_option_i64_none,
93+
vec![],
94+
);
7995
}
8096

8197
fn integration_values_return_null(_: &mut [Val]) {}
@@ -136,9 +152,25 @@ fn integration_values_return_string_map(_: &mut [Val]) -> HashMap<String, String
136152
map
137153
}
138154

155+
fn integration_values_return_i64_index_map(_: &mut [Val]) -> IndexMap<&'static str, i64> {
156+
let mut map = IndexMap::new();
157+
map.insert("a", 0);
158+
map.insert("b", 1);
159+
map.insert("c", 2);
160+
map
161+
}
162+
139163
fn integration_values_return_array(_: &mut [Val]) -> Array {
140164
let mut arr = Array::new();
141165
arr.insert("a", Val::new(1));
142166
arr.insert("b", Val::new("foo"));
143167
arr
144168
}
169+
170+
fn integration_values_return_option_i64_some(_: &mut [Val]) -> Option<i64> {
171+
Some(64)
172+
}
173+
174+
fn integration_values_return_option_i64_none(_: &mut [Val]) -> Option<i64> {
175+
None
176+
}

tests/integration/tests/php/_common.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,8 @@ function assert_eq($left, $right) {
99
throw new Exception(sprintf("left != right,\n left: %s,\n right: %s", var_export($left, true), var_export($right, true)));
1010
}
1111
}
12+
13+
function array_ksort($array) {
14+
ksort($array);
15+
return $array;
16+
}

tests/integration/tests/php/values.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
assert_eq(integration_values_return_string(), "foo");
1414
assert_eq(integration_values_return_i64_vec(), [0, 1, 2]);
1515
assert_eq(integration_values_return_string_vec(), ["a", "b", "c"]);
16-
assert_eq(integration_values_return_i64_map(), ["a" => 0, "b" => 1, "c" => 2]);
17-
assert_eq(integration_values_return_string_map(), ["a" => "x", "b" => "y", "c" => "z"]);
16+
assert_eq(array_ksort(integration_values_return_i64_map()), ["a" => 0, "b" => 1, "c" => 2]);
17+
assert_eq(array_ksort(integration_values_return_string_map()), ["a" => "x", "b" => "y", "c" => "z"]);
18+
assert_eq(integration_values_return_i64_index_map(), ["a" => 0, "b" => 1, "c" => 2]);
1819
assert_eq(integration_values_return_array(), ["a" => 1, "b" => "foo"]);
20+
assert_eq(integration_values_return_option_i64_some(), 64);
21+
assert_eq(integration_values_return_option_i64_none(), null);

0 commit comments

Comments
 (0)