aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe-php-shim/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/shirabe-php-shim/src/lib.rs')
-rw-r--r--crates/shirabe-php-shim/src/lib.rs63
1 files changed, 60 insertions, 3 deletions
diff --git a/crates/shirabe-php-shim/src/lib.rs b/crates/shirabe-php-shim/src/lib.rs
index c30c434..4f7b4d2 100644
--- a/crates/shirabe-php-shim/src/lib.rs
+++ b/crates/shirabe-php-shim/src/lib.rs
@@ -1900,10 +1900,67 @@ where
}
pub fn array_replace_recursive(
- _base: IndexMap<String, PhpMixed>,
- _replacement: IndexMap<String, PhpMixed>,
+ mut base: IndexMap<String, PhpMixed>,
+ replacement: IndexMap<String, PhpMixed>,
) -> IndexMap<String, PhpMixed> {
- todo!()
+ for (key, replacement_value) in replacement {
+ let merged = match base.get(&key) {
+ Some(base_value) => {
+ array_replace_recursive_value(base_value.clone(), replacement_value)
+ }
+ None => replacement_value,
+ };
+ base.insert(key, merged);
+ }
+ base
+}
+
+// PHP recurses only when both the existing and the replacing value are arrays;
+// otherwise the replacing value wins outright.
+fn array_replace_recursive_value(base: PhpMixed, replacement: PhpMixed) -> PhpMixed {
+ match (base, replacement) {
+ (PhpMixed::Array(base), PhpMixed::Array(replacement)) => {
+ PhpMixed::Array(array_replace_recursive_assoc(base, replacement))
+ }
+ (PhpMixed::List(base), PhpMixed::List(replacement)) => {
+ PhpMixed::List(array_replace_recursive_list(base, replacement))
+ }
+ (_, replacement) => replacement,
+ }
+}
+
+fn array_replace_recursive_assoc(
+ mut base: IndexMap<String, Box<PhpMixed>>,
+ replacement: IndexMap<String, Box<PhpMixed>>,
+) -> IndexMap<String, Box<PhpMixed>> {
+ for (key, replacement_value) in replacement {
+ let merged = match base.get(&key) {
+ Some(base_value) => Box::new(array_replace_recursive_value(
+ (**base_value).clone(),
+ *replacement_value,
+ )),
+ None => replacement_value,
+ };
+ base.insert(key, merged);
+ }
+ base
+}
+
+fn array_replace_recursive_list(
+ mut base: Vec<Box<PhpMixed>>,
+ replacement: Vec<Box<PhpMixed>>,
+) -> Vec<Box<PhpMixed>> {
+ for (index, replacement_value) in replacement.into_iter().enumerate() {
+ if index < base.len() {
+ base[index] = Box::new(array_replace_recursive_value(
+ (*base[index]).clone(),
+ *replacement_value,
+ ));
+ } else {
+ base.push(replacement_value);
+ }
+ }
+ base
}
pub const PHP_MAJOR_VERSION: i64 = 8;