rust/hg-core/src/bdiff.rs
author Pierre-Yves David <pierre-yves.david@octobus.net>
Tue, 11 Mar 2025 02:29:42 +0100
branchstable
changeset 53042 cdd7bf612c7b
parent 53016 3ac28aa1430e
permissions -rw-r--r--
bundle-spec: properly format boolean parameter (issue6960) This was breaking automatic clone bundle generation. This changeset fixes it and add a test to catch it in the future.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
52755
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
     1
//! Safe bindings to bdiff.c.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
     2
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
     3
use crate::errors::HgError;
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
     4
use std::marker::PhantomData;
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
     5
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
     6
/// A file split into lines, ready for diffing.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
     7
pub struct Lines<'a> {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
     8
    /// The array of lines, allocated by bdiff.c.
53016
3ac28aa1430e rust-annotate: do not impl Sync for Lines
Mitchell Kember <mkember@janestreet.com>
parents: 52767
diff changeset
     9
    /// Must never be mutated by Rust code apart from freeing it in `Drop`.
52755
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    10
    array: *mut ffi::bdiff_line,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    11
    /// Length of the array.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    12
    len: u32,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    13
    /// Lifetime of the source buffer, since array items store pointers.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    14
    _lifetime: PhantomData<&'a [u8]>,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    15
}
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    16
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    17
/// Splits `source` into lines that can be diffed.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    18
pub fn split_lines(source: &[u8]) -> Result<Lines, HgError> {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    19
    let mut array = std::ptr::null_mut();
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    20
    // Safety: The pointer and length are valid since they both come from
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    21
    // `source`, and the out pointer is non-null.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    22
    let result = unsafe {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    23
        ffi::bdiff_splitlines(
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    24
            source.as_ptr() as *const std::ffi::c_char,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    25
            source.len() as isize,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    26
            &mut array,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    27
        )
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    28
    };
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    29
    match u32::try_from(result) {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    30
        Ok(len) => {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    31
            assert!(!array.is_null());
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    32
            Ok(Lines {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    33
                array,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    34
                len,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    35
                _lifetime: PhantomData,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    36
            })
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    37
        }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    38
        Err(_) => {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    39
            Err(HgError::abort_simple("bdiff_splitlines failed to allocate"))
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    40
        }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    41
    }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    42
}
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    43
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    44
impl<'a> Lines<'a> {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    45
    /// Returns the number of lines.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    46
    pub fn len(&self) -> usize {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    47
        self.len as usize
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    48
    }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    49
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    50
    /// Returns an iterator over the lines.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    51
    pub fn iter(&self) -> LinesIter<'_, 'a> {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    52
        LinesIter {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    53
            lines: self,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    54
            index: 0,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    55
        }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    56
    }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    57
}
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    58
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    59
impl Drop for Lines<'_> {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    60
    fn drop(&mut self) {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    61
        // Safety: This is the only place that frees the array (no
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    62
        // double-free), and it's in a `Drop` impl (no use-after-free).
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    63
        unsafe {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    64
            libc::free(self.array as *mut std::ffi::c_void);
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    65
        }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    66
    }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    67
}
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    68
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    69
// Safety: It is safe to send `Lines` to a different thread because
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    70
// `self.array` is never copied so only one thread will free it.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    71
unsafe impl Send for Lines<'_> {}
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    72
53016
3ac28aa1430e rust-annotate: do not impl Sync for Lines
Mitchell Kember <mkember@janestreet.com>
parents: 52767
diff changeset
    73
// It is *not* safe to share `&Lines` between threads because `ffi::bdiff_diff`
3ac28aa1430e rust-annotate: do not impl Sync for Lines
Mitchell Kember <mkember@janestreet.com>
parents: 52767
diff changeset
    74
// mutates lines by storing bookkeeping information in `n` and `e`.
3ac28aa1430e rust-annotate: do not impl Sync for Lines
Mitchell Kember <mkember@janestreet.com>
parents: 52767
diff changeset
    75
static_assertions_next::assert_impl!(Lines<'_>: !Sync);
3ac28aa1430e rust-annotate: do not impl Sync for Lines
Mitchell Kember <mkember@janestreet.com>
parents: 52767
diff changeset
    76
52755
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    77
#[derive(Clone)]
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    78
pub struct LinesIter<'a, 'b> {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    79
    lines: &'a Lines<'b>,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    80
    index: usize,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    81
}
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    82
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    83
impl<'b> Iterator for LinesIter<'_, 'b> {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    84
    type Item = &'b [u8];
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    85
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    86
    fn next(&mut self) -> Option<Self::Item> {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    87
        if self.index == self.lines.len() {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    88
            return None;
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    89
        }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    90
        // Safety: We just checked that the index has not reached the length.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    91
        let line = unsafe { *self.lines.array.add(self.index) };
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    92
        self.index += 1;
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    93
        // Safety: We assume bdiff.c sets `l` and `len` correctly.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    94
        Some(unsafe {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    95
            std::slice::from_raw_parts(line.l as *const u8, line.len as usize)
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    96
        })
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    97
    }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    98
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
    99
    fn size_hint(&self) -> (usize, Option<usize>) {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   100
        let len = self.lines.len() - self.index;
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   101
        (len, Some(len))
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   102
    }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   103
}
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   104
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   105
impl ExactSizeIterator for LinesIter<'_, '_> {}
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   106
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   107
/// A diff hunk comparing lines [a1,a2) in file A with lines [b1,b2) in file B.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   108
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   109
pub struct Hunk {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   110
    /// Start line index in file A (inclusive).
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   111
    pub a1: u32,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   112
    /// End line index in file A (exclusive).
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   113
    pub a2: u32,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   114
    /// Start line index in file B (inclusive).
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   115
    pub b1: u32,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   116
    /// End line index in file B (exclusive).
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   117
    pub b2: u32,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   118
}
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   119
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   120
/// A list of matching hunks.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   121
pub struct HunkList {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   122
    /// The head of the linked list, allocated by bdiff.c.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   123
    head: *mut ffi::bdiff_hunk,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   124
    /// Length of the list.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   125
    len: u32,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   126
}
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   127
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   128
/// Returns a list of hunks that match in `a` and `b`.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   129
pub fn diff(a: &Lines, b: &Lines) -> Result<HunkList, HgError> {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   130
    let mut out = ffi::bdiff_hunk {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   131
        a1: 0,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   132
        a2: 0,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   133
        b1: 0,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   134
        b2: 0,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   135
        next: std::ptr::null_mut(),
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   136
    };
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   137
    // Safety: We assume bdiff.c sets `array` and `len` correctly; and the
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   138
    // out pointer is non-null.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   139
    let result = unsafe {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   140
        ffi::bdiff_diff(a.array, a.len as i32, b.array, b.len as i32, &mut out)
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   141
    };
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   142
    match u32::try_from(result) {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   143
        Ok(len) => Ok(HunkList {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   144
            // Start with out.next because the first hunk is not meaningful and
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   145
            // is not included in len. This matches mercurial/cffi/bdiff.py.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   146
            head: out.next,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   147
            len,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   148
        }),
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   149
        Err(_) => Err(HgError::abort_simple("bdiff_diff failed to allocate")),
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   150
    }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   151
}
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   152
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   153
impl HunkList {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   154
    /// Returns the number of hunks.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   155
    pub fn len(&self) -> usize {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   156
        self.len as usize
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   157
    }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   158
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   159
    /// Returns an iterator over the hunks.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   160
    pub fn iter(&self) -> HunkListIter {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   161
        HunkListIter {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   162
            // Safety: If `self.head` is null, this is safe. If non-null, then:
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   163
            // - We assume bdiff.c made it properly aligned.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   164
            // - It's dereferenceable (any bit pattern is ok for `bdiff_hunk`).
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   165
            // - It won't be mutated because `HunkListIter` is tied to `&self`.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   166
            next: unsafe { self.head.as_ref() },
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   167
            remaining: self.len(),
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   168
        }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   169
    }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   170
}
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   171
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   172
impl Drop for HunkList {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   173
    fn drop(&mut self) {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   174
        // Safety: This is the only place that frees `self.head` (no
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   175
        // double-free), and it's in a `Drop` impl (no use-after-free).
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   176
        unsafe {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   177
            ffi::bdiff_freehunks(self.head);
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   178
        }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   179
    }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   180
}
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   181
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   182
pub struct HunkListIter<'a> {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   183
    next: Option<&'a ffi::bdiff_hunk>,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   184
    remaining: usize,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   185
}
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   186
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   187
impl Iterator for HunkListIter<'_> {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   188
    type Item = Hunk;
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   189
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   190
    fn next(&mut self) -> Option<Self::Item> {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   191
        match self.next {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   192
            Some(hunk) => {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   193
                // Safety: Same reasoning as in `HunkList::iter`.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   194
                self.next = unsafe { hunk.next.as_ref() };
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   195
                self.remaining -= 1;
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   196
                debug_assert_eq!(hunk.a2 - hunk.a1, hunk.b2 - hunk.b1);
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   197
                Some(Hunk {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   198
                    a1: hunk.a1 as u32,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   199
                    a2: hunk.a2 as u32,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   200
                    b1: hunk.b1 as u32,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   201
                    b2: hunk.b2 as u32,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   202
                })
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   203
            }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   204
            None => {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   205
                assert_eq!(self.remaining, 0);
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   206
                None
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   207
            }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   208
        }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   209
    }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   210
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   211
    fn size_hint(&self) -> (usize, Option<usize>) {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   212
        (self.remaining, Some(self.remaining))
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   213
    }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   214
}
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   215
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   216
impl ExactSizeIterator for HunkListIter<'_> {}
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   217
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   218
mod ffi {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   219
    #![allow(non_camel_case_types)]
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   220
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   221
    use std::ffi::{c_char, c_int};
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   222
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   223
    #[repr(C)]
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   224
    #[derive(Debug, Copy, Clone)]
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   225
    pub struct bdiff_line {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   226
        pub hash: c_int,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   227
        pub n: c_int,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   228
        pub e: c_int,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   229
        pub len: isize,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   230
        pub l: *const c_char,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   231
    }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   232
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   233
    #[repr(C)]
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   234
    #[derive(Debug, Copy, Clone)]
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   235
    pub struct bdiff_hunk {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   236
        pub a1: c_int,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   237
        pub a2: c_int,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   238
        pub b1: c_int,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   239
        pub b2: c_int,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   240
        pub next: *mut bdiff_hunk,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   241
    }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   242
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   243
    #[link(name = "bdiff", kind = "static")]
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   244
    extern "C" {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   245
        /// Splits `a` into lines. On success, stores a pointer to an array of
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   246
        /// lines in `*lr` and returns its length. On failure, returns
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   247
        /// -1. The caller is responsible for freeing the array.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   248
        ///
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   249
        /// # Safety
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   250
        ///
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   251
        /// - `a` must point to an array of `len` chars.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   252
        /// - `lr` must be non-null (but `*lr` can be null).
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   253
        pub fn bdiff_splitlines(
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   254
            a: *const c_char,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   255
            len: isize,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   256
            lr: *mut *mut bdiff_line,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   257
        ) -> c_int;
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   258
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   259
        /// Diffs `a` and `b`. On success, stores the head of a linked list of
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   260
        /// hunks in `base->next` and returns its length. On failure, returns
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   261
        /// -1. The caller is responsible for `bdiff_freehunks(base->next)`.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   262
        ///
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   263
        /// # Safety
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   264
        ///
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   265
        /// - `a` must point to an array of `an` lines.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   266
        /// - `b` must point to an array of `bn` lines.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   267
        /// - `base` must be non-null.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   268
        pub fn bdiff_diff(
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   269
            a: *mut bdiff_line,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   270
            an: c_int,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   271
            b: *mut bdiff_line,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   272
            bn: c_int,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   273
            base: *mut bdiff_hunk,
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   274
        ) -> c_int;
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   275
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   276
        /// Frees the linked list of hunks `l`.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   277
        ///
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   278
        /// # Safety
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   279
        ///
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   280
        /// - `l` must be non-null, not already freed, and not used after this.
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   281
        pub fn bdiff_freehunks(l: *mut bdiff_hunk);
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   282
    }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   283
}
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   284
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   285
#[cfg(test)]
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   286
mod tests {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   287
    fn split(a: &[u8]) -> Vec<&[u8]> {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   288
        super::split_lines(a).unwrap().iter().collect()
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   289
    }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   290
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   291
    fn diff(a: &[u8], b: &[u8]) -> Vec<(u32, u32, u32, u32)> {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   292
        let la = super::split_lines(a).unwrap();
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   293
        let lb = super::split_lines(b).unwrap();
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   294
        let hunks = super::diff(&la, &lb).unwrap();
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   295
        hunks.iter().map(|h| (h.a1, h.a2, h.b1, h.b2)).collect()
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   296
    }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   297
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   298
    #[test]
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   299
    fn test_split_lines() {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   300
        assert_eq!(split(b""), [] as [&[u8]; 0]);
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   301
        assert_eq!(split(b"\n"), [b"\n"]);
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   302
        assert_eq!(split(b"\r\n"), [b"\r\n"]);
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   303
        assert_eq!(split(b"X\nY"), [b"X\n" as &[u8], b"Y"]);
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   304
        assert_eq!(split(b"X\nY\n"), [b"X\n" as &[u8], b"Y\n"]);
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   305
        assert_eq!(split(b"X\r\nY\r\n"), [b"X\r\n" as &[u8], b"Y\r\n"]);
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   306
    }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   307
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   308
    #[test]
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   309
    fn test_diff_single_line() {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   310
        assert_eq!(diff(b"", b""), &[(0, 0, 0, 0)]);
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   311
        assert_eq!(diff(b"x", b"x"), &[(0, 1, 0, 1), (1, 1, 1, 1)]);
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   312
        assert_eq!(diff(b"x", b"y"), &[(1, 1, 1, 1)]);
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   313
    }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   314
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   315
    #[test]
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   316
    fn test_diff_multiple_lines() {
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   317
        assert_eq!(
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   318
            diff(
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   319
                b" line1 \n line2 \n line3 \n line4 \n REMOVED \n",
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   320
                b" ADDED \n line1 \n lined2_CHANGED \n line3 \n line4 \n"
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   321
            ),
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   322
            &[(0, 1, 1, 2), (2, 4, 3, 5), (5, 5, 5, 5)]
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   323
        );
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   324
    }
1b7a57a5b47a rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff changeset
   325
}