diff --git a/rust/indexes/src/errors.rs b/rust/indexes/src/errors.rs --- a/rust/indexes/src/errors.rs +++ b/rust/indexes/src/errors.rs @@ -3,6 +3,9 @@ // This software may be used and distributed according to the terms of the // GNU General Public License version 2 or any later version. +use cpython::{Python, PyErr}; +use cpython::exc::RuntimeError; + error_chain! { foreign_links { Radix(::radixbuf::errors::Error); @@ -14,3 +17,12 @@ } } } + +/// Convert `Error` to Python `RuntimeError`s +impl From for PyErr { + fn from(e: Error) -> PyErr { + let gil = Python::acquire_gil(); + let py = gil.python(); + PyErr::new::(py, format!("{}", e)) + } +} diff --git a/rust/indexes/src/lib.rs b/rust/indexes/src/lib.rs --- a/rust/indexes/src/lib.rs +++ b/rust/indexes/src/lib.rs @@ -14,3 +14,6 @@ pub mod errors; pub mod nodemap; mod pybuf; + +#[allow(non_camel_case_types)] +pub mod pyext; diff --git a/rust/indexes/src/pyext.rs b/rust/indexes/src/pyext.rs new file mode 100644 --- /dev/null +++ b/rust/indexes/src/pyext.rs @@ -0,0 +1,54 @@ +// Copyright 2017 Facebook, Inc. +// +// This software may be used and distributed according to the terms of the +// GNU General Public License version 2 or any later version. + +use cpython::{PyResult, PyBytes, PyObject}; +use nodemap::NodeRevMap; +use pybuf::SimplePyBuf; +use std::slice; + +py_module_initializer!(indexes, initindexes, PyInit_indexes, |py, m| { + try!(m.add_class::(py)); + Ok(()) +}); + +py_class!(class nodemap |py| { + data nodemap: NodeRevMap, SimplePyBuf>; + + def __new__(_cls, changelog: &PyObject, index: &PyObject) -> PyResult { + let changelog_buf = SimplePyBuf::new(py, changelog); + let index_buf = SimplePyBuf::new(py, index); + let nm = NodeRevMap::new(changelog_buf, index_buf)?; + nodemap::create_instance(py, nm) + } + + def __getitem__(&self, key: PyBytes) -> PyResult> { + Ok(self.nodemap(py).node_to_rev(key.data(py))?) + } + + def __contains__(&self, key: PyBytes) -> PyResult { + Ok(self.nodemap(py).node_to_rev(key.data(py))?.is_some()) + } + + def partialmatch(&self, hex: PyBytes) -> PyResult> { + Ok(self.nodemap(py).hex_prefix_to_node(hex.data(py))?.map(|b| PyBytes::new(py, b))) + } + + def build(&self) -> PyResult { + let buf = self.nodemap(py).build_incrementally()?; + let slice = unsafe { slice::from_raw_parts(buf.as_ptr() as *const u8, buf.len() * 4) }; + Ok(PyBytes::new(py, slice)) + } + + def lag(&self) -> PyResult { + Ok(self.nodemap(py).lag()) + } + + @staticmethod + def emptyindexbuffer() -> PyResult { + let buf = NodeRevMap::, Vec>::empty_index_buffer(); + let slice = unsafe { slice::from_raw_parts(buf.as_ptr() as *const u8, buf.len() * 4) }; + Ok(PyBytes::new(py, slice)) + } +});