A lightweight, zero-dependency struct diffing library which allows changed fields to be collected and applied

Overview

structdiff

A lightweight, zero-dependency struct diffing library which allows changed fields to be collected and applied. Derive Difference on a struct, then use the StructDiff trait to make and apply diffs.

Example:

use structdiff::{Difference, StructDiff};

#[derive(Debug, PartialEq, Clone, Difference)]
struct Example {
    field1: f64,
    #[difference(skip)]
    field2: Vec<i32>,
    field3: String,
}

let first = Example {
    field1: 0.0,
    field2: Vec::new(),
    field3: String::from("Hello Diff"),
};

let second = Example {
    field1: 3.14,
    field2: vec![1],
    field3: String::from("Hello Diff"),
};

let diffs = first.diff(&second);
// diffs is now a Vec of differences, with length 
// equal to number of changed/unskipped fields
assert_eq!(diffs.len(), 1);

let diffed = first.apply(diffs);
// diffed is now equal to second, except for skipped field
assert_eq!(diffed.field1, second.field1);
assert_eq!(diffed.field3, second.field3);
assert_ne!(diffed, second); 

For more examples take a look at integration tests

Derive macro attributes

  • #[difference(skip)] - Do not consider this field when creating a diff
  • #[difference(recurse)] - Generate a StructDiff for this field when creating a diff
  • #[difference(collection_strategy = "{}")
    • unordered_hash - Generates a changeset for collections of items which implement Hash + Eq, rather than cloning the entire list. (currently works for Vec, BTreeSet, LinkedList, and HashSet)

Optional features

  • [nanoserde, serde] - Serialization of Difference derived associated types

Development status

This is being actively worked on (especially on collections strategies). PRs will be accepted for either more tests or functionality.

You might also like...
Parse command line arguments by defining a struct.

StructOpt Parse command line arguments by defining a struct. It combines clap with custom derive. Documentation Find it on Docs.rs. You can also check

Convert a unix timestamp (seconds) to a struct {year, month, day, hour, minute, second, weekday}.

uts2ts uts2ts is a simple function that does only one thing: It converts a unix timestamp to something slightly more useful. ;-) So why then? Well, it

Statically verified Rust struct field names as strings.

field Statically verified struct field names as strings. See the documentation for more details. Installation Add the following to your Cargo manifest

A high-performance WebSocket integration library for streaming public market data. Used as a key dependency of the `barter-rs` project.

Barter-Data A high-performance WebSocket integration library for streaming public market data from leading cryptocurrency exchanges - batteries includ

Dynamic dependency injection library for rust.

DDI (dynamic dependency injection) This library provides a generic dependency injection container that can be easily integrated into any application a

Track and query Cargo dependency graphs.

cargo-guppy: track and query dependency graphs This repository contains the source code for: guppy: a library for performing queries on Cargo dependen

Generate a dependency list to thank them on README.

thanks-dependencies This generates list of dependencies. I think it's better to publish dependencies explicitly on documentation. Of course users can

python dependency vulnerability scanner, written in Rust.
python dependency vulnerability scanner, written in Rust.

🐍 Pyscan A dependency vulnerability scanner for your python projects, straight from the terminal. 🚀 blazingly fast scanner that can be used within l

Rudi - an out-of-the-box dependency injection framework for Rust.

Rudi Rudi - an out-of-the-box dependency injection framework for Rust. use rudi::{Context, Singleton, Transient}; // Register `fn(cx) - A { A }` as

Comments
  • Collections Support

    Collections Support

    Need to add different strategies for handling collections. Hashmaps/sets are straightforward, but need to decide on better ways than == for comparing Vecs/Arrays/LinkedLists/Maps (and allow recursion, probably).

    • [x] unordered/hashable strategy - Turn any two array-like collections into a hashset and compare
    • [x] hashmap/btreemap impl
    • [ ] ordered with minimal moves
    opened by knickish 0
Owner
null
Rust TUI library - Clipping region is a set of min/max x/y values applied to the existing region

TinyBit Clipping region is a set of min/max x/y values applied to the existing region A TUI lib This is not yet production ready T O D O TODO: bugs: T

Togglebit 13 May 3, 2022
List public items (public API) of library crates. Enables diffing public API between releases.

cargo-public-items List public items (the public API) of a Rust library crate by analyzing the rustdoc JSON of the crate. Automatically builds the rus

Martin Nordholts 203 Dec 31, 2022
zero-dependency 3d math library in rust

dualquat A lightweight, zero-dependency 3d math library for use in Dual Quaternion based physics simulation. Capable of representing and transforming

null 4 Nov 11, 2022
Run if inputs have changed, otherwise use cache

Boost Why Boost? Our planet is burning, and everywhere I look I see CI pipelines repeating work that has already been done. Tools such as TurboRepo, N

Stuart Harris 6 Jul 28, 2022
Bit fields and masks for rust!

ubits Bit fields and masks for rust! Provides a macro for generating bit field types complete with flags and some helpful trait implementations. Suppo

Adam Romano 2 Sep 16, 2022
Command-line tool that provides a workflow for extending, editing, diffing, and writing to vim-style grep lines.

Grug Grug is a command-line tool that provides a workflow for expanding, editing, diffing, and writing edits to files using vim-styled grep lines (suc

null 4 Apr 25, 2023
A crate providing a MemoryCell struct, which stores a current and previous value.

memcell What is a MemoryCell? A MemoryCell is a struct containing both a current and optional previous value. Definition #[derive(Debug, Clone)] pub s

Imajin 9 Nov 21, 2022
A zero-dependency crate for writing repetitive code easier and faster.

akin A zero-dependency crate for writing repetitive code easier and faster. Check Syntax for information about how to use it. Why? Example Syntax NONE

LyonSyonII 36 Dec 29, 2022
A truly zero-dependency crate providing quick, easy, reliable, and scalable access to the name "jordin"

jordin Finally! A truly zero-dependency crate providing quick, easy, reliable, and scalable access to the name "jordin". Additionally, this one-of-a-k

jordin 2 Aug 4, 2022
A super simple /sbin/init for Linux which allows running one and only one program

Summary High-performance /sbin/init program for Linux This is designed to do literally nothing but accept binaries over the network and run them as a

null 19 Dec 4, 2023