1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
//! # Serde Merge
//!
//! `serde_merge` is a set of methods on top of [serde](https://github.com/serde-rs/serde)
//! for merging some serializable types.
use crate::error::Result;
use serde::{de::DeserializeOwned, Serialize};

pub mod error;
mod utils;

/// Alias for a `serde_json::Map<String, serde_json::Value>`.
///
/// Represents default type used in this library.
pub type Map = serde_json::Map<String, serde_json::Value>;

/// Merge two types into `serde_merge::Map`, returns `serde_merge::Result<serde_merge::Map>`.
///
/// Merge `R` into `L`. `R` override matching keys of `L`.
/// Both `L` and `R` have to implement `serde::Serialize`.
pub fn mmerge<L, R>(left: L, right: R) -> Result<Map>
where
    L: Serialize,
    R: Serialize,
{
    let mut left_map = utils::to_map(&left)?;
    let right_map = utils::to_map(&right)?;
    left_map.extend(right_map);

    Ok(left_map)
}

/// Merge two types into given type `T`, returns `serde_merge::Result<T>`. ( *Recommended* )
///
/// Works the same as `serde_merge::mmerge` but convert result to given type `T`.
/// `T` has to implement `serde::Serialize` and `serde::de::DeserializeOwned`.
pub fn tmerge<L, R, T>(left: L, right: R) -> Result<T>
where
    L: Serialize,
    R: Serialize,
    T: Serialize + DeserializeOwned,
{
    let merged_map = mmerge(left, right)?;
    utils::from_map(&merged_map)
}

/// Merge two types into given type `T`, returns `serde_merge::Result<T>`. ( *Recommended* )
///
/// Works the same as `serde_merge::tmerge` except that `right`'s `Option::None` member
/// will not overwrite the corresponding value in `left`.
/// `T` has to implement `serde::Serialize` and `serde::de::DeserializeOwned`.
pub fn omerge<L, R, T>(left: L, right: R) -> Result<T>
where
    L: Serialize,
    R: Serialize,
    T: Serialize + DeserializeOwned,
{
    let mut left_map = utils::to_map(&left)?;
    let mut right_map = utils::to_map(&right)?;
    right_map.retain(|_, v| !v.is_null());
    left_map.extend(right_map);

    utils::from_map(&left_map)
}