author | Georges Racinet <gracinet@anybox.fr> |
Thu, 27 Sep 2018 16:51:36 +0200 | |
changeset 40272 | a36c5e23c055 |
child 40300 | 72b94f946e90 |
permissions | -rw-r--r-- |
40272
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
1 |
// Copyright 2018 Georges Racinet <gracinet@anybox.fr> |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
2 |
// |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
3 |
// This software may be used and distributed according to the terms of the |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
4 |
// GNU General Public License version 2 or any later version. |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
5 |
|
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
6 |
//! Bindings for CPython extension code |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
7 |
//! |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
8 |
//! This exposes methods to build and use a `rustlazyancestors` iterator |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
9 |
//! from C code, using an index and its parents function that are passed |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
10 |
//! from the caller at instantiation. |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
11 |
|
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
12 |
use hg::AncestorsIterator; |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
13 |
use hg::{Graph, GraphError, Revision, NULL_REVISION}; |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
14 |
use libc::{c_int, c_long, c_void, ssize_t}; |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
15 |
use std::ptr::null_mut; |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
16 |
use std::slice; |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
17 |
|
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
18 |
type IndexPtr = *mut c_void; |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
19 |
type IndexParentsFn = |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
20 |
unsafe extern "C" fn(index: IndexPtr, rev: ssize_t, ps: *mut [c_int; 2], max_rev: c_int) |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
21 |
-> c_int; |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
22 |
|
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
23 |
/// A Graph backed up by objects and functions from revlog.c |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
24 |
/// |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
25 |
/// This implementation of the Graph trait, relies on (pointers to) |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
26 |
/// - the C index object (`index` member) |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
27 |
/// - the `index_get_parents()` function (`parents` member) |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
28 |
pub struct Index { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
29 |
index: IndexPtr, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
30 |
parents: IndexParentsFn, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
31 |
} |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
32 |
|
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
33 |
impl Index { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
34 |
pub fn new(index: IndexPtr, parents: IndexParentsFn) -> Self { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
35 |
Index { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
36 |
index: index, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
37 |
parents: parents, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
38 |
} |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
39 |
} |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
40 |
} |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
41 |
|
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
42 |
impl Graph for Index { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
43 |
/// wrap a call to the C extern parents function |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
44 |
fn parents(&self, rev: Revision) -> Result<(Revision, Revision), GraphError> { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
45 |
let mut res: [c_int; 2] = [0; 2]; |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
46 |
let code = |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
47 |
unsafe { (self.parents)(self.index, rev as ssize_t, &mut res as *mut [c_int; 2], rev) }; |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
48 |
match code { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
49 |
0 => Ok((res[0], res[1])), |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
50 |
_ => Err(GraphError::ParentOutOfRange(rev)), |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
51 |
} |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
52 |
} |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
53 |
} |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
54 |
|
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
55 |
/// Wrapping of AncestorsIterator<Index> constructor, for C callers. |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
56 |
/// |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
57 |
/// Besides `initrevs`, `stoprev` and `inclusive`, that are converted |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
58 |
/// we receive the index and the parents function as pointers |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
59 |
#[no_mangle] |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
60 |
pub extern "C" fn rustlazyancestors_init( |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
61 |
index: IndexPtr, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
62 |
parents: IndexParentsFn, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
63 |
initrevslen: usize, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
64 |
initrevs: *mut c_long, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
65 |
stoprev: c_long, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
66 |
inclusive: c_int, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
67 |
) -> *mut AncestorsIterator<Index> { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
68 |
unsafe { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
69 |
raw_init( |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
70 |
Index::new(index, parents), |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
71 |
initrevslen, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
72 |
initrevs, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
73 |
stoprev, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
74 |
inclusive, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
75 |
) |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
76 |
} |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
77 |
} |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
78 |
|
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
79 |
/// Testable (for any Graph) version of rustlazyancestors_init |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
80 |
#[inline] |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
81 |
unsafe fn raw_init<G: Graph>( |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
82 |
graph: G, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
83 |
initrevslen: usize, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
84 |
initrevs: *mut c_long, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
85 |
stoprev: c_long, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
86 |
inclusive: c_int, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
87 |
) -> *mut AncestorsIterator<G> { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
88 |
let inclb = match inclusive { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
89 |
0 => false, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
90 |
1 => true, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
91 |
_ => { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
92 |
return null_mut(); |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
93 |
} |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
94 |
}; |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
95 |
|
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
96 |
let slice = slice::from_raw_parts(initrevs, initrevslen); |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
97 |
|
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
98 |
Box::into_raw(Box::new(match AncestorsIterator::new( |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
99 |
graph, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
100 |
slice.into_iter().map(|&r| r as Revision), |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
101 |
stoprev as Revision, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
102 |
inclb, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
103 |
) { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
104 |
Ok(it) => it, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
105 |
Err(_) => { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
106 |
return null_mut(); |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
107 |
} |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
108 |
})) |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
109 |
} |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
110 |
|
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
111 |
/// Deallocator to be called from C code |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
112 |
#[no_mangle] |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
113 |
pub extern "C" fn rustlazyancestors_drop(raw_iter: *mut AncestorsIterator<Index>) { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
114 |
raw_drop(raw_iter); |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
115 |
} |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
116 |
|
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
117 |
/// Testable (for any Graph) version of rustlazayancestors_drop |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
118 |
#[inline] |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
119 |
fn raw_drop<G: Graph>(raw_iter: *mut AncestorsIterator<G>) { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
120 |
unsafe { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
121 |
Box::from_raw(raw_iter); |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
122 |
} |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
123 |
} |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
124 |
|
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
125 |
/// Iteration main method to be called from C code |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
126 |
/// |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
127 |
/// We convert the end of iteration into NULL_REVISION, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
128 |
/// it will be up to the C wrapper to convert that back into a Python end of |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
129 |
/// iteration |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
130 |
#[no_mangle] |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
131 |
pub extern "C" fn rustlazyancestors_next(raw: *mut AncestorsIterator<Index>) -> c_long { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
132 |
raw_next(raw) |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
133 |
} |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
134 |
|
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
135 |
/// Testable (for any Graph) version of rustlazayancestors_next |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
136 |
#[inline] |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
137 |
fn raw_next<G: Graph>(raw: *mut AncestorsIterator<G>) -> c_long { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
138 |
let as_ref = unsafe { &mut *raw }; |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
139 |
as_ref.next().unwrap_or(NULL_REVISION) as c_long |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
140 |
} |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
141 |
|
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
142 |
#[cfg(test)] |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
143 |
mod tests { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
144 |
use super::*; |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
145 |
use std::thread; |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
146 |
|
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
147 |
#[derive(Clone, Debug)] |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
148 |
struct Stub; |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
149 |
|
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
150 |
impl Graph for Stub { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
151 |
fn parents(&self, r: Revision) -> Result<(Revision, Revision), GraphError> { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
152 |
match r { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
153 |
25 => Err(GraphError::ParentOutOfRange(25)), |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
154 |
_ => Ok((1, 2)), |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
155 |
} |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
156 |
} |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
157 |
} |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
158 |
|
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
159 |
/// Helper for test_init_next() |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
160 |
fn stub_raw_init( |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
161 |
initrevslen: usize, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
162 |
initrevs: usize, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
163 |
stoprev: c_long, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
164 |
inclusive: c_int, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
165 |
) -> usize { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
166 |
unsafe { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
167 |
raw_init( |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
168 |
Stub, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
169 |
initrevslen, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
170 |
initrevs as *mut c_long, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
171 |
stoprev, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
172 |
inclusive, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
173 |
) as usize |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
174 |
} |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
175 |
} |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
176 |
|
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
177 |
fn stub_raw_init_from_vec( |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
178 |
mut initrevs: Vec<c_long>, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
179 |
stoprev: c_long, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
180 |
inclusive: c_int, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
181 |
) -> *mut AncestorsIterator<Stub> { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
182 |
unsafe { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
183 |
raw_init( |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
184 |
Stub, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
185 |
initrevs.len(), |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
186 |
initrevs.as_mut_ptr(), |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
187 |
stoprev, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
188 |
inclusive, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
189 |
) |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
190 |
} |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
191 |
} |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
192 |
|
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
193 |
#[test] |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
194 |
// Test what happens when we init an Iterator as with the exposed C ABI |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
195 |
// and try to use it afterwards |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
196 |
// We spawn new threads, in order to make memory consistency harder |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
197 |
// but this forces us to convert the pointers into shareable usizes. |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
198 |
fn test_init_next() { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
199 |
let mut initrevs: Vec<c_long> = vec![11, 13]; |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
200 |
let initrevs_len = initrevs.len(); |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
201 |
let initrevs_ptr = initrevs.as_mut_ptr() as usize; |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
202 |
let handler = thread::spawn(move || stub_raw_init(initrevs_len, initrevs_ptr, 0, 1)); |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
203 |
let raw = handler.join().unwrap() as *mut AncestorsIterator<Stub>; |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
204 |
|
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
205 |
assert_eq!(raw_next(raw), 13); |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
206 |
assert_eq!(raw_next(raw), 11); |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
207 |
assert_eq!(raw_next(raw), 2); |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
208 |
assert_eq!(raw_next(raw), 1); |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
209 |
assert_eq!(raw_next(raw), NULL_REVISION as c_long); |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
210 |
raw_drop(raw); |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
211 |
} |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
212 |
|
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
213 |
#[test] |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
214 |
fn test_init_wrong_bool() { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
215 |
assert_eq!(stub_raw_init_from_vec(vec![11, 13], 0, 2), null_mut()); |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
216 |
} |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
217 |
|
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
218 |
#[test] |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
219 |
fn test_empty() { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
220 |
let raw = stub_raw_init_from_vec(vec![], 0, 1); |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
221 |
assert_eq!(raw_next(raw), NULL_REVISION as c_long); |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
222 |
raw_drop(raw); |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
223 |
} |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
224 |
|
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
225 |
#[test] |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
226 |
fn test_init_err_out_of_range() { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
227 |
assert!(stub_raw_init_from_vec(vec![25], 0, 0).is_null()); |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
228 |
} |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
229 |
} |