comparison rust/hg-cpython/src/parsers.rs @ 43208:1ca3823aeefd

rust-cpython: add wrapper around decapsule_make_dirstate_tuple() There are a couple of safety issues. First, the returned function pointer must be unsafe. Second, its return value must be a raw pointer (i.e. python27_sys::PyObject), not a cpython::PyObject. The wrapper function will address these issues.
author Yuya Nishihara <yuya@tcha.org>
date Sun, 13 Oct 2019 16:55:17 +0900
parents 7a01778bc7b7
children ce088b38f92b
comparison
equal deleted inserted replaced
43207:4aa9f3a1c1df 43208:1ca3823aeefd
13 use cpython::{ 13 use cpython::{
14 exc, PyBytes, PyDict, PyErr, PyInt, PyModule, PyResult, PyTuple, Python, 14 exc, PyBytes, PyDict, PyErr, PyInt, PyModule, PyResult, PyTuple, Python,
15 PythonObject, ToPyObject, 15 PythonObject, ToPyObject,
16 }; 16 };
17 use hg::{ 17 use hg::{
18 pack_dirstate, parse_dirstate, utils::hg_path::HgPathBuf, DirstateEntry, 18 pack_dirstate, parse_dirstate, utils::hg_path::HgPathBuf,
19 DirstatePackError, DirstateParents, DirstateParseError, PARENT_SIZE, 19 DirstatePackError, DirstateParents, DirstateParseError, PARENT_SIZE,
20 }; 20 };
21 use std::collections::HashMap; 21 use std::collections::HashMap;
22 use std::convert::TryInto; 22 use std::convert::TryInto;
23 23
24 use libc::c_char; 24 use crate::dirstate::{extract_dirstate, make_dirstate_tuple};
25
26 use crate::dirstate::{decapsule_make_dirstate_tuple, extract_dirstate};
27 use std::time::Duration; 25 use std::time::Duration;
28 26
29 fn parse_dirstate_wrapper( 27 fn parse_dirstate_wrapper(
30 py: Python, 28 py: Python,
31 dmap: PyDict, 29 dmap: PyDict,
35 let mut dirstate_map = HashMap::new(); 33 let mut dirstate_map = HashMap::new();
36 let mut copies = HashMap::new(); 34 let mut copies = HashMap::new();
37 35
38 match parse_dirstate(&mut dirstate_map, &mut copies, st.data(py)) { 36 match parse_dirstate(&mut dirstate_map, &mut copies, st.data(py)) {
39 Ok(parents) => { 37 Ok(parents) => {
40 for (filename, entry) in dirstate_map { 38 for (filename, entry) in &dirstate_map {
41 // Explicitly go through u8 first, then cast to
42 // platform-specific `c_char` because Into<u8> has a specific
43 // implementation while `as c_char` would just do a naive enum
44 // cast.
45 let state: u8 = entry.state.into();
46
47 dmap.set_item( 39 dmap.set_item(
48 py, 40 py,
49 PyBytes::new(py, filename.as_ref()), 41 PyBytes::new(py, filename.as_ref()),
50 decapsule_make_dirstate_tuple(py)?( 42 make_dirstate_tuple(py, entry)?,
51 state as c_char,
52 entry.mode,
53 entry.size,
54 entry.mtime,
55 ),
56 )?; 43 )?;
57 } 44 }
58 for (path, copy_path) in copies { 45 for (path, copy_path) in copies {
59 copymap.set_item( 46 copymap.set_item(
60 py, 47 py,
125 p2: p2.try_into().unwrap(), 112 p2: p2.try_into().unwrap(),
126 }, 113 },
127 Duration::from_secs(now.as_object().extract::<u64>(py)?), 114 Duration::from_secs(now.as_object().extract::<u64>(py)?),
128 ) { 115 ) {
129 Ok(packed) => { 116 Ok(packed) => {
130 for ( 117 for (filename, entry) in &dirstate_map {
131 filename,
132 DirstateEntry {
133 state,
134 mode,
135 size,
136 mtime,
137 },
138 ) in dirstate_map
139 {
140 // Explicitly go through u8 first, then cast to
141 // platform-specific `c_char` because Into<u8> has a specific
142 // implementation while `as c_char` would just do a naive enum
143 // cast.
144 let state: u8 = state.into();
145 dmap.set_item( 118 dmap.set_item(
146 py, 119 py,
147 PyBytes::new(py, filename.as_ref()), 120 PyBytes::new(py, filename.as_ref()),
148 decapsule_make_dirstate_tuple(py)?( 121 make_dirstate_tuple(py, entry)?,
149 state as c_char,
150 mode,
151 size,
152 mtime,
153 ),
154 )?; 122 )?;
155 } 123 }
156 Ok(PyBytes::new(py, &packed)) 124 Ok(PyBytes::new(py, &packed))
157 } 125 }
158 Err(error) => Err(PyErr::new::<exc::ValueError, _>( 126 Err(error) => Err(PyErr::new::<exc::ValueError, _>(