rust/hg-direct-ffi/src/ancestors.rs
author Pierre-Yves David <pierre-yves.david@octobus.net>
Wed, 12 Jun 2019 14:22:49 +0100
changeset 42711 716d575df275
parent 40950 18513d6ef7d4
child 42829 6a551a2dc666
permissions -rw-r--r--
upgrade: always use full text if "full-add" mode is enable We should not be using a delta since the goal is to perform a full addition from scratch in all cases. Without this patch, `hg debugupgraderepo --optimize re-delta-fulladd --run` can crash.
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;
40880
54a60968f0aa rust: look up HgRevlogIndex_GetParents() from symbol table
Yuya Nishihara <yuya@tcha.org>
parents: 40428
diff changeset
    19
54a60968f0aa rust: look up HgRevlogIndex_GetParents() from symbol table
Yuya Nishihara <yuya@tcha.org>
parents: 40428
diff changeset
    20
extern "C" {
54a60968f0aa rust: look up HgRevlogIndex_GetParents() from symbol table
Yuya Nishihara <yuya@tcha.org>
parents: 40428
diff changeset
    21
    fn HgRevlogIndex_GetParents(
54a60968f0aa rust: look up HgRevlogIndex_GetParents() from symbol table
Yuya Nishihara <yuya@tcha.org>
parents: 40428
diff changeset
    22
        op: IndexPtr,
54a60968f0aa rust: look up HgRevlogIndex_GetParents() from symbol table
Yuya Nishihara <yuya@tcha.org>
parents: 40428
diff changeset
    23
        rev: c_int,
54a60968f0aa rust: look up HgRevlogIndex_GetParents() from symbol table
Yuya Nishihara <yuya@tcha.org>
parents: 40428
diff changeset
    24
        parents: *mut [c_int; 2],
54a60968f0aa rust: look up HgRevlogIndex_GetParents() from symbol table
Yuya Nishihara <yuya@tcha.org>
parents: 40428
diff changeset
    25
    ) -> c_int;
54a60968f0aa rust: look up HgRevlogIndex_GetParents() from symbol table
Yuya Nishihara <yuya@tcha.org>
parents: 40428
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 {
40880
54a60968f0aa rust: look up HgRevlogIndex_GetParents() from symbol table
Yuya Nishihara <yuya@tcha.org>
parents: 40428
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
40950
18513d6ef7d4 rust: changed Graph.parents to return [Revision; 2]
Georges Racinet <gracinet@anybox.fr>
parents: 40881
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 =
40880
54a60968f0aa rust: look up HgRevlogIndex_GetParents() from symbol table
Yuya Nishihara <yuya@tcha.org>
parents: 40428
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 {
40950
18513d6ef7d4 rust: changed Graph.parents to return [Revision; 2]
Georges Racinet <gracinet@anybox.fr>
parents: 40881
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,
40428
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> {
40428
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(
40880
54a60968f0aa rust: look up HgRevlogIndex_GetParents() from symbol table
Yuya Nishihara <yuya@tcha.org>
parents: 40428
diff changeset
    73
            Index::new(index),
40428
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 };
40881
443eb4bc41af rust: propagate error of index_get_parents() properly
Yuya Nishihara <yuya@tcha.org>
parents: 40880
diff changeset
   142
    let rev = match as_ref.next() {
443eb4bc41af rust: propagate error of index_get_parents() properly
Yuya Nishihara <yuya@tcha.org>
parents: 40880
diff changeset
   143
        Some(Ok(rev)) => rev,
443eb4bc41af rust: propagate error of index_get_parents() properly
Yuya Nishihara <yuya@tcha.org>
parents: 40880
diff changeset
   144
        Some(Err(_)) | None => NULL_REVISION,
443eb4bc41af rust: propagate error of index_get_parents() properly
Yuya Nishihara <yuya@tcha.org>
parents: 40880
diff changeset
   145
    };
443eb4bc41af rust: propagate error of index_get_parents() properly
Yuya Nishihara <yuya@tcha.org>
parents: 40880
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 };
40881
443eb4bc41af rust: propagate error of index_get_parents() properly
Yuya Nishihara <yuya@tcha.org>
parents: 40880
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: 40880
diff changeset
   165
        Ok(r) => r as c_int,
443eb4bc41af rust: propagate error of index_get_parents() properly
Yuya Nishihara <yuya@tcha.org>
parents: 40880
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 {
40950
18513d6ef7d4 rust: changed Graph.parents to return [Revision; 2]
Georges Racinet <gracinet@anybox.fr>
parents: 40881
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)),
40950
18513d6ef7d4 rust: changed Graph.parents to return [Revision; 2]
Georges Racinet <gracinet@anybox.fr>
parents: 40881
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
}