From 7cc66cff4bee03f8e25a3cc4f163e164565e22c3 Mon Sep 17 00:00:00 2001 From: Ophir Lojkine Date: Wed, 7 Oct 2026 09:44:44 +0000 Subject: [PATCH 1/2] refactor: move owned values when merging and flattening --- src/dynamic_component.rs | 24 +++++++++++++++++++++++- src/webserver/single_or_vec.rs | 21 ++++++++++++++++++++- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/dynamic_component.rs b/src/dynamic_component.rs index 058a25491..080d86ffa 100644 --- a/src/dynamic_component.rs +++ b/src/dynamic_component.rs @@ -116,7 +116,7 @@ fn dynamic_properties_to_result_vec( JsonValue::Array(values) => { let mut vec = Vec::with_capacity(values.len()); for value in values { - vec.extend_from_slice(&dynamic_properties_to_result_vec(value)?); + vec.extend(dynamic_properties_to_result_vec(value)?); } Ok(vec) } @@ -158,6 +158,28 @@ mod tests { assert!(dynamic_properties_to_result_vec(properties).is_err()); } + #[test] + fn flattens_nested_arrays_and_json_strings_in_order() { + let properties = serde_json::json!([ + [], + [{"first": {"nested": [1, 2]}}, [r#"{"second": 2}"#]], + r#"[{"third": 3}, []]"#, + {"fourth": 4} + ]); + assert_eq!( + dynamic_properties_to_result_vec(properties).unwrap(), + vec![ + serde_json::json!({"first": {"nested": [1, 2]}}), + serde_json::json!({"second": 2}), + serde_json::json!({"third": 3}), + serde_json::json!({"fourth": 4}), + ] + ); + for invalid in [serde_json::json!([{}, [null]]), serde_json::json!(["{"])] { + assert!(dynamic_properties_to_result_vec(invalid).is_err()); + } + } + #[test] fn test_dynamic_properties_to_vec() { let properties = JsonValue::String(r#"{"a": 1}"#.to_string()); diff --git a/src/webserver/single_or_vec.rs b/src/webserver/single_or_vec.rs index 394445170..ae87a8f80 100644 --- a/src/webserver/single_or_vec.rs +++ b/src/webserver/single_or_vec.rs @@ -63,7 +63,7 @@ impl SingleOrVec { (Self::Single(old), Self::Single(new)) => *old = new, (old, mut new) => { let mut v = old.take_vec(); - v.extend_from_slice(&new.take_vec()); + v.extend(new.take_vec()); *old = Self::Vec(v); } } @@ -122,6 +122,25 @@ mod single_or_vec_tests { ); } + #[test] + fn merges_preserve_scalar_replacement_and_array_order() { + let single = |s: &str| SingleOrVec::Single(s.into()); + let array = + |values: &[&str]| SingleOrVec::Vec(values.iter().map(|s| (*s).into()).collect()); + for (mut old, new, expected) in [ + (single("old"), single("new"), single("new")), + (single("a"), array(&["b", "c"]), array(&["a", "b", "c"])), + (array(&["a", "b"]), single("c"), array(&["a", "b", "c"])), + (array(&["a"]), array(&["b", "c"]), array(&["a", "b", "c"])), + (single("a"), array(&[]), array(&["a"])), + (array(&[]), single("b"), array(&["b"])), + (array(&[]), array(&[]), array(&[])), + ] { + old.merge(new); + assert_eq!(old, expected); + } + } + #[test] fn first_str_returns_first_value() { assert_eq!(SingleOrVec::Single("a".to_string()).first_str(), "a"); From 2e76ea5d41a6f0dcb89801793de7f2b84cd289a0 Mon Sep 17 00:00:00 2001 From: Ophir Lojkine Date: Wed, 7 Oct 2026 10:22:37 +0000 Subject: [PATCH 2/2] Reuse dynamic component regression test cases --- src/dynamic_component.rs | 55 ++++++++++++++-------------------------- 1 file changed, 19 insertions(+), 36 deletions(-) diff --git a/src/dynamic_component.rs b/src/dynamic_component.rs index 080d86ffa..9461a42cf 100644 --- a/src/dynamic_component.rs +++ b/src/dynamic_component.rs @@ -132,34 +132,16 @@ mod tests { #[test] fn test_dynamic_properties_to_result_vec() { - let mut properties = JsonValue::String(r#"{"a": 1}"#.to_string()); - assert_eq!( - dynamic_properties_to_result_vec(properties.clone()).unwrap(), - vec![JsonValue::Object( - serde_json::from_str(r#"{"a": 1}"#).unwrap() - )] - ); - - properties = JsonValue::Array(vec![JsonValue::String(r#"{"a": 1}"#.to_string())]); - assert_eq!( - dynamic_properties_to_result_vec(properties.clone()).unwrap(), - vec![serde_json::json!({"a": 1})] - ); - - properties = JsonValue::Object(serde_json::from_str(r#"{"a": 1}"#).unwrap()); - assert_eq!( - dynamic_properties_to_result_vec(properties.clone()).unwrap(), - vec![JsonValue::Object( - serde_json::from_str(r#"{"a": 1}"#).unwrap() - )] - ); - - properties = JsonValue::Null; - assert!(dynamic_properties_to_result_vec(properties).is_err()); - } - - #[test] - fn flattens_nested_arrays_and_json_strings_in_order() { + for properties in [ + serde_json::json!({"a": 1}), + serde_json::json!(r#"{"a": 1}"#), + serde_json::json!([r#"{"a": 1}"#]), + ] { + assert_eq!( + dynamic_properties_to_result_vec(properties).unwrap(), + vec![serde_json::json!({"a": 1})] + ); + } let properties = serde_json::json!([ [], [{"first": {"nested": [1, 2]}}, [r#"{"second": 2}"#]], @@ -167,15 +149,16 @@ mod tests { {"fourth": 4} ]); assert_eq!( - dynamic_properties_to_result_vec(properties).unwrap(), - vec![ - serde_json::json!({"first": {"nested": [1, 2]}}), - serde_json::json!({"second": 2}), - serde_json::json!({"third": 3}), - serde_json::json!({"fourth": 4}), - ] + JsonValue::Array(dynamic_properties_to_result_vec(properties).unwrap()), + serde_json::json!([ + {"first": {"nested": [1, 2]}}, {"second": 2}, {"third": 3}, {"fourth": 4} + ]) ); - for invalid in [serde_json::json!([{}, [null]]), serde_json::json!(["{"])] { + for invalid in [ + JsonValue::Null, + serde_json::json!([{}, [null]]), + serde_json::json!(["{"]), + ] { assert!(dynamic_properties_to_result_vec(invalid).is_err()); } }