Mercurial > public > mercurial-scm > hg
diff rust/hg-cpython/src/dirstate/copymap.rs @ 42754:4e8f504424f3
rust-dirstate: rust-cpython bridge for dirstatemap
This change also showcases the limitations of the `py_shared_ref!` macro.
See the previous commit 'rust-dirstate: rust implementation of dirstatemap`
for an explanation for the TODOs in the code.
Differential Revision: https://phab.mercurial-scm.org/D6633
author | Rapha?l Gom?s <rgomes@octobus.net> |
---|---|
date | Wed, 10 Jul 2019 09:56:53 +0200 |
parents | |
children | 67853749961b |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rust/hg-cpython/src/dirstate/copymap.rs Wed Jul 10 09:56:53 2019 +0200 @@ -0,0 +1,116 @@ +// copymap.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 `hg::dirstate::dirstate_map::CopyMap` provided by the +//! `hg-core` package. + +use cpython::{PyBytes, PyClone, PyDict, PyObject, PyResult, Python}; +use std::cell::RefCell; + +use crate::dirstate::dirstate_map::{DirstateMap, DirstateMapLeakedRef}; + +py_class!(pub class CopyMap |py| { + data dirstate_map: DirstateMap; + + def __getitem__(&self, key: PyObject) -> PyResult<PyBytes> { + (*self.dirstate_map(py)).copymapgetitem(py, key) + } + + def __len__(&self) -> PyResult<usize> { + self.dirstate_map(py).copymaplen(py) + } + + def __contains__(&self, key: PyObject) -> PyResult<bool> { + self.dirstate_map(py).copymapcontains(py, key) + } + + def get( + &self, + key: PyObject, + default: Option<PyObject> = None + ) -> PyResult<Option<PyObject>> { + self.dirstate_map(py).copymapget(py, key, default) + } + + def pop( + &self, + key: PyObject, + default: Option<PyObject> = None + ) -> PyResult<Option<PyObject>> { + self.dirstate_map(py).copymappop(py, key, default) + } + + def __iter__(&self) -> PyResult<CopyMapKeysIterator> { + self.dirstate_map(py).copymapiter(py) + } + + // Python's `dict()` builtin works with either a subclass of dict + // or an abstract mapping. Said mapping needs to implement `__getitem__` + // and `keys`. + def keys(&self) -> PyResult<CopyMapKeysIterator> { + self.dirstate_map(py).copymapiter(py) + } + + def items(&self) -> PyResult<CopyMapItemsIterator> { + self.dirstate_map(py).copymapitemsiter(py) + } + + def iteritems(&self) -> PyResult<CopyMapItemsIterator> { + self.dirstate_map(py).copymapitemsiter(py) + } + + def __setitem__( + &self, + key: PyObject, + item: PyObject + ) -> PyResult<()> { + self.dirstate_map(py).copymapsetitem(py, key, item)?; + Ok(()) + } + + def copy(&self) -> PyResult<PyDict> { + self.dirstate_map(py).copymapcopy(py) + } + +}); + +impl CopyMap { + pub fn from_inner(py: Python, dm: DirstateMap) -> PyResult<Self> { + Self::create_instance(py, dm) + } + fn translate_key( + py: Python, + res: (&Vec<u8>, &Vec<u8>), + ) -> PyResult<Option<PyBytes>> { + Ok(Some(PyBytes::new(py, res.0))) + } + fn translate_key_value( + py: Python, + res: (&Vec<u8>, &Vec<u8>), + ) -> PyResult<Option<(PyBytes, PyBytes)>> { + let (k, v) = res; + Ok(Some((PyBytes::new(py, k), PyBytes::new(py, v)))) + } +} + +py_shared_mapping_iterator!( + CopyMapKeysIterator, + DirstateMapLeakedRef, + Vec<u8>, + Vec<u8>, + CopyMap::translate_key, + Option<PyBytes> +); + +py_shared_mapping_iterator!( + CopyMapItemsIterator, + DirstateMapLeakedRef, + Vec<u8>, + Vec<u8>, + CopyMap::translate_key_value, + Option<(PyBytes, PyBytes)> +);