Show More
@@ -9,7 +9,7 b' pub mod node;' | |||||
9 | pub mod nodemap; |
|
9 | pub mod nodemap; | |
10 | mod nodemap_docket; |
|
10 | mod nodemap_docket; | |
11 | pub mod path_encode; |
|
11 | pub mod path_encode; | |
12 |
pub use node::{ |
|
12 | pub use node::{FromHexError, Node, NodePrefix, NodePrefixRef}; | |
13 | pub mod changelog; |
|
13 | pub mod changelog; | |
14 | pub mod index; |
|
14 | pub mod index; | |
15 | pub mod manifest; |
|
15 | pub mod manifest; |
@@ -9,7 +9,7 b'' | |||||
9 | //! of a revision. |
|
9 | //! of a revision. | |
10 |
|
10 | |||
11 | use bytes_cast::BytesCast; |
|
11 | use bytes_cast::BytesCast; | |
12 |
use hex::{self, FromHex |
|
12 | use hex::{self, FromHex}; | |
13 | use std::convert::TryFrom; |
|
13 | use std::convert::TryFrom; | |
14 | use std::fmt; |
|
14 | use std::fmt; | |
15 |
|
15 | |||
@@ -47,10 +47,9 b' type NodeData = [u8; NODE_BYTES_LENGTH];' | |||||
47 | /// if they need a loop boundary. |
|
47 | /// if they need a loop boundary. | |
48 | /// |
|
48 | /// | |
49 | /// All methods that create a `Node` either take a type that enforces |
|
49 | /// All methods that create a `Node` either take a type that enforces | |
50 | /// the size or fail immediately at runtime with [`ExactLengthRequired`]. |
|
50 | /// the size or return an error at runtime. | |
51 | /// |
|
51 | /// | |
52 | /// [`nybbles_len`]: #method.nybbles_len |
|
52 | /// [`nybbles_len`]: #method.nybbles_len | |
53 | /// [`ExactLengthRequired`]: struct.NodeError#variant.ExactLengthRequired |
|
|||
54 | #[derive(Clone, Debug, PartialEq, BytesCast)] |
|
53 | #[derive(Clone, Debug, PartialEq, BytesCast)] | |
55 | #[repr(transparent)] |
|
54 | #[repr(transparent)] | |
56 | pub struct Node { |
|
55 | pub struct Node { | |
@@ -90,12 +89,8 b' impl fmt::LowerHex for Node {' | |||||
90 | } |
|
89 | } | |
91 | } |
|
90 | } | |
92 |
|
91 | |||
93 |
#[derive(Debug |
|
92 | #[derive(Debug)] | |
94 | pub enum NodeError { |
|
93 | pub struct FromHexError; | |
95 | ExactLengthRequired(usize, String), |
|
|||
96 | PrefixTooLong(String), |
|
|||
97 | HexError(FromHexError, String), |
|
|||
98 | } |
|
|||
99 |
|
94 | |||
100 | /// Low level utility function, also for prefixes |
|
95 | /// Low level utility function, also for prefixes | |
101 | fn get_nybble(s: &[u8], i: usize) -> u8 { |
|
96 | fn get_nybble(s: &[u8], i: usize) -> u8 { | |
@@ -128,9 +123,9 b' impl Node {' | |||||
128 | /// |
|
123 | /// | |
129 | /// To be used in FFI and I/O only, in order to facilitate future |
|
124 | /// To be used in FFI and I/O only, in order to facilitate future | |
130 | /// changes of hash format. |
|
125 | /// changes of hash format. | |
131 |
pub fn from_hex(hex: impl AsRef<[u8]>) -> Result<Node, |
|
126 | pub fn from_hex(hex: impl AsRef<[u8]>) -> Result<Node, FromHexError> { | |
132 | Ok(NodeData::from_hex(hex.as_ref()) |
|
127 | Ok(NodeData::from_hex(hex.as_ref()) | |
133 |
.map_err(| |
|
128 | .map_err(|_| FromHexError)? | |
134 | .into()) |
|
129 | .into()) | |
135 | } |
|
130 | } | |
136 |
|
131 | |||
@@ -143,19 +138,6 b' impl Node {' | |||||
143 | } |
|
138 | } | |
144 | } |
|
139 | } | |
145 |
|
140 | |||
146 | impl<T: AsRef<[u8]>> From<(FromHexError, T)> for NodeError { |
|
|||
147 | fn from(err_offender: (FromHexError, T)) -> Self { |
|
|||
148 | let (err, offender) = err_offender; |
|
|||
149 | let offender = String::from_utf8_lossy(offender.as_ref()).into_owned(); |
|
|||
150 | match err { |
|
|||
151 | FromHexError::InvalidStringLength => { |
|
|||
152 | NodeError::ExactLengthRequired(NODE_NYBBLES_LENGTH, offender) |
|
|||
153 | } |
|
|||
154 | _ => NodeError::HexError(err, offender), |
|
|||
155 | } |
|
|||
156 | } |
|
|||
157 | } |
|
|||
158 |
|
||||
159 | /// The beginning of a binary revision SHA. |
|
141 | /// The beginning of a binary revision SHA. | |
160 | /// |
|
142 | /// | |
161 | /// Since it can potentially come from an hexadecimal representation with |
|
143 | /// Since it can potentially come from an hexadecimal representation with | |
@@ -175,31 +157,22 b' impl NodePrefix {' | |||||
175 | /// |
|
157 | /// | |
176 | /// To be used in FFI and I/O only, in order to facilitate future |
|
158 | /// To be used in FFI and I/O only, in order to facilitate future | |
177 | /// changes of hash format. |
|
159 | /// changes of hash format. | |
178 |
pub fn from_hex(hex: impl AsRef<[u8]>) -> Result<Self, |
|
160 | pub fn from_hex(hex: impl AsRef<[u8]>) -> Result<Self, FromHexError> { | |
179 | let hex = hex.as_ref(); |
|
161 | let hex = hex.as_ref(); | |
180 | let len = hex.len(); |
|
162 | let len = hex.len(); | |
181 | if len > NODE_NYBBLES_LENGTH { |
|
163 | if len > NODE_NYBBLES_LENGTH { | |
182 |
return Err( |
|
164 | return Err(FromHexError); | |
183 | String::from_utf8_lossy(hex).to_owned().to_string(), |
|
|||
184 | )); |
|
|||
185 | } |
|
165 | } | |
186 |
|
166 | |||
187 | let is_odd = len % 2 == 1; |
|
167 | let is_odd = len % 2 == 1; | |
188 | let even_part = if is_odd { &hex[..len - 1] } else { hex }; |
|
168 | let even_part = if is_odd { &hex[..len - 1] } else { hex }; | |
189 | let mut buf: Vec<u8> = |
|
169 | let mut buf: Vec<u8> = | |
190 |
Vec::from_hex(&even_part).map_err(| |
|
170 | Vec::from_hex(&even_part).map_err(|_| FromHexError)?; | |
191 |
|
171 | |||
192 | if is_odd { |
|
172 | if is_odd { | |
193 | let latest_char = char::from(hex[len - 1]); |
|
173 | let latest_char = char::from(hex[len - 1]); | |
194 |
let latest_nybble = |
|
174 | let latest_nybble = | |
195 | ( |
|
175 | latest_char.to_digit(16).ok_or_else(|| FromHexError)? as u8; | |
196 | FromHexError::InvalidHexCharacter { |
|
|||
197 | c: latest_char, |
|
|||
198 | index: len - 1, |
|
|||
199 | }, |
|
|||
200 | hex, |
|
|||
201 | ) |
|
|||
202 | })? as u8; |
|
|||
203 | buf.push(latest_nybble << 4); |
|
176 | buf.push(latest_nybble << 4); | |
204 | } |
|
177 | } | |
205 | Ok(NodePrefix { buf, is_odd }) |
|
178 | Ok(NodePrefix { buf, is_odd }) | |
@@ -329,24 +302,15 b' mod tests {' | |||||
329 |
|
302 | |||
330 | #[test] |
|
303 | #[test] | |
331 | fn test_node_from_hex() { |
|
304 | fn test_node_from_hex() { | |
332 |
assert_eq!(Node::from_hex(&sample_node_hex()), |
|
305 | assert_eq!(Node::from_hex(&sample_node_hex()).unwrap(), sample_node()); | |
333 |
|
306 | |||
334 | let mut short = hex_pad_right("0123"); |
|
307 | let mut short = hex_pad_right("0123"); | |
335 | short.pop(); |
|
308 | short.pop(); | |
336 | short.pop(); |
|
309 | short.pop(); | |
337 | assert_eq!( |
|
310 | assert!(Node::from_hex(&short).is_err()); | |
338 | Node::from_hex(&short), |
|
|||
339 | Err(NodeError::ExactLengthRequired(NODE_NYBBLES_LENGTH, short)), |
|
|||
340 | ); |
|
|||
341 |
|
311 | |||
342 | let not_hex = hex_pad_right("012... oops"); |
|
312 | let not_hex = hex_pad_right("012... oops"); | |
343 | assert_eq!( |
|
313 | assert!(Node::from_hex(¬_hex).is_err(),); | |
344 | Node::from_hex(¬_hex), |
|
|||
345 | Err(NodeError::HexError( |
|
|||
346 | FromHexError::InvalidHexCharacter { c: '.', index: 3 }, |
|
|||
347 | not_hex, |
|
|||
348 | )), |
|
|||
349 | ); |
|
|||
350 | } |
|
314 | } | |
351 |
|
315 | |||
352 | #[test] |
|
316 | #[test] | |
@@ -355,7 +319,7 b' mod tests {' | |||||
355 | } |
|
319 | } | |
356 |
|
320 | |||
357 | #[test] |
|
321 | #[test] | |
358 |
fn test_prefix_from_hex() -> Result<(), |
|
322 | fn test_prefix_from_hex() -> Result<(), FromHexError> { | |
359 | assert_eq!( |
|
323 | assert_eq!( | |
360 | NodePrefix::from_hex("0e1")?, |
|
324 | NodePrefix::from_hex("0e1")?, | |
361 | NodePrefix { |
|
325 | NodePrefix { | |
@@ -386,25 +350,14 b' mod tests {' | |||||
386 |
|
350 | |||
387 | #[test] |
|
351 | #[test] | |
388 | fn test_prefix_from_hex_errors() { |
|
352 | fn test_prefix_from_hex_errors() { | |
389 | assert_eq!( |
|
353 | assert!(NodePrefix::from_hex("testgr").is_err()); | |
390 | NodePrefix::from_hex("testgr"), |
|
|||
391 | Err(NodeError::HexError( |
|
|||
392 | FromHexError::InvalidHexCharacter { c: 't', index: 0 }, |
|
|||
393 | "testgr".to_string() |
|
|||
394 | )) |
|
|||
395 | ); |
|
|||
396 | let mut long = format!("{:x}", NULL_NODE); |
|
354 | let mut long = format!("{:x}", NULL_NODE); | |
397 | long.push('c'); |
|
355 | long.push('c'); | |
398 |
|
|
356 | assert!(NodePrefix::from_hex(&long).is_err()) | |
399 | .expect_err("should be refused as too long") |
|
|||
400 | { |
|
|||
401 | NodeError::PrefixTooLong(s) => assert_eq!(s, long), |
|
|||
402 | err => panic!(format!("Should have been TooLong, got {:?}", err)), |
|
|||
403 | } |
|
|||
404 | } |
|
357 | } | |
405 |
|
358 | |||
406 | #[test] |
|
359 | #[test] | |
407 |
fn test_is_prefix_of() -> Result<(), |
|
360 | fn test_is_prefix_of() -> Result<(), FromHexError> { | |
408 | let mut node_data = [0; NODE_BYTES_LENGTH]; |
|
361 | let mut node_data = [0; NODE_BYTES_LENGTH]; | |
409 | node_data[0] = 0x12; |
|
362 | node_data[0] = 0x12; | |
410 | node_data[1] = 0xca; |
|
363 | node_data[1] = 0xca; | |
@@ -417,7 +370,7 b' mod tests {' | |||||
417 | } |
|
370 | } | |
418 |
|
371 | |||
419 | #[test] |
|
372 | #[test] | |
420 |
fn test_get_nybble() -> Result<(), |
|
373 | fn test_get_nybble() -> Result<(), FromHexError> { | |
421 | let prefix = NodePrefix::from_hex("dead6789cafe")?; |
|
374 | let prefix = NodePrefix::from_hex("dead6789cafe")?; | |
422 | assert_eq!(prefix.borrow().get_nybble(0), 13); |
|
375 | assert_eq!(prefix.borrow().get_nybble(0), 13); | |
423 | assert_eq!(prefix.borrow().get_nybble(7), 9); |
|
376 | assert_eq!(prefix.borrow().get_nybble(7), 9); |
@@ -13,7 +13,7 b'' | |||||
13 | //! is used in a more abstract context. |
|
13 | //! is used in a more abstract context. | |
14 |
|
14 | |||
15 | use super::{ |
|
15 | use super::{ | |
16 |
node::NULL_NODE, |
|
16 | node::NULL_NODE, FromHexError, Node, NodePrefix, NodePrefixRef, Revision, | |
17 | RevlogIndex, NULL_REVISION, |
|
17 | RevlogIndex, NULL_REVISION, | |
18 | }; |
|
18 | }; | |
19 |
|
19 | |||
@@ -27,14 +27,14 b' use std::ops::Index;' | |||||
27 | #[derive(Debug, PartialEq)] |
|
27 | #[derive(Debug, PartialEq)] | |
28 | pub enum NodeMapError { |
|
28 | pub enum NodeMapError { | |
29 | MultipleResults, |
|
29 | MultipleResults, | |
30 |
InvalidNodePrefix |
|
30 | InvalidNodePrefix, | |
31 | /// A `Revision` stored in the nodemap could not be found in the index |
|
31 | /// A `Revision` stored in the nodemap could not be found in the index | |
32 | RevisionNotInIndex(Revision), |
|
32 | RevisionNotInIndex(Revision), | |
33 | } |
|
33 | } | |
34 |
|
34 | |||
35 |
impl From< |
|
35 | impl From<FromHexError> for NodeMapError { | |
36 |
fn from( |
|
36 | fn from(_: FromHexError) -> Self { | |
37 |
NodeMapError::InvalidNodePrefix |
|
37 | NodeMapError::InvalidNodePrefix | |
38 | } |
|
38 | } | |
39 | } |
|
39 | } | |
40 |
|
40 |
@@ -18,7 +18,7 b' use cpython::{' | |||||
18 | use hg::{ |
|
18 | use hg::{ | |
19 | nodemap::{Block, NodeMapError, NodeTree}, |
|
19 | nodemap::{Block, NodeMapError, NodeTree}, | |
20 | revlog::{nodemap::NodeMap, RevlogIndex}, |
|
20 | revlog::{nodemap::NodeMap, RevlogIndex}, | |
21 |
|
|
21 | Revision, | |
22 | }; |
|
22 | }; | |
23 | use std::cell::RefCell; |
|
23 | use std::cell::RefCell; | |
24 |
|
24 | |||
@@ -468,17 +468,12 b' fn nodemap_error(py: Python, err: NodeMa' | |||||
468 | match err { |
|
468 | match err { | |
469 | NodeMapError::MultipleResults => revlog_error(py), |
|
469 | NodeMapError::MultipleResults => revlog_error(py), | |
470 | NodeMapError::RevisionNotInIndex(r) => rev_not_in_index(py, r), |
|
470 | NodeMapError::RevisionNotInIndex(r) => rev_not_in_index(py, r), | |
471 |
NodeMapError::InvalidNodePrefix |
|
471 | NodeMapError::InvalidNodePrefix => { | |
|
472 | PyErr::new::<ValueError, _>(py, "Invalid node or prefix") | |||
|
473 | } | |||
472 | } |
|
474 | } | |
473 | } |
|
475 | } | |
474 |
|
476 | |||
475 | fn invalid_node_prefix(py: Python, ne: &NodeError) -> PyErr { |
|
|||
476 | PyErr::new::<ValueError, _>( |
|
|||
477 | py, |
|
|||
478 | format!("Invalid node or prefix: {:?}", ne), |
|
|||
479 | ) |
|
|||
480 | } |
|
|||
481 |
|
||||
482 | /// Create the module, with __package__ given from parent |
|
477 | /// Create the module, with __package__ given from parent | |
483 | pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> { |
|
478 | pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> { | |
484 | let dotted_name = &format!("{}.revlog", package); |
|
479 | let dotted_name = &format!("{}.revlog", package); |
General Comments 0
You need to be logged in to leave comments.
Login now