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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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 }