Skip to main content

java_diff_utils_rs/patch/
insert_delta.rs

1use std::fmt;
2
3use super::chunk::Chunk;
4use super::delta::Delta;
5use super::delta_type::DeltaType;
6use super::error::PatchError;
7
8/// Describes an insert-delta representing new content added to a target sequence.
9#[derive(Debug, Clone, PartialEq, Eq, Hash)]
10pub struct InsertDelta<T> {
11    inner: Delta<T>,
12}
13
14impl<T> InsertDelta<T> {
15    /// Creates a new `InsertDelta` with the given original (source) and revised (target) chunks.
16    pub fn new(original: Chunk<T>, revised: Chunk<T>) -> Self {
17        Self {
18            inner: Delta::new(DeltaType::Insert, original, revised),
19        }
20    }
21
22    /// Returns a reference to the underlying inner [`Delta`].
23    #[inline]
24    pub fn delta(&self) -> &Delta<T> {
25        &self.inner
26    }
27
28    /// Consumes `self` and returns the inner [`Delta`].
29    #[inline]
30    pub fn into_delta(self) -> Delta<T> {
31        self.inner
32    }
33
34    /// Returns a reference to the source (original) chunk.
35    #[inline]
36    pub fn source(&self) -> &Chunk<T> {
37        self.inner.source()
38    }
39
40    /// Returns a reference to the target (revised) chunk.
41    #[inline]
42    pub fn target(&self) -> &Chunk<T> {
43        self.inner.target()
44    }
45
46    /// Applies this insert delta to the target vector.
47    ///
48    /// Inserts the revised chunk lines at the source chunk's target position.
49    pub fn apply_to(&self, target: &mut Vec<T>) -> Result<(), PatchError>
50    where
51        T: Clone,
52    {
53        let position = self.source().position();
54
55        if position > target.len() {
56            return Err(PatchError::PatchFailed(format!(
57                "InsertDelta position {} out of bounds for target length {}",
58                position,
59                target.len()
60            )));
61        }
62
63        target.splice(position..position, self.target().lines().iter().cloned());
64
65        Ok(())
66    }
67
68    /// Restores (un-applies) this insert delta on the target vector.
69    ///
70    /// Removes/drains the inserted target lines from the target vector.
71    pub fn restore(&self, target: &mut Vec<T>) -> Result<(), PatchError> {
72        let position = self.target().position();
73        let size = self.target().len();
74
75        if position > target.len() || position + size > target.len() {
76            return Err(PatchError::PatchFailed(format!(
77                "InsertDelta restore range [{}..{}] out of bounds for target length {}",
78                position,
79                position + size,
80                target.len()
81            )));
82        }
83
84        target.drain(position..position + size);
85        Ok(())
86    }
87
88    /// Creates a new `InsertDelta` with custom source and target chunks.
89    #[must_use]
90    pub fn with_chunks(&self, original: Chunk<T>, revised: Chunk<T>) -> Self {
91        Self::new(original, revised)
92    }
93}
94
95impl<T: fmt::Debug> fmt::Display for InsertDelta<T> {
96    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97        write!(
98            f,
99            "[InsertDelta, position: {}, lines: {:?}]",
100            self.source().position(),
101            self.target().lines()
102        )
103    }
104}
105
106impl<T> From<InsertDelta<T>> for Delta<T> {
107    fn from(insert: InsertDelta<T>) -> Self {
108        insert.inner
109    }
110}