Details
Details
Diff Detail
Diff Detail
- Repository
- rHG Mercurial
- Branch
- default
- Lint
No Linters Available - Unit
No Unit Test Coverage
| No Linters Available |
| No Unit Test Coverage |
| Path | Packages | |||
|---|---|---|---|---|
| M | rust/hg-core/src/revlog/node.rs (15 lines) |
| Commit | Parents | Author | Summary | Date |
|---|---|---|---|---|
| fe6246d199fc | 111e038ef451 | Simon Sapin | Jan 25 2021, 5:34 AM |
| 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), | ||||