# DeepMerge
A flexible deep merge library for Rust with policy-driven merging and derive macros featuring typed attributes.
## Features
- **Policy-driven merging**: Configure how different types should be merged
- **Derive macro support**: Automatically implement `DeepMerge` for your structs
- **Typed attributes**: Use identifiers instead of string literals for better compile-time checking
- **Flexible attribute syntax**: Mix string literals, identifiers, and path expressions
- **Precedence rules**: Field-level > struct-level > caller-provided policies
- **Multiple merge strategies**: Append, prepend, union, concatenation, replacement, and more
- **No-std compatible**: Works without the standard library (with `alloc`)
## Quick Start
Add this to your `Cargo.toml`:
```toml
[dependencies]
deepmerge = { version = "0.1", features = ["derive"] }
```
## Usage Examples
### Basic Usage with Typed Attributes
```rust
use deepmerge::prelude::*;
// Use clean identifier syntax instead of string literals
#[derive(DeepMerge, Debug)]
#[merge(policy(string = concat, sequence = append, bool = true_wins))]
struct Config {
pub title: String,
pub tags: Vec<String>,
pub enabled: bool,
// Field-level override
#[merge(string = keep)]
pub version: String,
}
let mut config = Config {
title: "My App".to_string(),
tags: vec!["web".to_string()],
enabled: false,
version: "1.0".to_string(),
};
let update = Config {
title: " v2".to_string(),
tags: vec!["api".to_string()],
enabled: true,
version: "2.0".to_string(),
};
config.merge_with_policy(update, &DefaultPolicy);
// Results:
// title: "My App v2" (concatenated)
// tags: ["web", "api"] (appended)
// enabled: true (true wins)
// version: "1.0" (kept original due to field-level override)
```
### Supported Attribute Syntax
```rust
use deepmerge::prelude::*;
#[derive(DeepMerge)]
#[merge(policy(
// String literals (traditional)
string = "concat",
// Identifiers (new, cleaner syntax)
sequence = append,
bool = true_wins,
number = sum,
// Mixed syntax is supported
map = "overlay"
))]
struct FlexibleConfig { /* ... */ }
```
### Available Merge Policies
**String Policies**: `concat`, `keep`, `replace`
**Sequence Policies**: `append`, `prepend`, `union`, `extend`, `intersect`
**Boolean Policies**: `true_wins`, `false_wins`, `replace`, `keep`
**Number Policies**: `sum`, `max`, `min`, `replace`, `keep`
**Map Policies**: `overlay`, `union`, `left`, `right`
**Option Policies**: `take`, `preserve`, `or_left`
### Policy Precedence
Policies are applied in this order of precedence:
1. **Field-level attributes** (highest priority)
2. **Struct-level attributes**
3. **Caller-provided policies** (lowest priority)
## Advanced Features
### Future Path Expression Support
The infrastructure is ready for advanced path expressions:
```rust
// Coming soon:
// #[merge(policy(string = StringMerge::ConcatWithSep(", ")))]
```
### Condition Policies with Key Extractors
```rust
// Coming soon:
// #[merge(policy(condition = changed, changed_by = "key_extractor_fn"))]
```
## Feature Flags
- `derive` (default): Enable the derive macro
- `std` (default): Enable standard library support
- `alloc` (default): Enable allocation support
- `indexmap`: Add support for `IndexMap` types
## License
Licensed under either of:
- Apache License, Version 2.0
- MIT License
at your option.
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.