deepmerge 0.1.0

Deep merge functionality with policy-driven merging and derive macro support
Documentation
//! Forwarding implementations for smart pointers and borrowed types

use crate::policy::Policy;
use crate::DeepMerge;

#[cfg(feature = "alloc")]
use alloc::{boxed::Box, rc::Rc, sync::Arc, borrow::Cow, string::ToString};

/// `DeepMerge` implementation for `Box<T>`.
///
/// Forwards the merge operation to the boxed value, allowing seamless
/// merging of heap-allocated values.
///
/// # Examples
///
/// ```rust
/// use std::collections::HashMap;
/// use deepmerge::prelude::*;
///
/// #[derive(DeepMerge)]
/// #[merge(policy(string = concat))]
/// struct Config {
///     name: String,
///     data: HashMap<String, i32>,
/// }
///
/// let mut boxed_config = Box::new(Config {
///     name: "app".to_string(),
///     data: [("count".to_string(), 5)].into(),
/// });
///
/// let other_config = Box::new(Config {
///     name: "_v2".to_string(), 
///     data: [("users".to_string(), 100)].into(),
/// });
///
/// boxed_config.merge_with_policy(other_config, &DefaultPolicy);
///
/// assert_eq!(boxed_config.name, "app_v2");
/// assert_eq!(boxed_config.data.get("count"), Some(&5));
/// assert_eq!(boxed_config.data.get("users"), Some(&100));
/// ```
#[cfg(feature = "alloc")]
impl<T: DeepMerge<P>, P: Policy> DeepMerge<P> for Box<T> {
    fn merge_with_policy(&mut self, other: Self, policy: &P) {
        self.as_mut().merge_with_policy(*other, policy);
    }
}

/// `DeepMerge` implementation for `Rc<T>`.
///
/// Creates a new `Rc` with the merged value since `Rc` is immutable.
/// Requires `T: Clone` to extract and clone the inner values.
///
/// # Examples
///
/// ```rust
/// use std::rc::Rc;
/// use deepmerge::prelude::*;
///
/// #[derive(DeepMerge, Clone)]
/// struct Config {
///     version: String,
///     count: i32,
/// }
///
/// let mut rc_config = Rc::new(Config {
///     version: "v1".to_string(),
///     count: 5,
/// });
///
/// let other_config = Rc::new(Config {
///     version: "v2".to_string(),
///     count: 10,
/// });
///
/// <Rc<Config> as DeepMerge<DefaultPolicy>>::merge_with_policy(&mut rc_config, other_config, &DefaultPolicy);
///
/// // Note: Rc is immutable, so merge creates a new Rc
/// assert_eq!(rc_config.version, "v2");
/// assert_eq!(rc_config.count, 10);
/// ```
#[cfg(feature = "alloc")]
impl<T: DeepMerge<P> + Clone, P: Policy> DeepMerge<P> for Rc<T> {
    fn merge_with_policy(&mut self, other: Self, policy: &P) {
        let mut self_inner = (**self).clone();
        self_inner.merge_with_policy((*other).clone(), policy);
        *self = Rc::new(self_inner);
    }
}

/// `DeepMerge` implementation for `Arc<T>`.
///
/// Creates a new `Arc` with the merged value since `Arc` is immutable.
/// Requires `T: Clone` to extract and clone the inner values.
/// Useful for thread-safe sharing of merged configuration data.
///
/// # Examples
///
/// ```rust
/// use std::sync::Arc;
/// use std::collections::HashMap;
/// use deepmerge::prelude::*;
///
/// #[derive(DeepMerge, Clone)]
/// struct SharedConfig {
///     tags: Vec<String>,
///     settings: HashMap<String, i32>,
/// }
///
/// let mut arc_config = Arc::new(SharedConfig {
///     tags: vec!["web".to_string()],
///     settings: [("timeout".to_string(), 30)].into(),
/// });
///
/// let other_config = Arc::new(SharedConfig {
///     tags: vec!["api".to_string()],
///     settings: [("retries".to_string(), 3)].into(),
/// });
///
/// <Arc<SharedConfig> as DeepMerge<DefaultPolicy>>::merge_with_policy(&mut arc_config, other_config, &DefaultPolicy);
///
/// // Note: Arc is immutable, so merge creates a new Arc
/// // Vec merges by appending with DefaultPolicy
/// assert_eq!(arc_config.tags, vec!["web".to_string(), "api".to_string()]);
/// // HashMap overlays - both entries are present
/// assert_eq!(arc_config.settings.get("timeout"), Some(&30));
/// assert_eq!(arc_config.settings.get("retries"), Some(&3));
/// ```
#[cfg(feature = "alloc")]
impl<T: DeepMerge<P> + Clone, P: Policy> DeepMerge<P> for Arc<T> {
    fn merge_with_policy(&mut self, other: Self, policy: &P) {
        let mut self_inner = (**self).clone();
        self_inner.merge_with_policy((*other).clone(), policy);
        *self = Arc::new(self_inner);
    }
}

/// `DeepMerge` implementation for `Cow<'_, str>`.
///
/// Converts both borrowed and owned string data to `String` for merging,
/// then stores the result as `Cow::Owned`. This allows seamless merging
/// of string data regardless of whether it's borrowed or owned.
///
/// # Examples
///
/// ```rust
/// use std::borrow::Cow;
/// use deepmerge::prelude::*;
///
/// // Concat: concatenate strings
/// let policy = ComposedPolicy::new(DefaultPolicy)
///     .with_string_merge(StringMerge::Concat);
///
/// let mut cow_str: Cow<str> = Cow::Borrowed("Hello");
/// let other_cow: Cow<str> = Cow::Owned(" World".to_string());
///
/// cow_str.merge_with_policy(other_cow, &policy);
/// assert_eq!(cow_str, "Hello World");
/// assert!(matches!(cow_str, Cow::Owned(_))); // Result is owned
///
/// // ConcatWithSep: concatenate with separator
/// let policy = ComposedPolicy::new(DefaultPolicy)
///     .with_string_merge(StringMerge::ConcatWithSep(", "));
///
/// let mut items: Cow<str> = Cow::Borrowed("apple");
/// let more_items: Cow<str> = Cow::Borrowed("banana");
///
/// items.merge_with_policy(more_items, &policy);
/// assert_eq!(items, "apple, banana");
/// ```
#[cfg(feature = "alloc")]
impl<P: Policy> DeepMerge<P> for Cow<'_, str> {
    fn merge_with_policy(&mut self, other: Self, policy: &P) {
        let mut self_string = (*self).to_string();
        let other_string = other.to_string();
        self_string.merge_with_policy(other_string, policy);
        *self = Cow::Owned(self_string);
    }
}

/// `DeepMerge` implementation for `Cow<'_, [T]>`.
///
/// Converts both borrowed and owned slice data to `Vec<T>` for merging,
/// then stores the result as `Cow::Owned`. This allows seamless merging
/// of slice data regardless of whether it's borrowed or owned.
/// Requires `T: Clone` to convert slices to vectors.
///
/// # Examples
///
/// ```rust
/// use std::borrow::Cow;
/// use deepmerge::prelude::*;
///
/// // Append: concatenate sequences
/// let policy = ComposedPolicy::new(DefaultPolicy)
///     .with_sequence_merge(SequenceMerge::Append);
///
/// let mut cow_slice: Cow<[i32]> = Cow::Borrowed(&[1, 2, 3]);
/// let other_cow: Cow<[i32]> = Cow::Owned(vec![4, 5]);
///
/// cow_slice.merge_with_policy(other_cow, &policy);
/// assert_eq!(cow_slice.as_ref(), &[1, 2, 3, 4, 5]);
/// assert!(matches!(cow_slice, Cow::Owned(_))); // Result is owned
///
/// // Prepend: add new elements at the beginning
/// let policy = ComposedPolicy::new(DefaultPolicy)
///     .with_sequence_merge(SequenceMerge::Prepend);
///
/// let mut tags: Cow<[&str]> = Cow::Borrowed(&["web", "api"]);
/// let more_tags: Cow<[&str]> = Cow::Borrowed(&["mobile"]);
///
/// tags.merge_with_policy(more_tags, &policy);
/// let result: Vec<_> = tags.iter().collect();
/// assert_eq!(result, vec![&"mobile", &"web", &"api"]);
/// ```
#[cfg(feature = "alloc")]
impl<T: Clone, P: Policy> DeepMerge<P> for Cow<'_, [T]> {
    fn merge_with_policy(&mut self, other: Self, policy: &P) {
        let mut self_vec = self.to_vec();
        let other_vec = other.to_vec();
        self_vec.merge_with_policy(other_vec, policy);
        *self = Cow::Owned(self_vec);
    }
}