dirs_multiset.rs
127 lines
| 3.8 KiB
| application/rls-services+xml
|
RustLexer
Raphaël Gomès
|
r42991 | // dirs_multiset.rs | ||
// | ||||
// Copyright 2019 Raphaël Gomès <rgomes@octobus.net> | ||||
// | ||||
// This software may be used and distributed according to the terms of the | ||||
// GNU General Public License version 2 or any later version. | ||||
//! Bindings for the `hg::dirstate::dirs_multiset` file provided by the | ||||
//! `hg-core` package. | ||||
use std::cell::RefCell; | ||||
Raphaël Gomès
|
r42997 | use std::convert::TryInto; | ||
Raphaël Gomès
|
r42991 | |||
use cpython::{ | ||||
Raphaël Gomès
|
r42997 | exc, ObjectProtocol, PyBytes, PyClone, PyDict, PyErr, PyObject, PyResult, | ||
Python, | ||||
Raphaël Gomès
|
r42991 | }; | ||
Yuya Nishihara
|
r43115 | use crate::dirstate::extract_dirstate; | ||
use crate::ref_sharing::{PySharedRefCell, PySharedState}; | ||||
Yuya Nishihara
|
r43070 | use hg::{DirsMultiset, DirstateMapError, DirstateParseError, EntryState}; | ||
Raphaël Gomès
|
r42991 | |||
py_class!(pub class Dirs |py| { | ||||
Yuya Nishihara
|
r43115 | data inner: PySharedRefCell<DirsMultiset>; | ||
Raphaël Gomès
|
r42997 | data py_shared_state: PySharedState; | ||
Raphaël Gomès
|
r42991 | |||
// `map` is either a `dict` or a flat iterator (usually a `set`, sometimes | ||||
// a `list`) | ||||
def __new__( | ||||
_cls, | ||||
map: PyObject, | ||||
skip: Option<PyObject> = None | ||||
) -> PyResult<Self> { | ||||
Raphaël Gomès
|
r42994 | let mut skip_state: Option<EntryState> = None; | ||
Raphaël Gomès
|
r42991 | if let Some(skip) = skip { | ||
Raphaël Gomès
|
r42994 | skip_state = Some( | ||
skip.extract::<PyBytes>(py)?.data(py)[0] | ||||
.try_into() | ||||
.map_err(|e: DirstateParseError| { | ||||
PyErr::new::<exc::ValueError, _>(py, e.to_string()) | ||||
})?, | ||||
); | ||||
Raphaël Gomès
|
r42991 | } | ||
Raphaël Gomès
|
r42993 | let inner = if let Ok(map) = map.cast_as::<PyDict>(py) { | ||
let dirstate = extract_dirstate(py, &map)?; | ||||
Yuya Nishihara
|
r43070 | DirsMultiset::from_dirstate(&dirstate, skip_state) | ||
Raphaël Gomès
|
r42991 | } else { | ||
let map: Result<Vec<Vec<u8>>, PyErr> = map | ||||
.iter(py)? | ||||
.map(|o| Ok(o?.extract::<PyBytes>(py)?.data(py).to_owned())) | ||||
.collect(); | ||||
Yuya Nishihara
|
r43070 | DirsMultiset::from_manifest(&map?) | ||
Raphaël Gomès
|
r42993 | }; | ||
Raphaël Gomès
|
r42991 | |||
Raphaël Gomès
|
r42997 | Self::create_instance( | ||
py, | ||||
Yuya Nishihara
|
r43115 | PySharedRefCell::new(inner), | ||
Raphaël Gomès
|
r42997 | PySharedState::default() | ||
) | ||||
Raphaël Gomès
|
r42991 | } | ||
def addpath(&self, path: PyObject) -> PyResult<PyObject> { | ||||
Raphaël Gomès
|
r42997 | self.borrow_mut(py)?.add_path( | ||
Raphaël Gomès
|
r42991 | path.extract::<PyBytes>(py)?.data(py), | ||
); | ||||
Ok(py.None()) | ||||
} | ||||
def delpath(&self, path: PyObject) -> PyResult<PyObject> { | ||||
Raphaël Gomès
|
r42997 | self.borrow_mut(py)?.delete_path( | ||
Raphaël Gomès
|
r42991 | path.extract::<PyBytes>(py)?.data(py), | ||
) | ||||
.and(Ok(py.None())) | ||||
.or_else(|e| { | ||||
match e { | ||||
DirstateMapError::PathNotFound(_p) => { | ||||
Err(PyErr::new::<exc::ValueError, _>( | ||||
py, | ||||
"expected a value, found none".to_string(), | ||||
)) | ||||
} | ||||
DirstateMapError::EmptyPath => { | ||||
Ok(py.None()) | ||||
} | ||||
} | ||||
}) | ||||
} | ||||
Raphaël Gomès
|
r42997 | def __iter__(&self) -> PyResult<DirsMultisetKeysIterator> { | ||
Yuya Nishihara
|
r43117 | let (leak_handle, leaked_ref) = unsafe { self.leak_immutable(py)? }; | ||
Raphaël Gomès
|
r42997 | DirsMultisetKeysIterator::create_instance( | ||
py, | ||||
Yuya Nishihara
|
r43116 | RefCell::new(Some(leak_handle)), | ||
RefCell::new(Box::new(leaked_ref.iter())), | ||||
Raphaël Gomès
|
r42997 | ) | ||
Raphaël Gomès
|
r42991 | } | ||
def __contains__(&self, item: PyObject) -> PyResult<bool> { | ||||
Ok(self | ||||
Raphaël Gomès
|
r42997 | .inner(py) | ||
Raphaël Gomès
|
r42991 | .borrow() | ||
Raphaël Gomès
|
r42995 | .contains(item.extract::<PyBytes>(py)?.data(py).as_ref())) | ||
Raphaël Gomès
|
r42991 | } | ||
}); | ||||
Raphaël Gomès
|
r42997 | |||
py_shared_ref!(Dirs, DirsMultiset, inner, DirsMultisetLeakedRef,); | ||||
impl Dirs { | ||||
pub fn from_inner(py: Python, d: DirsMultiset) -> PyResult<Self> { | ||||
Yuya Nishihara
|
r43115 | Self::create_instance( | ||
py, | ||||
PySharedRefCell::new(d), | ||||
PySharedState::default(), | ||||
) | ||||
Raphaël Gomès
|
r42997 | } | ||
fn translate_key(py: Python, res: &Vec<u8>) -> PyResult<Option<PyBytes>> { | ||||
Ok(Some(PyBytes::new(py, res))) | ||||
} | ||||
} | ||||
py_shared_sequence_iterator!( | ||||
DirsMultisetKeysIterator, | ||||
DirsMultisetLeakedRef, | ||||
Vec<u8>, | ||||
Dirs::translate_key, | ||||
Option<PyBytes> | ||||
); | ||||