##// END OF EJS Templates
rust: Simplify error type for reading hex node IDs...
Simon Sapin -
r47156:5893706a default
parent child Browse files
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::{Node, NodeError, NodePrefix, NodePrefixRef};
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, FromHexError};
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, PartialEq)]
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, NodeError> {
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(|e| NodeError::from((e, hex)))?
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, NodeError> {
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(NodeError::PrefixTooLong(
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(|e| (e, hex))?;
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 = latest_char.to_digit(16).ok_or_else(|| {
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()), Ok(sample_node()));
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(&not_hex).is_err(),);
344 Node::from_hex(&not_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<(), NodeError> {
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 match NodePrefix::from_hex(&long)
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<(), NodeError> {
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<(), NodeError> {
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, Node, NodeError, NodePrefix, NodePrefixRef, Revision,
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(NodeError),
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<NodeError> for NodeMapError {
35 impl From<FromHexError> for NodeMapError {
36 fn from(err: NodeError) -> Self {
36 fn from(_: FromHexError) -> Self {
37 NodeMapError::InvalidNodePrefix(err)
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 NodeError, Revision,
21 Revision,
22 };
22 };
23 use std::cell::RefCell;
23 use std::cell::RefCell;
24
24
@@ -468,15 +468,10 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(s) => invalid_node_prefix(py, &s),
471 NodeMapError::InvalidNodePrefix => {
472 PyErr::new::<ValueError, _>(py, "Invalid node or prefix")
472 }
473 }
473 }
474 }
474
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 }
475 }
481
476
482 /// Create the module, with __package__ given from parent
477 /// Create the module, with __package__ given from parent
General Comments 0
You need to be logged in to leave comments. Login now