version_track/
lib.rs

1//! # Version Track
2//!
3//! This simple crate provides an easy way to track and compare changes to value that are too expensive to compare
4//! directly. This crate will track mutable changes to a value, and automatically increment a version number on every
5//! modification. Any comparison will then compare the internal version number, instead of having to do a full
6//! comparison on a complex data structure.
7//!
8//! Tracking is performed by two values, the first is a V4 [`uuid::Uuid`], and the second is a [usize] counter. The
9//! [`uuid::Uuid`] is generated once¹ per value being tracked, and then each subsequent mutable reference access
10//! increments the counter. This allows for tracking multiple distinct values independently, using the [`uuid::Uuid`] to
11//! track the different values across increments, and the counter to track direct changes to the value.
12//!
13//! The crate provides two ways to track versions. The first way is using a pointer-like wrapper around another value.
14//! This is the easiest way to use this crate, but at times may result in extra unneeded version increments. To address
15//! this it is possible to create a version tracker manually to be added as a field on a struct or stored separately.
16//!
17//! ¹ The [`uuid::Uuid`] value may be regenerated is the [usize] counter wraps back to zero.
18//!
19//! ## Basic Example
20//!
21//! Any value can be wrapped with [`Versioned<T>`], and because [`Versioned<T>`] implements [`std::ops::Deref`],
22//! [`std::ops::DerefMut`], [`std::convert::AsRef`] and [`std::convert::AsMut`], the wrapped value can be used in most
23//! places that the wrapped value is used.
24//!
25//! ```
26//! use version_track::Versioned;
27//!
28//! let mut tracked_value = Versioned::new(String::from("foo"));
29//! let current_version = tracked_value.version();
30//! tracked_value.push_str("bar");
31//!
32//! assert_ne!(current_version, tracked_value.version());
33//! assert_eq!(*tracked_value, "foobar");
34//! ```
35//!
36//! ## Direct Use Example
37//!
38//! Sometimes more control over the version is desired, or wrapping the value to be tracked is not possible. In those
39//! cases [Version] can be used directly. In this case, it is up to the developer to decide on when a change has
40//! occurred. This can be useful to only track some modifications to a value, or to only increment once when multiple
41//! mutable references are needed.
42//!
43//! ```
44//! use version_track::Version;
45//!
46//! let mut value = String::from("foo");
47//! let mut version = Version::new();
48//! let current_version = version;
49//!
50//! value.push_str("bar");
51//! version.increment();
52//!
53//! assert_ne!(current_version, version);
54//! assert_eq!(value, "foobar");
55//! ```
56
57mod version;
58mod versioned;
59
60pub use crate::{
61	version::{Version, SENTINEL_VERSION},
62	versioned::Versioned,
63};