2019-04-03 09:01:28 +00:00
|
|
|
//! Test slf: PyRef/PyMutRef<Self>(especially, slf.into::<Py>) works
|
2019-03-28 13:55:41 +00:00
|
|
|
use pyo3;
|
|
|
|
use pyo3::prelude::*;
|
|
|
|
use pyo3::types::{PyBytes, PyString};
|
|
|
|
use pyo3::PyIterProtocol;
|
|
|
|
use std::collections::HashMap;
|
|
|
|
|
|
|
|
mod common;
|
|
|
|
|
|
|
|
/// Assumes it's a file reader or so.
|
2019-04-03 09:01:28 +00:00
|
|
|
/// Inspired by https://github.com/jothan/cordoba, thanks.
|
2019-03-28 13:55:41 +00:00
|
|
|
#[pyclass]
|
2019-04-03 09:01:28 +00:00
|
|
|
#[derive(Clone)]
|
2019-03-28 13:55:41 +00:00
|
|
|
struct Reader {
|
|
|
|
inner: HashMap<u8, String>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[pymethods]
|
|
|
|
impl Reader {
|
2019-08-11 06:27:03 +00:00
|
|
|
fn clone_ref(slf: PyRef<Self>) -> PyRef<Self> {
|
|
|
|
slf
|
|
|
|
}
|
2019-04-03 08:14:03 +00:00
|
|
|
fn get_iter(slf: PyRef<Self>, keys: Py<PyBytes>) -> PyResult<Iter> {
|
2019-03-28 13:55:41 +00:00
|
|
|
Ok(Iter {
|
|
|
|
reader: slf.into(),
|
2019-04-03 09:01:28 +00:00
|
|
|
keys,
|
|
|
|
idx: 0,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
fn get_iter_and_reset(
|
|
|
|
mut slf: PyRefMut<Self>,
|
|
|
|
keys: Py<PyBytes>,
|
|
|
|
py: Python,
|
|
|
|
) -> PyResult<Iter> {
|
|
|
|
let reader = Py::new(py, slf.clone())?;
|
|
|
|
slf.inner.clear();
|
|
|
|
Ok(Iter {
|
|
|
|
reader,
|
|
|
|
keys,
|
2019-03-28 13:55:41 +00:00
|
|
|
idx: 0,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[pyclass]
|
|
|
|
struct Iter {
|
|
|
|
reader: Py<Reader>,
|
|
|
|
keys: Py<PyBytes>,
|
|
|
|
idx: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[pyproto]
|
|
|
|
impl PyIterProtocol for Iter {
|
|
|
|
fn __iter__(slf: PyRefMut<Self>) -> PyResult<PyObject> {
|
|
|
|
let py = unsafe { Python::assume_gil_acquired() };
|
|
|
|
Ok(slf.to_object(py))
|
|
|
|
}
|
|
|
|
fn __next__(mut slf: PyRefMut<Self>) -> PyResult<Option<PyObject>> {
|
|
|
|
let py = unsafe { Python::assume_gil_acquired() };
|
|
|
|
match slf.keys.as_ref(py).as_bytes().get(slf.idx) {
|
|
|
|
Some(&b) => {
|
|
|
|
let res = slf
|
|
|
|
.reader
|
|
|
|
.as_ref(py)
|
|
|
|
.inner
|
|
|
|
.get(&b)
|
|
|
|
.map(|s| PyString::new(py, s).into());
|
|
|
|
slf.idx += 1;
|
|
|
|
Ok(res)
|
|
|
|
}
|
|
|
|
None => Ok(None),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-11 06:27:03 +00:00
|
|
|
fn reader() -> Reader {
|
|
|
|
let reader = [(1, "a"), (2, "b"), (3, "c"), (4, "d"), (5, "e")];
|
|
|
|
Reader {
|
|
|
|
inner: reader.iter().map(|(k, v)| (*k, v.to_string())).collect(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-28 13:55:41 +00:00
|
|
|
#[test]
|
|
|
|
fn test_nested_iter() {
|
|
|
|
let gil = Python::acquire_gil();
|
|
|
|
let py = gil.python();
|
2019-08-24 17:21:45 +00:00
|
|
|
let reader: PyObject = reader().into_py(py);
|
2019-03-28 13:55:41 +00:00
|
|
|
py_assert!(
|
|
|
|
py,
|
|
|
|
reader,
|
|
|
|
"list(reader.get_iter(bytes([3, 5, 2]))) == ['c', 'e', 'b']"
|
|
|
|
);
|
|
|
|
}
|
2019-04-03 09:01:28 +00:00
|
|
|
|
2019-08-11 06:27:03 +00:00
|
|
|
#[test]
|
|
|
|
fn test_clone_ref() {
|
|
|
|
let gil = Python::acquire_gil();
|
|
|
|
let py = gil.python();
|
2019-08-24 17:21:45 +00:00
|
|
|
let reader: PyObject = reader().into_py(py);
|
2019-08-11 06:27:03 +00:00
|
|
|
py_assert!(py, reader, "reader == reader.clone_ref()");
|
|
|
|
}
|
|
|
|
|
2019-04-03 09:01:28 +00:00
|
|
|
#[test]
|
|
|
|
fn test_nested_iter_reset() {
|
|
|
|
let gil = Python::acquire_gil();
|
|
|
|
let py = gil.python();
|
2019-08-11 06:27:03 +00:00
|
|
|
let reader = PyRef::new(py, reader()).unwrap();
|
2019-04-03 09:01:28 +00:00
|
|
|
py_assert!(
|
|
|
|
py,
|
2019-08-11 06:27:03 +00:00
|
|
|
reader,
|
|
|
|
"list(reader.get_iter_and_reset(bytes([3, 5, 2]))) == ['c', 'e', 'b']"
|
2019-04-03 09:01:28 +00:00
|
|
|
);
|
|
|
|
assert!(reader.inner.is_empty());
|
|
|
|
}
|