Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/rust/similar/src/algorithms/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 5 kB image not shown  

Quelle  replace.rs

  Sprache: Rust
 

use crate::algorithms::DiffHook;

/// A [`DiffHook`] that combines deletions and insertions to give blocks
/// of maximal length, and replacements when appropriate.
///
/// It will replace [`DiffHook::insert`] and [`DiffHook::delete`] events when
/// possible with [`DiffHook::replace`] events.  Note that even though the
/// text processing in the crate does not use replace events and always resolves
/// then back to delete and insert, it's useful to always use the replacer to
/// ensure a consistent order of inserts and deletes.  This is why for instance
/// the text diffing automatically uses this hook internally.
pub struct Replace<D: DiffHook> {
    d: D,
    del: Option<(usize, usize, usize)>,
    ins: Option<(usize, usize, usize)>,
    eq: Option<(usize, usize, usize)>,
}

impl<D: DiffHook> Replace<D> {
    /// Creates a new replace hook wrapping another hook.
    pub fn new(d: D) -> Self {
        Replace {
            d,
            del: None,
            ins: None,
            eq: None,
        }
    }

    /// Extracts the inner hook.
    pub fn into_inner(self) -> D {
        self.d
    }

    fn flush_eq(&mut self) -> Result<(), D::Error> {
        if let Some((eq_old_index, eq_new_index, eq_len)) = self.eq.take() {
            self.d.equal(eq_old_index, eq_new_index, eq_len)?
        }
        Ok(())
    }

    fn flush_del_ins(&mut self) -> Result<(), D::Error> {
        if let Some((del_old_index, del_old_len, del_new_index)) = self.del.take() {
            if let Some((_, ins_new_index, ins_new_len)) = self.ins.take() {
                self.d
                    .replace(del_old_index, del_old_len, ins_new_index, ins_new_len)?;
            } else {
                self.d.delete(del_old_index, del_old_len, del_new_index)?;
            }
        } else if let Some((ins_old_index, ins_new_index, ins_new_len)) = self.ins.take() {
            self.d.insert(ins_old_index, ins_new_index, ins_new_len)?;
        }
        Ok(())
    }
}

impl<D: DiffHook> AsRef<D> for Replace<D> {
    fn as_ref(&self) -> &D {
        &self.d
    }
}

impl<D: DiffHook> AsMut<D> for Replace<D> {
    fn as_mut(&mut self) -> &mut D {
        &mut self.d
    }
}

impl<D: DiffHook> DiffHook for Replace<D> {
    type Error = D::Error;

    fn equal(&mut self, old_index: usize, new_index: usize, len: usize) -> Result<(), D::Error> {
        self.flush_del_ins()?;

        self.eq = if let Some((eq_old_index, eq_new_index, eq_len)) = self.eq.take() {
            Some((eq_old_index, eq_new_index, eq_len + len))
        } else {
            Some((old_index, new_index, len))
        };

        Ok(())
    }

    fn delete(
        &mut self,
        old_index: usize,
        old_len: usize,
        new_index: usize,
    ) -> Result<(), D::Error> {
        self.flush_eq()?;
        if let Some((del_old_index, del_old_len, del_new_index)) = self.del.take() {
            debug_assert_eq!(old_index, del_old_index + del_old_len);
            self.del = Some((del_old_index, del_old_len + old_len, del_new_index));
        } else {
            self.del = Some((old_index, old_len, new_index));
        }
        Ok(())
    }

    fn insert(
        &mut self,
        old_index: usize,
        new_index: usize,
        new_len: usize,
    ) -> Result<(), D::Error> {
        self.flush_eq()?;
        self.ins = if let Some((ins_old_index, ins_new_index, ins_new_len)) = self.ins.take() {
            debug_assert_eq!(ins_new_index + ins_new_len, new_index);
            Some((ins_old_index, ins_new_index, new_len + ins_new_len))
        } else {
            Some((old_index, new_index, new_len))
        };

        Ok(())
    }

    fn replace(
        &mut self,
        old_index: usize,
        old_len: usize,
        new_index: usize,
        new_len: usize,
    ) -> Result<(), D::Error> {
        self.flush_eq()?;
        self.d.replace(old_index, old_len, new_index, new_len)
    }

    fn finish(&mut self) -> Result<(), D::Error> {
        self.flush_eq()?;
        self.flush_del_ins()?;
        self.d.finish()
    }
}

#[test]
fn test_mayers_replace() {
    use crate::algorithms::{diff_slices, Algorithm};
    let a: &[&str] = &[
        ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n",
        "a\n",
        "b\n",
        "c\n",
        "================================\n",
        "d\n",
        "e\n",
        "f\n",
        "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n",
    ];
    let b: &[&str] = &[
        ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n",
        "x\n",
        "b\n",
        "c\n",
        "================================\n",
        "y\n",
        "e\n",
        "f\n",
        "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n",
    ];

    let mut d = Replace::new(crate::algorithms::Capture::new());
    diff_slices(Algorithm::Myers, &mut d, a, b).unwrap();

    insta::assert_debug_snapshot!(&d.into_inner().ops(), @r###"
    [
        Equal {
            old_index: 0,
            new_index: 0,
            len: 1,
        },
        Replace {
            old_index: 1,
            old_len: 1,
            new_index: 1,
            new_len: 1,
        },
        Equal {
            old_index: 2,
            new_index: 2,
            len: 3,
        },
        Replace {
            old_index: 5,
            old_len: 1,
            new_index: 5,
            new_len: 1,
        },
        Equal {
            old_index: 6,
            new_index: 6,
            len: 3,
        },
    ]
    "###);
}

#[test]
fn test_replace() {
    use crate::algorithms::{diff_slices, Algorithm};

    let a: &[usize] = &[01234];
    let b: &[usize] = &[012789];

    let mut d = Replace::new(crate::algorithms::Capture::new());
    diff_slices(Algorithm::Myers, &mut d, a, b).unwrap();
    insta::assert_debug_snapshot!(d.into_inner().ops(), @r###"
    [
        Equal {
            old_index: 0,
            new_index: 0,
            len: 3,
        },
        Replace {
            old_index: 3,
            old_len: 2,
            new_index: 3,
            new_len: 3,
        },
    ]
    "###);
}

Messung V0.5 in Prozent
C=86 H=97 G=91

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet am  2026-08-25) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.