From acca78bac2412dcd9ce23f80b30e92ae784859f8 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Mon, 20 Apr 2026 16:02:16 -0400 Subject: [PATCH 1/2] docs: cover remaining public API doc comments --- src/patch/format.rs | 5 +++++ src/patch/mod.rs | 6 ++++++ src/patch_set/mod.rs | 16 ++++++++++++++-- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/patch/format.rs b/src/patch/format.rs index 1e7156f..7b56cb0 100644 --- a/src/patch/format.rs +++ b/src/patch/format.rs @@ -76,6 +76,11 @@ impl PatchFormatter { PatchDisplay { f: self, patch } } + /// Writes a formatted patch into a writer. + /// + /// This is the byte-oriented equivalent of [`fmt_patch`](Self::fmt_patch) + /// for callers that want to stream the formatted patch into an `io::Write` + /// sink instead of going through `Display`. #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub fn write_patch_into + ?Sized, W: io::Write>( diff --git a/src/patch/mod.rs b/src/patch/mod.rs index 6669016..c17634a 100644 --- a/src/patch/mod.rs +++ b/src/patch/mod.rs @@ -99,6 +99,7 @@ impl<'a, T: ToOwned + ?Sized> Patch<'a, T> { &self.hunks } + /// Returns a patch that transforms the modified text back into the original text. pub fn reverse(&self) -> Patch<'_, T> { let hunks = self.hunks.iter().map(Hunk::reverse).collect(); Patch { @@ -438,6 +439,11 @@ impl Clone for Line<'_, T> { } impl Line<'_, T> { + /// Reverses the direction of this diff line. + /// + /// * Context lines are unchanged + /// * Insertions become deletions + /// * Deletions become insertions pub fn reverse(&self) -> Self { match self { Line::Context(s) => Line::Context(s), diff --git a/src/patch_set/mod.rs b/src/patch_set/mod.rs index 3efc64e..2b341c2 100644 --- a/src/patch_set/mod.rs +++ b/src/patch_set/mod.rs @@ -285,17 +285,29 @@ pub enum FileOperation<'a, T: ToOwned + ?Sized> { /// /// Usually, the caller needs to strip the prefix from the paths to determine. Modify { + /// The original path before the modification. original: Cow<'a, T>, + /// The resulting path after the modification. modified: Cow<'a, T>, }, /// Rename a file (move from `from` to `to`, delete `from`). /// /// Only produced when git extended headers explicitly indicate a rename. - Rename { from: Cow<'a, T>, to: Cow<'a, T> }, + Rename { + /// The source path before the rename. + from: Cow<'a, T>, + /// The destination path after the rename. + to: Cow<'a, T>, + }, /// Copy a file (copy from `from` to `to`, keep `from`). /// /// Only produced when git extended headers explicitly indicate a copy. - Copy { from: Cow<'a, T>, to: Cow<'a, T> }, + Copy { + /// The source path that is copied from. + from: Cow<'a, T>, + /// The destination path that is copied to. + to: Cow<'a, T>, + }, } impl Clone for FileOperation<'_, T> { From 6f62d3f2e857c7b13ac9c8f1c0dc899c1048fa45 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Mon, 20 Apr 2026 16:02:27 -0400 Subject: [PATCH 2/2] docs: add examples for high-value public APIs --- src/apply.rs | 28 ++++++++++++++++++++++ src/binary/mod.rs | 57 ++++++++++++++++++++++++++++++++++++++++++++ src/diff/mod.rs | 58 +++++++++++++++++++++++++++++++++++++++++++++ src/merge/mod.rs | 57 ++++++++++++++++++++++++++++++++++++++++++++ src/patch/format.rs | 27 ++++++++++++++++++++- 5 files changed, 226 insertions(+), 1 deletion(-) diff --git a/src/apply.rs b/src/apply.rs index bc1097a..779cb2b 100644 --- a/src/apply.rs +++ b/src/apply.rs @@ -108,6 +108,34 @@ pub fn apply(base_image: &str, patch: &Patch<'_, str>) -> Result) -> Result, ApplyError> { let mut image: Vec<_> = LineIter::new(base_image) .map(ImageLine::Unpatched) diff --git a/src/binary/mod.rs b/src/binary/mod.rs index 4eea36a..07b9f4f 100644 --- a/src/binary/mod.rs +++ b/src/binary/mod.rs @@ -81,6 +81,36 @@ impl<'a> BinaryPatch<'a> { /// - If the forward block is `Delta`: applies delta instructions to `original`. /// /// Unlike `git apply`, this doesn't validate the original content hash. + /// + /// # Examples + /// + /// ``` + /// use diffy::patch_set::ParseOptions; + /// use diffy::patch_set::PatchSet; + /// + /// let input = b"\ + /// diff --git a/blob b/blob + /// index e69de29..0000000 100644 + /// GIT binary patch + /// literal 10 + /// UcmV+l0QLU>0RjUA1qKHQ2>`DEE&u=k + /// + /// literal 0 + /// KcmV+b0RR6000031 + /// + /// "; + /// + /// let patch = PatchSet::parse_bytes(input, ParseOptions::gitdiff()) + /// .next() + /// .unwrap() + /// .unwrap(); + /// let binary = patch.patch().as_binary().unwrap(); + /// + /// assert_eq!( + /// binary.apply(&[]).unwrap(), + /// b"\0\x01\x02\x03\x04\x05\x06\x07\x08\t" + /// ); + /// ``` #[cfg(feature = "binary")] #[cfg_attr(docsrs, doc(cfg(feature = "binary")))] pub fn apply(&self, original: &[u8]) -> Result, BinaryPatchParseError> { @@ -96,6 +126,33 @@ impl<'a> BinaryPatch<'a> { /// - If the reverse block is `Delta`: applies delta instructions to `modified`. /// /// Unlike `git apply`, this doesn't validate the modified content hash. + /// + /// # Examples + /// + /// ``` + /// use diffy::patch_set::ParseOptions; + /// use diffy::patch_set::PatchSet; + /// + /// let input = b"\ + /// diff --git a/blob b/blob + /// index e69de29..0000000 100644 + /// GIT binary patch + /// literal 10 + /// UcmV+l0QLU>0RjUA1qKHQ2>`DEE&u=k + /// + /// literal 0 + /// KcmV+b0RR6000031 + /// + /// "; + /// + /// let patch = PatchSet::parse_bytes(input, ParseOptions::gitdiff()) + /// .next() + /// .unwrap() + /// .unwrap(); + /// let binary = patch.patch().as_binary().unwrap(); + /// + /// assert_eq!(binary.apply_reverse(&[]).unwrap(), b""); + /// ``` #[cfg(feature = "binary")] #[cfg_attr(docsrs, doc(cfg(feature = "binary")))] pub fn apply_reverse(&self, modified: &[u8]) -> Result, BinaryPatchParseError> { diff --git a/src/diff/mod.rs b/src/diff/mod.rs index c634a0a..861f638 100644 --- a/src/diff/mod.rs +++ b/src/diff/mod.rs @@ -47,6 +47,44 @@ where } /// A collection of options for modifying the way a diff is performed +/// +/// # Examples +/// +/// ``` +/// use diffy::DiffOptions; +/// +/// let mut options = DiffOptions::new(); +/// options +/// .set_context_len(1) +/// .set_original_filename("before.txt") +/// .set_modified_filename("after.txt"); +/// +/// let patch = options.create_patch( +/// "\ +/// alpha +/// beta +/// gamma +/// ", +/// "\ +/// alpha +/// BETA +/// gamma +/// ", +/// ); +/// +/// assert_eq!( +/// patch.to_string(), +/// "\ +/// --- before.txt +/// +++ after.txt +/// @@ -1,3 +1,3 @@ +/// alpha +/// -beta +/// +BETA +/// gamma +/// ", +/// ); +/// ``` #[derive(Debug)] pub struct DiffOptions { compact: bool, @@ -234,6 +272,26 @@ pub fn create_patch<'a>(original: &'a str, modified: &'a str) -> Patch<'a, str> } /// Create a patch between two potentially non-utf8 texts +/// +/// # Examples +/// +/// ``` +/// use diffy::create_patch_bytes; +/// +/// let patch = create_patch_bytes(b"alpha\nbeta\n", b"alpha\nBETA\n"); +/// +/// assert_eq!( +/// patch.to_bytes(), +/// b"\ +/// --- original +/// +++ modified +/// @@ -1,2 +1,2 @@ +/// alpha +/// -beta +/// +BETA +/// ", +/// ); +/// ``` pub fn create_patch_bytes<'a>(original: &'a [u8], modified: &'a [u8]) -> Patch<'a, [u8]> { DiffOptions::default().create_patch_bytes(original, modified) } diff --git a/src/merge/mod.rs b/src/merge/mod.rs index 7e1f001..15744df 100644 --- a/src/merge/mod.rs +++ b/src/merge/mod.rs @@ -116,6 +116,31 @@ pub enum ConflictStyle { } /// A collection of options for modifying the way a merge is performed +/// +/// # Examples +/// +/// ``` +/// use diffy::ConflictStyle; +/// use diffy::MergeOptions; +/// +/// let mut options = MergeOptions::new(); +/// options +/// .set_conflict_style(ConflictStyle::Merge) +/// .set_conflict_marker_length(5); +/// +/// let conflict = options.merge("value\n", "ours\n", "theirs\n").unwrap_err(); +/// +/// assert_eq!( +/// conflict, +/// "\ +/// <<<<< ours +/// ours +/// ===== +/// theirs +/// >>>>> theirs +/// ", +/// ); +/// ``` #[derive(Debug)] pub struct MergeOptions { conflict_marker_length: usize, @@ -272,6 +297,38 @@ pub fn merge<'a>(ancestor: &'a str, ours: &'a str, theirs: &'a str) -> Result( ancestor: &'a [u8], ours: &'a [u8], diff --git a/src/patch/format.rs b/src/patch/format.rs index 7b56cb0..4cb8e43 100644 --- a/src/patch/format.rs +++ b/src/patch/format.rs @@ -13,7 +13,32 @@ use super::Line; use super::Patch; use super::NO_NEWLINE_AT_EOF; -/// Struct used to adjust the formatting of a `Patch` +/// Formats patches for display or writing into byte streams. +/// +/// # Examples +/// +/// ``` +/// use diffy::create_patch; +/// use diffy::PatchFormatter; +/// +/// let patch = create_patch("alpha\nbeta\n", "ALPHA\nbeta\n"); +/// let formatter = PatchFormatter::new().missing_newline_message(false); +/// let mut output = Vec::new(); +/// +/// formatter.write_patch_into(&patch, &mut output).unwrap(); +/// +/// assert_eq!( +/// String::from_utf8(output).unwrap(), +/// "\ +/// --- original +/// +++ modified +/// @@ -1,2 +1,2 @@ +/// -alpha +/// +ALPHA +/// beta +/// ", +/// ); +/// ``` #[derive(Debug)] pub struct PatchFormatter { #[cfg(feature = "color")]