deepmerge/
forwarding.rs

1//! Forwarding implementations for smart pointers and borrowed types
2
3use crate::policy::Policy;
4use crate::DeepMerge;
5
6#[cfg(feature = "alloc")]
7use alloc::{boxed::Box, rc::Rc, sync::Arc, borrow::Cow, string::ToString};
8
9/// `DeepMerge` implementation for `Box<T>`.
10///
11/// Forwards the merge operation to the boxed value, allowing seamless
12/// merging of heap-allocated values.
13///
14/// # Examples
15///
16/// ```rust
17/// use std::collections::HashMap;
18/// use deepmerge::prelude::*;
19///
20/// #[derive(DeepMerge)]
21/// #[merge(policy(string = concat))]
22/// struct Config {
23///     name: String,
24///     data: HashMap<String, i32>,
25/// }
26///
27/// let mut boxed_config = Box::new(Config {
28///     name: "app".to_string(),
29///     data: [("count".to_string(), 5)].into(),
30/// });
31///
32/// let other_config = Box::new(Config {
33///     name: "_v2".to_string(), 
34///     data: [("users".to_string(), 100)].into(),
35/// });
36///
37/// boxed_config.merge_with_policy(other_config, &DefaultPolicy);
38///
39/// assert_eq!(boxed_config.name, "app_v2");
40/// assert_eq!(boxed_config.data.get("count"), Some(&5));
41/// assert_eq!(boxed_config.data.get("users"), Some(&100));
42/// ```
43#[cfg(feature = "alloc")]
44impl<T: DeepMerge<P>, P: Policy> DeepMerge<P> for Box<T> {
45    fn merge_with_policy(&mut self, other: Self, policy: &P) {
46        self.as_mut().merge_with_policy(*other, policy);
47    }
48}
49
50/// `DeepMerge` implementation for `Rc<T>`.
51///
52/// Creates a new `Rc` with the merged value since `Rc` is immutable.
53/// Requires `T: Clone` to extract and clone the inner values.
54///
55/// # Examples
56///
57/// ```rust
58/// use std::rc::Rc;
59/// use deepmerge::prelude::*;
60///
61/// #[derive(DeepMerge, Clone)]
62/// struct Config {
63///     version: String,
64///     count: i32,
65/// }
66///
67/// let mut rc_config = Rc::new(Config {
68///     version: "v1".to_string(),
69///     count: 5,
70/// });
71///
72/// let other_config = Rc::new(Config {
73///     version: "v2".to_string(),
74///     count: 10,
75/// });
76///
77/// <Rc<Config> as DeepMerge<DefaultPolicy>>::merge_with_policy(&mut rc_config, other_config, &DefaultPolicy);
78///
79/// // Note: Rc is immutable, so merge creates a new Rc
80/// assert_eq!(rc_config.version, "v2");
81/// assert_eq!(rc_config.count, 10);
82/// ```
83#[cfg(feature = "alloc")]
84impl<T: DeepMerge<P> + Clone, P: Policy> DeepMerge<P> for Rc<T> {
85    fn merge_with_policy(&mut self, other: Self, policy: &P) {
86        let mut self_inner = (**self).clone();
87        self_inner.merge_with_policy((*other).clone(), policy);
88        *self = Rc::new(self_inner);
89    }
90}
91
92/// `DeepMerge` implementation for `Arc<T>`.
93///
94/// Creates a new `Arc` with the merged value since `Arc` is immutable.
95/// Requires `T: Clone` to extract and clone the inner values.
96/// Useful for thread-safe sharing of merged configuration data.
97///
98/// # Examples
99///
100/// ```rust
101/// use std::sync::Arc;
102/// use std::collections::HashMap;
103/// use deepmerge::prelude::*;
104///
105/// #[derive(DeepMerge, Clone)]
106/// struct SharedConfig {
107///     tags: Vec<String>,
108///     settings: HashMap<String, i32>,
109/// }
110///
111/// let mut arc_config = Arc::new(SharedConfig {
112///     tags: vec!["web".to_string()],
113///     settings: [("timeout".to_string(), 30)].into(),
114/// });
115///
116/// let other_config = Arc::new(SharedConfig {
117///     tags: vec!["api".to_string()],
118///     settings: [("retries".to_string(), 3)].into(),
119/// });
120///
121/// <Arc<SharedConfig> as DeepMerge<DefaultPolicy>>::merge_with_policy(&mut arc_config, other_config, &DefaultPolicy);
122///
123/// // Note: Arc is immutable, so merge creates a new Arc
124/// // Vec merges by appending with DefaultPolicy
125/// assert_eq!(arc_config.tags, vec!["web".to_string(), "api".to_string()]);
126/// // HashMap overlays - both entries are present
127/// assert_eq!(arc_config.settings.get("timeout"), Some(&30));
128/// assert_eq!(arc_config.settings.get("retries"), Some(&3));
129/// ```
130#[cfg(feature = "alloc")]
131impl<T: DeepMerge<P> + Clone, P: Policy> DeepMerge<P> for Arc<T> {
132    fn merge_with_policy(&mut self, other: Self, policy: &P) {
133        let mut self_inner = (**self).clone();
134        self_inner.merge_with_policy((*other).clone(), policy);
135        *self = Arc::new(self_inner);
136    }
137}
138
139/// `DeepMerge` implementation for `Cow<'_, str>`.
140///
141/// Converts both borrowed and owned string data to `String` for merging,
142/// then stores the result as `Cow::Owned`. This allows seamless merging
143/// of string data regardless of whether it's borrowed or owned.
144///
145/// # Examples
146///
147/// ```rust
148/// use std::borrow::Cow;
149/// use deepmerge::prelude::*;
150///
151/// // Concat: concatenate strings
152/// let policy = ComposedPolicy::new(DefaultPolicy)
153///     .with_string_merge(StringMerge::Concat);
154///
155/// let mut cow_str: Cow<str> = Cow::Borrowed("Hello");
156/// let other_cow: Cow<str> = Cow::Owned(" World".to_string());
157///
158/// cow_str.merge_with_policy(other_cow, &policy);
159/// assert_eq!(cow_str, "Hello World");
160/// assert!(matches!(cow_str, Cow::Owned(_))); // Result is owned
161///
162/// // ConcatWithSep: concatenate with separator
163/// let policy = ComposedPolicy::new(DefaultPolicy)
164///     .with_string_merge(StringMerge::ConcatWithSep(", "));
165///
166/// let mut items: Cow<str> = Cow::Borrowed("apple");
167/// let more_items: Cow<str> = Cow::Borrowed("banana");
168///
169/// items.merge_with_policy(more_items, &policy);
170/// assert_eq!(items, "apple, banana");
171/// ```
172#[cfg(feature = "alloc")]
173impl<P: Policy> DeepMerge<P> for Cow<'_, str> {
174    fn merge_with_policy(&mut self, other: Self, policy: &P) {
175        let mut self_string = (*self).to_string();
176        let other_string = other.to_string();
177        self_string.merge_with_policy(other_string, policy);
178        *self = Cow::Owned(self_string);
179    }
180}
181
182/// `DeepMerge` implementation for `Cow<'_, [T]>`.
183///
184/// Converts both borrowed and owned slice data to `Vec<T>` for merging,
185/// then stores the result as `Cow::Owned`. This allows seamless merging
186/// of slice data regardless of whether it's borrowed or owned.
187/// Requires `T: Clone` to convert slices to vectors.
188///
189/// # Examples
190///
191/// ```rust
192/// use std::borrow::Cow;
193/// use deepmerge::prelude::*;
194///
195/// // Append: concatenate sequences
196/// let policy = ComposedPolicy::new(DefaultPolicy)
197///     .with_sequence_merge(SequenceMerge::Append);
198///
199/// let mut cow_slice: Cow<[i32]> = Cow::Borrowed(&[1, 2, 3]);
200/// let other_cow: Cow<[i32]> = Cow::Owned(vec![4, 5]);
201///
202/// cow_slice.merge_with_policy(other_cow, &policy);
203/// assert_eq!(cow_slice.as_ref(), &[1, 2, 3, 4, 5]);
204/// assert!(matches!(cow_slice, Cow::Owned(_))); // Result is owned
205///
206/// // Prepend: add new elements at the beginning
207/// let policy = ComposedPolicy::new(DefaultPolicy)
208///     .with_sequence_merge(SequenceMerge::Prepend);
209///
210/// let mut tags: Cow<[&str]> = Cow::Borrowed(&["web", "api"]);
211/// let more_tags: Cow<[&str]> = Cow::Borrowed(&["mobile"]);
212///
213/// tags.merge_with_policy(more_tags, &policy);
214/// let result: Vec<_> = tags.iter().collect();
215/// assert_eq!(result, vec![&"mobile", &"web", &"api"]);
216/// ```
217#[cfg(feature = "alloc")]
218impl<T: Clone, P: Policy> DeepMerge<P> for Cow<'_, [T]> {
219    fn merge_with_policy(&mut self, other: Self, policy: &P) {
220        let mut self_vec = self.to_vec();
221        let other_vec = other.to_vec();
222        self_vec.merge_with_policy(other_vec, policy);
223        *self = Cow::Owned(self_vec);
224    }
225}