Mercurial > hg
diff rust/hg-core/src/revlog/node.rs @ 46033:88e741bf2d93
rust: use NodePrefix::from_hex instead of hex::decode directly
This adds support for prefixes with an odd number of hex digits.
Differential Revision: https://phab.mercurial-scm.org/D9490
author | Simon Sapin <simon-commits@exyr.org> |
---|---|
date | Wed, 02 Dec 2020 15:00:49 +0100 |
parents | b0d6309ff50c |
children | cfb6c10c08c2 |
line wrap: on
line diff
--- a/rust/hg-core/src/revlog/node.rs Mon Nov 30 19:34:49 2020 +0100 +++ b/rust/hg-core/src/revlog/node.rs Wed Dec 02 15:00:49 2020 +0100 @@ -9,6 +9,7 @@ //! of a revision. use hex::{self, FromHex, FromHexError}; +use std::convert::{TryFrom, TryInto}; /// The length in bytes of a `Node` /// @@ -65,6 +66,19 @@ } } +/// Return an error if the slice has an unexpected length +impl<'a> TryFrom<&'a [u8]> for &'a Node { + type Error = std::array::TryFromSliceError; + + #[inline] + fn try_from(bytes: &'a [u8]) -> Result<&'a Node, Self::Error> { + let data = bytes.try_into()?; + // Safety: `#[repr(transparent)]` makes it ok to "wrap" the target + // of a reference to the type of the single field. + Ok(unsafe { std::mem::transmute::<&NodeData, &Node>(data) }) + } +} + #[derive(Debug, PartialEq)] pub enum NodeError { ExactLengthRequired(usize, String), @@ -103,8 +117,8 @@ /// /// To be used in FFI and I/O only, in order to facilitate future /// changes of hash format. - pub fn from_hex(hex: &str) -> Result<Node, NodeError> { - Ok(NodeData::from_hex(hex) + pub fn from_hex(hex: impl AsRef<[u8]>) -> Result<Node, NodeError> { + Ok(NodeData::from_hex(hex.as_ref()) .map_err(|e| NodeError::from((e, hex)))? .into()) } @@ -126,17 +140,15 @@ } } -impl<T: AsRef<str>> From<(FromHexError, T)> for NodeError { +impl<T: AsRef<[u8]>> From<(FromHexError, T)> for NodeError { fn from(err_offender: (FromHexError, T)) -> Self { let (err, offender) = err_offender; + let offender = String::from_utf8_lossy(offender.as_ref()).into_owned(); match err { FromHexError::InvalidStringLength => { - NodeError::ExactLengthRequired( - NODE_NYBBLES_LENGTH, - offender.as_ref().to_owned(), - ) + NodeError::ExactLengthRequired(NODE_NYBBLES_LENGTH, offender) } - _ => NodeError::HexError(err, offender.as_ref().to_owned()), + _ => NodeError::HexError(err, offender), } } } @@ -171,8 +183,8 @@ let is_odd = len % 2 == 1; let even_part = if is_odd { &hex[..len - 1] } else { hex }; - let mut buf: Vec<u8> = Vec::from_hex(&even_part) - .map_err(|e| (e, String::from_utf8_lossy(hex)))?; + let mut buf: Vec<u8> = + Vec::from_hex(&even_part).map_err(|e| (e, hex))?; if is_odd { let latest_char = char::from(hex[len - 1]); @@ -182,7 +194,7 @@ c: latest_char, index: len - 1, }, - String::from_utf8_lossy(hex), + hex, ) })? as u8; buf.push(latest_nybble << 4); @@ -278,6 +290,12 @@ } } +impl PartialEq<Node> for NodePrefixRef<'_> { + fn eq(&self, other: &Node) -> bool { + !self.is_odd && self.buf == other.data + } +} + #[cfg(test)] mod tests { use super::*; @@ -292,7 +310,7 @@ } /// Pad an hexadecimal string to reach `NODE_NYBBLES_LENGTH` - /// + ///check_hash /// The padding is made with zeros pub fn hex_pad_right(hex: &str) -> String { let mut res = hex.to_string();