pub struct HunkApplier<'a> { /* private fields */ }Expand description
An iterator that applies hunks from a patch one by one.
This struct provides fine-grained control over the patch application process. It allows you to apply hunks sequentially, inspect the intermediate state of the content, and handle results on a per-hunk basis.
The iterator yields a HunkApplyStatus for each hunk in the patch.
§Example
use mpatch::{parse_single_patch, HunkApplier, HunkApplyStatus, ApplyOptions};
// 1. Define original content and a patch.
let original_lines = vec!["line 1", "line 2", "line 3"];
let diff_content = r#"
```diff
--- a/file.txt
+++ b/file.txt
@@ -2,1 +2,1 @@
-line 2
+line two
```
"#;
let patch = parse_single_patch(diff_content)?;
let options = ApplyOptions::new();
// 2. Create the applier.
let mut applier = HunkApplier::new(&patch, Some(&original_lines), &options);
// 3. Apply the first (and only) hunk.
let status = applier.next().unwrap();
assert!(matches!(status, HunkApplyStatus::Applied { .. }));
// 4. Check that there are no more hunks.
assert!(applier.next().is_none());
// 5. Finalize the content.
let new_content = applier.into_content();
assert_eq!(new_content, "line 1\nline two\nline 3\n");Implementations§
Source§impl<'a> HunkApplier<'a>
impl<'a> HunkApplier<'a>
Sourcepub fn new<T: AsRef<str>>(
patch: &'a Patch,
original_lines: Option<&'a [T]>,
options: &'a ApplyOptions,
) -> Self
pub fn new<T: AsRef<str>>( patch: &'a Patch, original_lines: Option<&'a [T]>, options: &'a ApplyOptions, ) -> Self
Creates a new HunkApplier to begin a step-by-step patch operation.
This constructor initializes the applier with the patch to be applied and the
original content. The content is provided as an optional slice of lines,
allowing for both file modifications (Some(lines)) and file creations (None).
The applier can then be used as an iterator to apply hunks one by one.
§Example
let original_lines = vec!["line 1", "line 2"];
let diff = "```diff\n--- a/f\n+++ b/f\n@@ -2,1 +2,1\n-line 2\n+line two\n```";
let patch = parse_single_patch(diff)?;
let options = ApplyOptions::new();
// Create the applier for a step-by-step operation.
let mut applier = HunkApplier::new(&patch, Some(&original_lines), &options);
// Now `applier` is ready to be used as an iterator.
let status = applier.next().unwrap();Sourcepub fn current_lines(&self) -> &[String]
pub fn current_lines(&self) -> &[String]
Returns a slice of the current lines, reflecting all hunks applied so far.
This method provides read-only access to the intermediate state of the
content being patched. It is useful for inspecting the content between
applying hunks with the HunkApplier iterator.
§Example
let original_lines = vec!["line 1", "line 2"];
let diff = "```diff\n--- a/f\n+++ b/f\n@@ -2,1 +2,1\n-line 2\n+line two\n```";
let patch = parse_single_patch(diff)?;
let options = ApplyOptions::new();
let mut applier = HunkApplier::new(&patch, Some(&original_lines), &options);
// Before applying, it's the original content.
assert_eq!(applier.current_lines(), &["line 1", "line 2"]);
// Apply the hunk.
applier.next();
// After applying, the lines are updated.
assert_eq!(applier.current_lines(), &["line 1", "line two"]);Sourcepub fn set_original_newline_status(&mut self, ends_with_newline: bool)
pub fn set_original_newline_status(&mut self, ends_with_newline: bool)
Sets whether the original content ended with a newline.
When working with a slice of lines (e.g., Vec<String>), the information about
whether the original file ended with a newline character is typically lost.
This method allows you to restore that context.
mpatch uses this information to determine the newline status of the final output:
- If a patch modifies the end of the file (i.e., the last hunk applies to the
very end), the patch’s
ends_with_newlinesetting takes precedence. - If the patch only modifies the middle of the file, the original newline status is preserved.
By default, HunkApplier assumes the original content ended with a newline (true).
§Arguments
ends_with_newline-trueif the original content had a trailing newline,falseotherwise.
§Example
// Original content: "line 1\nline 2" (No trailing newline)
let original_lines = vec!["line 1", "line 2"];
let diff = "```diff\n--- a/f\n+++ b/f\n@@ -1,1 +1,1\n-line 1\n+line one\n```";
let patch = parse_single_patch(diff)?;
let options = ApplyOptions::new();
let mut applier = HunkApplier::new(&patch, Some(&original_lines), &options);
// Crucial step: Tell the applier the original file didn't have a newline.
applier.set_original_newline_status(false);
applier.next(); // Apply the hunk (modifies line 1)
// The result should preserve the "no newline" status because the patch didn't touch EOF.
let result = applier.into_content();
assert_eq!(result, "line one\nline 2");Sourcepub fn into_lines(self) -> Vec<String>
pub fn into_lines(self) -> Vec<String>
Consumes the applier and returns the final vector of lines.
After iterating through the HunkApplier and applying all desired hunks,
this method can be called to take ownership of the final, modified vector
of strings.
§Example
let original_lines = vec!["line 1", "line 2"];
let diff = "```diff\n--- a/f\n+++ b/f\n@@ -2,1 +2,1\n-line 2\n+line two\n```";
let patch = parse_single_patch(diff)?;
let options = ApplyOptions::new();
let mut applier = HunkApplier::new(&patch, Some(&original_lines), &options);
applier.next(); // Apply all hunks
let final_lines = applier.into_lines();
assert_eq!(final_lines, vec!["line 1".to_string(), "line two".to_string()]);Sourcepub fn into_content(self) -> String
pub fn into_content(self) -> String
Consumes the applier and returns the final content as a single string.
This method joins the final lines with newlines and ensures the content
has a trailing newline if required by the patch’s ends_with_newline
property. It is the most common way to get the final result from a
HunkApplier.
§Example
let original_lines = vec!["line 1"];
let diff = "```diff\n--- a/f\n+++ b/f\n@@ -1,1 +1,1\n-line 1\n+line one\n```";
let patch = parse_single_patch(diff)?;
let options = ApplyOptions::new();
let mut applier = HunkApplier::new(&patch, Some(&original_lines), &options);
applier.next(); // Apply all hunks
let final_content = applier.into_content();
assert_eq!(final_content, "line one\n");Trait Implementations§
Source§impl<'a> Debug for HunkApplier<'a>
impl<'a> Debug for HunkApplier<'a>
Source§impl<'a> Iterator for HunkApplier<'a>
impl<'a> Iterator for HunkApplier<'a>
Source§fn next(&mut self) -> Option<Self::Item>
fn next(&mut self) -> Option<Self::Item>
Applies the next hunk in the patch and returns its status.
This method advances the iterator, applying one hunk to the internal state
of the HunkApplier. It returns Some(HunkApplyStatus) for each hunk in
the patch, and None when all hunks have been processed.
§Example
let original_lines = vec!["line 1", "line 2"];
let diff = "```diff\n--- a/f\n+++ b/f\n@@ -2,1 +2,1\n-line 2\n+line two\n```";
let patch = parse_single_patch(diff)?;
let options = ApplyOptions::new();
let mut applier = HunkApplier::new(&patch, Some(&original_lines), &options);
// Call next() to apply the first hunk.
let status = applier.next();
assert!(matches!(status, Some(HunkApplyStatus::Applied { .. })));
// Call next() again; there are no more hunks.
assert!(applier.next().is_none());Source§type Item = HunkApplyStatus
type Item = HunkApplyStatus
Source§fn next_chunk<const N: usize>(
&mut self,
) -> Result<[Self::Item; N], IntoIter<Self::Item, N>>where
Self: Sized,
fn next_chunk<const N: usize>(
&mut self,
) -> Result<[Self::Item; N], IntoIter<Self::Item, N>>where
Self: Sized,
iter_next_chunk)N values. Read more1.0.0 · Source§fn size_hint(&self) -> (usize, Option<usize>)
fn size_hint(&self) -> (usize, Option<usize>)
1.0.0 · Source§fn count(self) -> usizewhere
Self: Sized,
fn count(self) -> usizewhere
Self: Sized,
1.0.0 · Source§fn last(self) -> Option<Self::Item>where
Self: Sized,
fn last(self) -> Option<Self::Item>where
Self: Sized,
Source§fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>>
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>>
iter_advance_by)n elements. Read more1.0.0 · Source§fn nth(&mut self, n: usize) -> Option<Self::Item>
fn nth(&mut self, n: usize) -> Option<Self::Item>
nth element of the iterator. Read more1.28.0 · Source§fn step_by(self, step: usize) -> StepBy<Self>where
Self: Sized,
fn step_by(self, step: usize) -> StepBy<Self>where
Self: Sized,
1.0.0 · Source§fn chain<U>(self, other: U) -> Chain<Self, <U as IntoIterator>::IntoIter>
fn chain<U>(self, other: U) -> Chain<Self, <U as IntoIterator>::IntoIter>
1.0.0 · Source§fn zip<U>(self, other: U) -> Zip<Self, <U as IntoIterator>::IntoIter>where
Self: Sized,
U: IntoIterator,
fn zip<U>(self, other: U) -> Zip<Self, <U as IntoIterator>::IntoIter>where
Self: Sized,
U: IntoIterator,
Source§fn intersperse(self, separator: Self::Item) -> Intersperse<Self>
fn intersperse(self, separator: Self::Item) -> Intersperse<Self>
iter_intersperse)separator between items
of the original iterator. Read moreSource§fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G>
fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G>
iter_intersperse)separator
between items of the original iterator. Read more1.0.0 · Source§fn map<B, F>(self, f: F) -> Map<Self, F>
fn map<B, F>(self, f: F) -> Map<Self, F>
1.0.0 · Source§fn filter<P>(self, predicate: P) -> Filter<Self, P>
fn filter<P>(self, predicate: P) -> Filter<Self, P>
1.0.0 · Source§fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F>
fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F>
1.0.0 · Source§fn enumerate(self) -> Enumerate<Self>where
Self: Sized,
fn enumerate(self) -> Enumerate<Self>where
Self: Sized,
1.0.0 · Source§fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P>
fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P>
1.0.0 · Source§fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P>
fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P>
1.57.0 · Source§fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P>
fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P>
1.0.0 · Source§fn skip(self, n: usize) -> Skip<Self>where
Self: Sized,
fn skip(self, n: usize) -> Skip<Self>where
Self: Sized,
n elements. Read more1.0.0 · Source§fn take(self, n: usize) -> Take<Self>where
Self: Sized,
fn take(self, n: usize) -> Take<Self>where
Self: Sized,
n elements, or fewer
if the underlying iterator ends sooner. Read more1.0.0 · Source§fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F>
fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F>
Source§fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N>
fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N>
iter_map_windows)f for each contiguous window of size N over
self and returns an iterator over the outputs of f. Like slice::windows(),
the windows during mapping overlap as well. Read more1.0.0 · Source§fn inspect<F>(self, f: F) -> Inspect<Self, F>
fn inspect<F>(self, f: F) -> Inspect<Self, F>
1.0.0 · Source§fn by_ref(&mut self) -> &mut Selfwhere
Self: Sized,
fn by_ref(&mut self) -> &mut Selfwhere
Self: Sized,
Iterator. Read moreSource§fn collect_into<E>(self, collection: &mut E) -> &mut E
fn collect_into<E>(self, collection: &mut E) -> &mut E
iter_collect_into)1.0.0 · Source§fn partition<B, F>(self, f: F) -> (B, B)
fn partition<B, F>(self, f: F) -> (B, B)
Source§fn is_partitioned<P>(self, predicate: P) -> bool
fn is_partitioned<P>(self, predicate: P) -> bool
iter_is_partitioned)true precede all those that return false. Read more1.27.0 · Source§fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
1.27.0 · Source§fn try_for_each<F, R>(&mut self, f: F) -> R
fn try_for_each<F, R>(&mut self, f: F) -> R
1.0.0 · Source§fn fold<B, F>(self, init: B, f: F) -> B
fn fold<B, F>(self, init: B, f: F) -> B
1.51.0 · Source§fn reduce<F>(self, f: F) -> Option<Self::Item>
fn reduce<F>(self, f: F) -> Option<Self::Item>
Source§fn try_reduce<R>(
&mut self,
f: impl FnMut(Self::Item, Self::Item) -> R,
) -> <<R as Try>::Residual as Residual<Option<<R as Try>::Output>>>::TryType
fn try_reduce<R>( &mut self, f: impl FnMut(Self::Item, Self::Item) -> R, ) -> <<R as Try>::Residual as Residual<Option<<R as Try>::Output>>>::TryType
iterator_try_reduce)1.0.0 · Source§fn all<F>(&mut self, f: F) -> bool
fn all<F>(&mut self, f: F) -> bool
1.0.0 · Source§fn any<F>(&mut self, f: F) -> bool
fn any<F>(&mut self, f: F) -> bool
1.0.0 · Source§fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
1.30.0 · Source§fn find_map<B, F>(&mut self, f: F) -> Option<B>
fn find_map<B, F>(&mut self, f: F) -> Option<B>
Source§fn try_find<R>(
&mut self,
f: impl FnMut(&Self::Item) -> R,
) -> <<R as Try>::Residual as Residual<Option<Self::Item>>>::TryType
fn try_find<R>( &mut self, f: impl FnMut(&Self::Item) -> R, ) -> <<R as Try>::Residual as Residual<Option<Self::Item>>>::TryType
try_find)1.0.0 · Source§fn position<P>(&mut self, predicate: P) -> Option<usize>
fn position<P>(&mut self, predicate: P) -> Option<usize>
1.6.0 · Source§fn max_by_key<B, F>(self, f: F) -> Option<Self::Item>
fn max_by_key<B, F>(self, f: F) -> Option<Self::Item>
1.15.0 · Source§fn max_by<F>(self, compare: F) -> Option<Self::Item>
fn max_by<F>(self, compare: F) -> Option<Self::Item>
1.6.0 · Source§fn min_by_key<B, F>(self, f: F) -> Option<Self::Item>
fn min_by_key<B, F>(self, f: F) -> Option<Self::Item>
1.15.0 · Source§fn min_by<F>(self, compare: F) -> Option<Self::Item>
fn min_by<F>(self, compare: F) -> Option<Self::Item>
1.0.0 · Source§fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB)
fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB)
1.36.0 · Source§fn copied<'a, T>(self) -> Copied<Self>
fn copied<'a, T>(self) -> Copied<Self>
Source§fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N>where
Self: Sized,
fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N>where
Self: Sized,
iter_array_chunks)N elements of the iterator at a time. Read more1.11.0 · Source§fn product<P>(self) -> P
fn product<P>(self) -> P
Source§fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering
fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering
iter_order_by)Iterator with those
of another with respect to the specified comparison function. Read more1.5.0 · Source§fn partial_cmp<I>(self, other: I) -> Option<Ordering>
fn partial_cmp<I>(self, other: I) -> Option<Ordering>
PartialOrd elements of
this Iterator with those of another. The comparison works like short-circuit
evaluation, returning a result without comparing the remaining elements.
As soon as an order can be determined, the evaluation stops and a result is returned. Read moreSource§fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering>where
Self: Sized,
I: IntoIterator,
F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Option<Ordering>,
fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering>where
Self: Sized,
I: IntoIterator,
F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Option<Ordering>,
iter_order_by)Iterator with those
of another with respect to the specified comparison function. Read moreSource§fn eq_by<I, F>(self, other: I, eq: F) -> bool
fn eq_by<I, F>(self, other: I, eq: F) -> bool
iter_order_by)1.5.0 · Source§fn lt<I>(self, other: I) -> bool
fn lt<I>(self, other: I) -> bool
Iterator are lexicographically
less than those of another. Read more1.5.0 · Source§fn le<I>(self, other: I) -> bool
fn le<I>(self, other: I) -> bool
Iterator are lexicographically
less or equal to those of another. Read more1.5.0 · Source§fn gt<I>(self, other: I) -> bool
fn gt<I>(self, other: I) -> bool
Iterator are lexicographically
greater than those of another. Read more1.5.0 · Source§fn ge<I>(self, other: I) -> bool
fn ge<I>(self, other: I) -> bool
Iterator are lexicographically
greater than or equal to those of another. Read more1.82.0 · Source§fn is_sorted_by<F>(self, compare: F) -> bool
fn is_sorted_by<F>(self, compare: F) -> bool
1.82.0 · Source§fn is_sorted_by_key<F, K>(self, f: F) -> bool
fn is_sorted_by_key<F, K>(self, f: F) -> bool
Auto Trait Implementations§
impl<'a> Freeze for HunkApplier<'a>
impl<'a> RefUnwindSafe for HunkApplier<'a>
impl<'a> Send for HunkApplier<'a>
impl<'a> Sync for HunkApplier<'a>
impl<'a> Unpin for HunkApplier<'a>
impl<'a> UnsafeUnpin for HunkApplier<'a>
impl<'a> UnwindSafe for HunkApplier<'a>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more