author | Pierre-Yves David <pierre-yves.david@octobus.net> |
Tue, 11 Mar 2025 02:29:42 +0100 | |
branch | stable |
changeset 53042 | cdd7bf612c7b |
parent 53016 | 3ac28aa1430e |
permissions | -rw-r--r-- |
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 |
} |