##// END OF EJS Templates
rust-parsers: fix unboxing of PyInt on Python 3...
Yuya Nishihara -
r43061:98901eb1 default
parent child Browse files
Show More
@@ -1,207 +1,207
1 1 // parsers.rs
2 2 //
3 3 // Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
4 4 //
5 5 // This software may be used and distributed according to the terms of the
6 6 // GNU General Public License version 2 or any later version.
7 7
8 8 //! Bindings for the `hg::dirstate::parsers` module provided by the
9 9 //! `hg-core` package.
10 10 //!
11 11 //! From Python, this will be seen as `mercurial.rustext.parsers`
12 12 //!
13 13 use cpython::{
14 14 exc, PyBytes, PyDict, PyErr, PyInt, PyModule, PyResult, PyTuple, Python,
15 ToPyObject,
15 PythonObject, ToPyObject,
16 16 };
17 17 use hg::{
18 18 pack_dirstate, parse_dirstate, utils::copy_into_array, DirstateEntry,
19 19 DirstatePackError, DirstateParents, DirstateParseError, PARENT_SIZE,
20 20 };
21 21 use std::collections::HashMap;
22 22
23 23 use libc::c_char;
24 24
25 25 use crate::dirstate::{decapsule_make_dirstate_tuple, extract_dirstate};
26 26 use std::time::Duration;
27 27
28 28 fn parse_dirstate_wrapper(
29 29 py: Python,
30 30 dmap: PyDict,
31 31 copymap: PyDict,
32 32 st: PyBytes,
33 33 ) -> PyResult<PyTuple> {
34 34 let mut dirstate_map = HashMap::new();
35 35 let mut copies = HashMap::new();
36 36
37 37 match parse_dirstate(&mut dirstate_map, &mut copies, st.data(py)) {
38 38 Ok(parents) => {
39 39 for (filename, entry) in dirstate_map {
40 40 // Explicitly go through u8 first, then cast to
41 41 // platform-specific `c_char` because Into<u8> has a specific
42 42 // implementation while `as c_char` would just do a naive enum
43 43 // cast.
44 44 let state: u8 = entry.state.into();
45 45
46 46 dmap.set_item(
47 47 py,
48 48 PyBytes::new(py, &filename),
49 49 decapsule_make_dirstate_tuple(py)?(
50 50 state as c_char,
51 51 entry.mode,
52 52 entry.size,
53 53 entry.mtime,
54 54 ),
55 55 )?;
56 56 }
57 57 for (path, copy_path) in copies {
58 58 copymap.set_item(
59 59 py,
60 60 PyBytes::new(py, &path),
61 61 PyBytes::new(py, &copy_path),
62 62 )?;
63 63 }
64 64 Ok(
65 65 (PyBytes::new(py, &parents.p1), PyBytes::new(py, &parents.p2))
66 66 .to_py_object(py),
67 67 )
68 68 }
69 69 Err(e) => Err(PyErr::new::<exc::ValueError, _>(
70 70 py,
71 71 match e {
72 72 DirstateParseError::TooLittleData => {
73 73 "too little data for parents".to_string()
74 74 }
75 75 DirstateParseError::Overflow => {
76 76 "overflow in dirstate".to_string()
77 77 }
78 78 DirstateParseError::CorruptedEntry(e) => e,
79 79 DirstateParseError::Damaged => {
80 80 "dirstate appears to be damaged".to_string()
81 81 }
82 82 },
83 83 )),
84 84 }
85 85 }
86 86
87 87 fn pack_dirstate_wrapper(
88 88 py: Python,
89 89 dmap: PyDict,
90 90 copymap: PyDict,
91 91 pl: PyTuple,
92 92 now: PyInt,
93 93 ) -> PyResult<PyBytes> {
94 94 let p1 = pl.get_item(py, 0).extract::<PyBytes>(py)?;
95 95 let p1: &[u8] = p1.data(py);
96 96 let p2 = pl.get_item(py, 1).extract::<PyBytes>(py)?;
97 97 let p2: &[u8] = p2.data(py);
98 98
99 99 let mut dirstate_map = extract_dirstate(py, &dmap)?;
100 100
101 101 let copies: Result<HashMap<Vec<u8>, Vec<u8>>, PyErr> = copymap
102 102 .items(py)
103 103 .iter()
104 104 .map(|(key, value)| {
105 105 Ok((
106 106 key.extract::<PyBytes>(py)?.data(py).to_owned(),
107 107 value.extract::<PyBytes>(py)?.data(py).to_owned(),
108 108 ))
109 109 })
110 110 .collect();
111 111
112 112 if p1.len() != PARENT_SIZE || p2.len() != PARENT_SIZE {
113 113 return Err(PyErr::new::<exc::ValueError, _>(
114 114 py,
115 115 "expected a 20-byte hash".to_string(),
116 116 ));
117 117 }
118 118
119 119 match pack_dirstate(
120 120 &mut dirstate_map,
121 121 &copies?,
122 122 DirstateParents {
123 123 p1: copy_into_array(&p1),
124 124 p2: copy_into_array(&p2),
125 125 },
126 Duration::from_secs(now.value(py) as u64),
126 Duration::from_secs(now.as_object().extract::<u64>(py)?),
127 127 ) {
128 128 Ok(packed) => {
129 129 for (
130 130 filename,
131 131 DirstateEntry {
132 132 state,
133 133 mode,
134 134 size,
135 135 mtime,
136 136 },
137 137 ) in dirstate_map
138 138 {
139 139 // Explicitly go through u8 first, then cast to
140 140 // platform-specific `c_char` because Into<u8> has a specific
141 141 // implementation while `as c_char` would just do a naive enum
142 142 // cast.
143 143 let state: u8 = state.into();
144 144 dmap.set_item(
145 145 py,
146 146 PyBytes::new(py, &filename[..]),
147 147 decapsule_make_dirstate_tuple(py)?(
148 148 state as c_char,
149 149 mode,
150 150 size,
151 151 mtime,
152 152 ),
153 153 )?;
154 154 }
155 155 Ok(PyBytes::new(py, &packed))
156 156 }
157 157 Err(error) => Err(PyErr::new::<exc::ValueError, _>(
158 158 py,
159 159 match error {
160 160 DirstatePackError::CorruptedParent => {
161 161 "expected a 20-byte hash".to_string()
162 162 }
163 163 DirstatePackError::CorruptedEntry(e) => e,
164 164 DirstatePackError::BadSize(expected, actual) => {
165 165 format!("bad dirstate size: {} != {}", actual, expected)
166 166 }
167 167 },
168 168 )),
169 169 }
170 170 }
171 171
172 172 /// Create the module, with `__package__` given from parent
173 173 pub fn init_parsers_module(py: Python, package: &str) -> PyResult<PyModule> {
174 174 let dotted_name = &format!("{}.parsers", package);
175 175 let m = PyModule::new(py, dotted_name)?;
176 176
177 177 m.add(py, "__package__", package)?;
178 178 m.add(py, "__doc__", "Parsers - Rust implementation")?;
179 179
180 180 m.add(
181 181 py,
182 182 "parse_dirstate",
183 183 py_fn!(
184 184 py,
185 185 parse_dirstate_wrapper(dmap: PyDict, copymap: PyDict, st: PyBytes)
186 186 ),
187 187 )?;
188 188 m.add(
189 189 py,
190 190 "pack_dirstate",
191 191 py_fn!(
192 192 py,
193 193 pack_dirstate_wrapper(
194 194 dmap: PyDict,
195 195 copymap: PyDict,
196 196 pl: PyTuple,
197 197 now: PyInt
198 198 )
199 199 ),
200 200 )?;
201 201
202 202 let sys = PyModule::import(py, "sys")?;
203 203 let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?;
204 204 sys_modules.set_item(py, dotted_name, &m)?;
205 205
206 206 Ok(m)
207 207 }
General Comments 0
You need to be logged in to leave comments. Login now