lsdiff_rs/
lib.rs

1//!
2//! The Lsdiff library.
3//!
4
5use failure::Fail;
6
7#[derive(Default)]
8pub struct Entry {
9    /// Starting from 0
10    pub start_line: usize,
11    /// Starting from 0
12    pub hunk_start_line: usize,
13    /// The file being patched path
14    pub input_path: String,
15    /// The patched file path
16    pub output_path: String,
17    /// Between consequent `start_line`s
18    pub lines_count: usize,
19}
20
21#[derive(Debug, Fail)]
22pub enum Error {
23    #[fail(display = "The patch is malformed at line {}", _0)]
24    MalformedPatch(usize),
25}
26
27pub type LsdiffResult<T> = Result<T, Error>;
28
29pub fn process(patch: &str) -> LsdiffResult<Vec<Entry>> {
30    let lines: Vec<&str> = patch.split('\n').map(|line| line.trim()).collect();
31
32    let mut entries: Vec<Entry> = Vec::new();
33
34    for index in 0..lines.len() - 1 {
35        if !(lines[index].starts_with("---") && lines[index + 1].starts_with("+++")) {
36            continue;
37        }
38
39        let mut entry = Entry::default();
40        entry.start_line = index;
41        entry.hunk_start_line = index + 2;
42
43        if let Some(last) = entries.last_mut() {
44            last.lines_count = entry.start_line - last.start_line;
45        }
46
47        let elements: Vec<&str> = lines[index].split(' ').collect();
48        if elements.len() < 2 {
49            return Err(Error::MalformedPatch(index + 1));
50        }
51        entry.input_path = elements[1].to_owned();
52
53        let elements: Vec<&str> = lines[index + 1].split(' ').collect();
54        if elements.len() < 2 {
55            return Err(Error::MalformedPatch(index + 2));
56        }
57        entry.output_path = elements[1].to_owned();
58
59        entries.push(entry)
60    }
61
62    if let Some(last) = entries.last_mut() {
63        last.lines_count = lines.len() - 1 - last.start_line;
64    }
65
66    Ok(entries)
67}