rust/hg-direct-ffi/src/ancestors.rs
author Georges Racinet <gracinet@anybox.fr>
Thu, 27 Sep 2018 16:51:36 +0200
changeset 40272 a36c5e23c055
child 40300 72b94f946e90
permissions -rw-r--r--
rust: iterator bindings to C code In this changeset, still made of Rust code only, we expose the Rust iterator for instantiation and consumption from C code. The idea is that both the index and index_get_parents() will be passed from the C extension, hence avoiding a hard link dependency to parsers.so, so that the crate can still be built and tested independently. On the other hand, parsers.so will use the symbols defined in this changeset.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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
}