Details
Details
Diff Detail
Diff Detail
- Repository
- rHG Mercurial
- Lint
Automatic diff as part of commit; lint not applicable. - Unit
Automatic diff as part of commit; unit tests not applicable.
Automatic diff as part of commit; lint not applicable. |
Automatic diff as part of commit; unit tests not applicable. |
Path | Packages | |||
---|---|---|---|---|
M | rust/hg-core/src/revlog/node.rs (15 lines) |
Status | Author | Revision | |
---|---|---|---|
Closed | SimonSapin | ||
Closed | SimonSapin |
// Copyright 2019-2020 Georges Racinet <georges.racinet@octobus.net> | // Copyright 2019-2020 Georges Racinet <georges.racinet@octobus.net> | ||||
// | // | ||||
// This software may be used and distributed according to the terms of the | // This software may be used and distributed according to the terms of the | ||||
// GNU General Public License version 2 or any later version. | // GNU General Public License version 2 or any later version. | ||||
//! Definitions and utilities for Revision nodes | //! Definitions and utilities for Revision nodes | ||||
//! | //! | ||||
//! In Mercurial code base, it is customary to call "a node" the binary SHA | //! In Mercurial code base, it is customary to call "a node" the binary SHA | ||||
//! of a revision. | //! of a revision. | ||||
use bytes_cast::BytesCast; | |||||
use hex::{self, FromHex, FromHexError}; | use hex::{self, FromHex, FromHexError}; | ||||
use std::convert::{TryFrom, TryInto}; | use std::convert::TryFrom; | ||||
/// The length in bytes of a `Node` | /// The length in bytes of a `Node` | ||||
/// | /// | ||||
/// This constant is meant to ease refactors of this module, and | /// This constant is meant to ease refactors of this module, and | ||||
/// are private so that calling code does not expect all nodes have | /// are private so that calling code does not expect all nodes have | ||||
/// the same size, should we support several formats concurrently in | /// the same size, should we support several formats concurrently in | ||||
/// the future. | /// the future. | ||||
pub const NODE_BYTES_LENGTH: usize = 20; | pub const NODE_BYTES_LENGTH: usize = 20; | ||||
/// and never make any assumption on the actual length, using [`nybbles_len`] | /// and never make any assumption on the actual length, using [`nybbles_len`] | ||||
/// if they need a loop boundary. | /// if they need a loop boundary. | ||||
/// | /// | ||||
/// All methods that create a `Node` either take a type that enforces | /// All methods that create a `Node` either take a type that enforces | ||||
/// the size or fail immediately at runtime with [`ExactLengthRequired`]. | /// the size or fail immediately at runtime with [`ExactLengthRequired`]. | ||||
/// | /// | ||||
/// [`nybbles_len`]: #method.nybbles_len | /// [`nybbles_len`]: #method.nybbles_len | ||||
/// [`ExactLengthRequired`]: struct.NodeError#variant.ExactLengthRequired | /// [`ExactLengthRequired`]: struct.NodeError#variant.ExactLengthRequired | ||||
#[derive(Clone, Debug, PartialEq)] | #[derive(Clone, Debug, PartialEq, BytesCast)] | ||||
#[repr(transparent)] | #[repr(transparent)] | ||||
pub struct Node { | pub struct Node { | ||||
data: NodeData, | data: NodeData, | ||||
} | } | ||||
/// The node value for NULL_REVISION | /// The node value for NULL_REVISION | ||||
pub const NULL_NODE: Node = Node { | pub const NULL_NODE: Node = Node { | ||||
data: [0; NODE_BYTES_LENGTH], | data: [0; NODE_BYTES_LENGTH], | ||||
}; | }; | ||||
impl From<NodeData> for Node { | impl From<NodeData> for Node { | ||||
fn from(data: NodeData) -> Node { | fn from(data: NodeData) -> Node { | ||||
Node { data } | Node { data } | ||||
} | } | ||||
} | } | ||||
/// Return an error if the slice has an unexpected length | /// Return an error if the slice has an unexpected length | ||||
impl<'a> TryFrom<&'a [u8]> for &'a Node { | impl<'a> TryFrom<&'a [u8]> for &'a Node { | ||||
type Error = std::array::TryFromSliceError; | type Error = (); | ||||
#[inline] | #[inline] | ||||
fn try_from(bytes: &'a [u8]) -> Result<&'a Node, Self::Error> { | fn try_from(bytes: &'a [u8]) -> Result<&'a Node, Self::Error> { | ||||
let data = bytes.try_into()?; | match Node::from_bytes(bytes) { | ||||
// Safety: `#[repr(transparent)]` makes it ok to "wrap" the target | Ok((node, rest)) if rest.is_empty() => Ok(node), | ||||
// of a reference to the type of the single field. | _ => Err(()), | ||||
Ok(unsafe { std::mem::transmute::<&NodeData, &Node>(data) }) | } | ||||
} | } | ||||
} | } | ||||
#[derive(Debug, PartialEq)] | #[derive(Debug, PartialEq)] | ||||
pub enum NodeError { | pub enum NodeError { | ||||
ExactLengthRequired(usize, String), | ExactLengthRequired(usize, String), | ||||
PrefixTooLong(String), | PrefixTooLong(String), | ||||
HexError(FromHexError, String), | HexError(FromHexError, String), |