Mercurial > hg
annotate rust/hg-direct-ffi/src/ancestors.rs @ 40933:18513d6ef7d4
rust: changed Graph.parents to return [Revision; 2]
This will allow for simple iteration on parent revisions,
such as:
for parent in graph.parents(rev)?.iter().cloned()
This seems to be a zero overhead abstraction once built in
release mode.
Differential Revision: https://phab.mercurial-scm.org/D5415
author | Georges Racinet <gracinet@anybox.fr> |
---|---|
date | Fri, 30 Nov 2018 00:44:04 +0100 |
parents | 443eb4bc41af |
children | 6a551a2dc666 |
rev | line source |
---|---|
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; |
40862
54a60968f0aa
rust: look up HgRevlogIndex_GetParents() from symbol table
Yuya Nishihara <yuya@tcha.org>
parents:
40454
diff
changeset
|
19 |
54a60968f0aa
rust: look up HgRevlogIndex_GetParents() from symbol table
Yuya Nishihara <yuya@tcha.org>
parents:
40454
diff
changeset
|
20 extern "C" { |
54a60968f0aa
rust: look up HgRevlogIndex_GetParents() from symbol table
Yuya Nishihara <yuya@tcha.org>
parents:
40454
diff
changeset
|
21 fn HgRevlogIndex_GetParents( |
54a60968f0aa
rust: look up HgRevlogIndex_GetParents() from symbol table
Yuya Nishihara <yuya@tcha.org>
parents:
40454
diff
changeset
|
22 op: IndexPtr, |
54a60968f0aa
rust: look up HgRevlogIndex_GetParents() from symbol table
Yuya Nishihara <yuya@tcha.org>
parents:
40454
diff
changeset
|
23 rev: c_int, |
54a60968f0aa
rust: look up HgRevlogIndex_GetParents() from symbol table
Yuya Nishihara <yuya@tcha.org>
parents:
40454
diff
changeset
|
24 parents: *mut [c_int; 2], |
54a60968f0aa
rust: look up HgRevlogIndex_GetParents() from symbol table
Yuya Nishihara <yuya@tcha.org>
parents:
40454
diff
changeset
|
25 ) -> c_int; |
54a60968f0aa
rust: look up HgRevlogIndex_GetParents() from symbol table
Yuya Nishihara <yuya@tcha.org>
parents:
40454
diff
changeset
|
26 } |
40272
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
27 |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
28 /// 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
|
29 /// |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
30 /// 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
|
31 /// - the C index object (`index` member) |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
32 /// - the `index_get_parents()` function (`parents` member) |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
33 pub struct Index { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
34 index: IndexPtr, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
35 } |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
36 |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
37 impl Index { |
40862
54a60968f0aa
rust: look up HgRevlogIndex_GetParents() from symbol table
Yuya Nishihara <yuya@tcha.org>
parents:
40454
diff
changeset
|
38 pub fn new(index: IndexPtr) -> Self { |
40272
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
39 Index { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
40 index: index, |
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 } |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
43 } |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
44 |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
45 impl Graph for Index { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
46 /// wrap a call to the C extern parents function |
40933
18513d6ef7d4
rust: changed Graph.parents to return [Revision; 2]
Georges Racinet <gracinet@anybox.fr>
parents:
40863
diff
changeset
|
47 fn parents(&self, rev: Revision) -> Result<[Revision; 2], GraphError> { |
40272
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
48 let mut res: [c_int; 2] = [0; 2]; |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
49 let code = |
40862
54a60968f0aa
rust: look up HgRevlogIndex_GetParents() from symbol table
Yuya Nishihara <yuya@tcha.org>
parents:
40454
diff
changeset
|
50 unsafe { HgRevlogIndex_GetParents(self.index, rev, &mut res as *mut [c_int; 2]) }; |
40272
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
51 match code { |
40933
18513d6ef7d4
rust: changed Graph.parents to return [Revision; 2]
Georges Racinet <gracinet@anybox.fr>
parents:
40863
diff
changeset
|
52 0 => Ok(res), |
40272
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
53 _ => Err(GraphError::ParentOutOfRange(rev)), |
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 } |
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 |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
58 /// Wrapping of AncestorsIterator<Index> constructor, for C callers. |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
59 /// |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
60 /// Besides `initrevs`, `stoprev` and `inclusive`, that are converted |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
61 /// 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
|
62 #[no_mangle] |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
63 pub extern "C" fn rustlazyancestors_init( |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
64 index: IndexPtr, |
40454
a91a2837150b
rust: fix signature of rustlazyancestors_init() function
Yuya Nishihara <yuya@tcha.org>
parents:
40300
diff
changeset
|
65 initrevslen: ssize_t, |
40272
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
66 initrevs: *mut c_long, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
67 stoprev: c_long, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
68 inclusive: c_int, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
69 ) -> *mut AncestorsIterator<Index> { |
40454
a91a2837150b
rust: fix signature of rustlazyancestors_init() function
Yuya Nishihara <yuya@tcha.org>
parents:
40300
diff
changeset
|
70 assert!(initrevslen >= 0); |
40272
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
71 unsafe { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
72 raw_init( |
40862
54a60968f0aa
rust: look up HgRevlogIndex_GetParents() from symbol table
Yuya Nishihara <yuya@tcha.org>
parents:
40454
diff
changeset
|
73 Index::new(index), |
40454
a91a2837150b
rust: fix signature of rustlazyancestors_init() function
Yuya Nishihara <yuya@tcha.org>
parents:
40300
diff
changeset
|
74 initrevslen as usize, |
40272
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
75 initrevs, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
76 stoprev, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
77 inclusive, |
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 } |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
80 } |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
81 |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
82 /// Testable (for any Graph) version of rustlazyancestors_init |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
83 #[inline] |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
84 unsafe fn raw_init<G: Graph>( |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
85 graph: G, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
86 initrevslen: usize, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
87 initrevs: *mut c_long, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
88 stoprev: c_long, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
89 inclusive: c_int, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
90 ) -> *mut AncestorsIterator<G> { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
91 let inclb = match inclusive { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
92 0 => false, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
93 1 => true, |
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 return null_mut(); |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
96 } |
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 |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
99 let slice = slice::from_raw_parts(initrevs, initrevslen); |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
100 |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
101 Box::into_raw(Box::new(match AncestorsIterator::new( |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
102 graph, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
103 slice.into_iter().map(|&r| r as Revision), |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
104 stoprev as Revision, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
105 inclb, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
106 ) { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
107 Ok(it) => it, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
108 Err(_) => { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
109 return null_mut(); |
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 })) |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
112 } |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
113 |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
114 /// Deallocator to be called from C code |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
115 #[no_mangle] |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
116 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
|
117 raw_drop(raw_iter); |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
118 } |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
119 |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
120 /// Testable (for any Graph) version of rustlazayancestors_drop |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
121 #[inline] |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
122 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
|
123 unsafe { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
124 Box::from_raw(raw_iter); |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
125 } |
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 |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
128 /// Iteration main method to be called from C code |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
129 /// |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
130 /// We convert the end of iteration into NULL_REVISION, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
131 /// 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
|
132 /// iteration |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
133 #[no_mangle] |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
134 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
|
135 raw_next(raw) |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
136 } |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
137 |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
138 /// Testable (for any Graph) version of rustlazayancestors_next |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
139 #[inline] |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
140 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
|
141 let as_ref = unsafe { &mut *raw }; |
40863
443eb4bc41af
rust: propagate error of index_get_parents() properly
Yuya Nishihara <yuya@tcha.org>
parents:
40862
diff
changeset
|
142 let rev = match as_ref.next() { |
443eb4bc41af
rust: propagate error of index_get_parents() properly
Yuya Nishihara <yuya@tcha.org>
parents:
40862
diff
changeset
|
143 Some(Ok(rev)) => rev, |
443eb4bc41af
rust: propagate error of index_get_parents() properly
Yuya Nishihara <yuya@tcha.org>
parents:
40862
diff
changeset
|
144 Some(Err(_)) | None => NULL_REVISION, |
443eb4bc41af
rust: propagate error of index_get_parents() properly
Yuya Nishihara <yuya@tcha.org>
parents:
40862
diff
changeset
|
145 }; |
443eb4bc41af
rust: propagate error of index_get_parents() properly
Yuya Nishihara <yuya@tcha.org>
parents:
40862
diff
changeset
|
146 rev as c_long |
40272
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
147 } |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
148 |
40300
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
149 #[no_mangle] |
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
150 pub extern "C" fn rustlazyancestors_contains( |
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
151 raw: *mut AncestorsIterator<Index>, |
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
152 target: c_long, |
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
153 ) -> c_int { |
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
154 raw_contains(raw, target) |
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
155 } |
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
156 |
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
157 /// Testable (for any Graph) version of rustlazayancestors_next |
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
158 #[inline] |
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
159 fn raw_contains<G: Graph>( |
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
160 raw: *mut AncestorsIterator<G>, |
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
161 target: c_long, |
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
162 ) -> c_int { |
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
163 let as_ref = unsafe { &mut *raw }; |
40863
443eb4bc41af
rust: propagate error of index_get_parents() properly
Yuya Nishihara <yuya@tcha.org>
parents:
40862
diff
changeset
|
164 match as_ref.contains(target as Revision) { |
443eb4bc41af
rust: propagate error of index_get_parents() properly
Yuya Nishihara <yuya@tcha.org>
parents:
40862
diff
changeset
|
165 Ok(r) => r as c_int, |
443eb4bc41af
rust: propagate error of index_get_parents() properly
Yuya Nishihara <yuya@tcha.org>
parents:
40862
diff
changeset
|
166 Err(_) => -1, |
40300
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
167 } |
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
168 } |
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
169 |
40272
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
170 #[cfg(test)] |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
171 mod tests { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
172 use super::*; |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
173 use std::thread; |
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 #[derive(Clone, Debug)] |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
176 struct Stub; |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
177 |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
178 impl Graph for Stub { |
40933
18513d6ef7d4
rust: changed Graph.parents to return [Revision; 2]
Georges Racinet <gracinet@anybox.fr>
parents:
40863
diff
changeset
|
179 fn parents(&self, r: Revision) -> Result<[Revision; 2], GraphError> { |
40272
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
180 match r { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
181 25 => Err(GraphError::ParentOutOfRange(25)), |
40933
18513d6ef7d4
rust: changed Graph.parents to return [Revision; 2]
Georges Racinet <gracinet@anybox.fr>
parents:
40863
diff
changeset
|
182 _ => Ok([1, 2]), |
40272
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
183 } |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
184 } |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
185 } |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
186 |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
187 /// Helper for test_init_next() |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
188 fn stub_raw_init( |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
189 initrevslen: usize, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
190 initrevs: usize, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
191 stoprev: c_long, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
192 inclusive: c_int, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
193 ) -> usize { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
194 unsafe { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
195 raw_init( |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
196 Stub, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
197 initrevslen, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
198 initrevs as *mut c_long, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
199 stoprev, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
200 inclusive, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
201 ) as usize |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
202 } |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
203 } |
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 fn stub_raw_init_from_vec( |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
206 mut initrevs: Vec<c_long>, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
207 stoprev: c_long, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
208 inclusive: c_int, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
209 ) -> *mut AncestorsIterator<Stub> { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
210 unsafe { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
211 raw_init( |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
212 Stub, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
213 initrevs.len(), |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
214 initrevs.as_mut_ptr(), |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
215 stoprev, |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
216 inclusive, |
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 } |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
219 } |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
220 |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
221 #[test] |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
222 // 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
|
223 // and try to use it afterwards |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
224 // 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
|
225 // 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
|
226 fn test_init_next() { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
227 let mut initrevs: Vec<c_long> = vec![11, 13]; |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
228 let initrevs_len = initrevs.len(); |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
229 let initrevs_ptr = initrevs.as_mut_ptr() as usize; |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
230 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
|
231 let raw = handler.join().unwrap() as *mut AncestorsIterator<Stub>; |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
232 |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
233 assert_eq!(raw_next(raw), 13); |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
234 assert_eq!(raw_next(raw), 11); |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
235 assert_eq!(raw_next(raw), 2); |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
236 assert_eq!(raw_next(raw), 1); |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
237 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
|
238 raw_drop(raw); |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
239 } |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
240 |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
241 #[test] |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
242 fn test_init_wrong_bool() { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
243 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
|
244 } |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
245 |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
246 #[test] |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
247 fn test_empty() { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
248 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
|
249 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
|
250 raw_drop(raw); |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
251 } |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
252 |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
253 #[test] |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
254 fn test_init_err_out_of_range() { |
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
255 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
|
256 } |
40300
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
257 |
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
258 #[test] |
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
259 fn test_contains() { |
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
260 let raw = stub_raw_init_from_vec(vec![5, 6], 0, 1); |
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
261 assert_eq!(raw_contains(raw, 5), 1); |
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
262 assert_eq!(raw_contains(raw, 2), 1); |
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
263 } |
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
264 |
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
265 #[test] |
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
266 fn test_contains_exclusive() { |
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
267 let raw = stub_raw_init_from_vec(vec![5, 6], 0, 0); |
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
268 assert_eq!(raw_contains(raw, 5), 0); |
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
269 assert_eq!(raw_contains(raw, 2), 1); |
72b94f946e90
rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents:
40272
diff
changeset
|
270 } |
40272
a36c5e23c055
rust: iterator bindings to C code
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
271 } |