Mercurial > public > mercurial-scm > hg-stable
annotate rust/hg-core/src/bdiff.rs @ 52792:3ea5bd40b8dc
rust-nodemap: requiring immutable part to be Sync
This is necessary for the upcoming PyO3 bindings and does not bring
any problems.
In practical applications, this immutable part is often obtained by
`mmap` and satisfies the requirement.
author | Georges Racinet <georges.racinet@cloudcrane.io> |
---|---|
date | Wed, 25 Dec 2024 12:43:45 +0100 |
parents | 6183949219b2 |
children | 3ac28aa1430e |
rev | line source |
---|---|
52769
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. |
1b7a57a5b47a
rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
9 /// Must never be mutated apart from freeing it in `Drop`. |
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 for multiple threads to share `&Lines` because |
1b7a57a5b47a
rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
70 // `self.array` is never mutated except in `Drop`. |
1b7a57a5b47a
rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
71 unsafe impl Sync for Lines<'_> {} |
1b7a57a5b47a
rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
72 |
1b7a57a5b47a
rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
73 // 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
|
74 // `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
|
75 unsafe impl Send for Lines<'_> {} |
1b7a57a5b47a
rust: add safe bindings to bdiff.c
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
76 |
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 } |