rust/hg-core/src/revlog/node.rs
author Simon Sapin <simon-commits@exyr.org>
Wed, 02 Dec 2020 15:00:49 +0100
changeset 46037 88e741bf2d93
parent 45537 b0d6309ff50c
child 46463 cfb6c10c08c2
permissions -rw-r--r--
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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
     1
// Copyright 2019-2020 Georges Racinet <georges.racinet@octobus.net>
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
     2
//
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
     3
// This software may be used and distributed according to the terms of the
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
     4
// GNU General Public License version 2 or any later version.
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
     5
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
     6
//! Definitions and utilities for Revision nodes
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
     7
//!
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
     8
//! In Mercurial code base, it is customary to call "a node" the binary SHA
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
     9
//! of a revision.
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    10
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    11
use hex::{self, FromHex, FromHexError};
46037
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
    12
use std::convert::{TryFrom, TryInto};
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    13
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    14
/// The length in bytes of a `Node`
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    15
///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    16
/// This constant is meant to ease refactors of this module, and
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    17
/// are private so that calling code does not expect all nodes have
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    18
/// the same size, should we support several formats concurrently in
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    19
/// the future.
45537
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 44998
diff changeset
    20
pub const NODE_BYTES_LENGTH: usize = 20;
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 44998
diff changeset
    21
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 44998
diff changeset
    22
/// Id of the null node.
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 44998
diff changeset
    23
///
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 44998
diff changeset
    24
/// Used to indicate the absence of node.
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 44998
diff changeset
    25
pub const NULL_NODE_ID: [u8; NODE_BYTES_LENGTH] = [0u8; NODE_BYTES_LENGTH];
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    26
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    27
/// The length in bytes of a `Node`
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    28
///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    29
/// see also `NODES_BYTES_LENGTH` about it being private.
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    30
const NODE_NYBBLES_LENGTH: usize = 2 * NODE_BYTES_LENGTH;
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    31
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    32
/// Private alias for readability and to ease future change
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    33
type NodeData = [u8; NODE_BYTES_LENGTH];
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    34
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    35
/// Binary revision SHA
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    36
///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    37
/// ## Future changes of hash size
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    38
///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    39
/// To accomodate future changes of hash size, Rust callers
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    40
/// should use the conversion methods at the boundaries (FFI, actual
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    41
/// computation of hashes and I/O) only, and only if required.
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    42
///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    43
/// All other callers outside of unit tests should just handle `Node` values
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    44
/// and never make any assumption on the actual length, using [`nybbles_len`]
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    45
/// if they need a loop boundary.
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    46
///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    47
/// All methods that create a `Node` either take a type that enforces
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    48
/// the size or fail immediately at runtime with [`ExactLengthRequired`].
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    49
///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    50
/// [`nybbles_len`]: #method.nybbles_len
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    51
/// [`ExactLengthRequired`]: struct.NodeError#variant.ExactLengthRequired
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    52
#[derive(Clone, Debug, PartialEq)]
44512
166349510398 revlog: using two new functions in C capsule from Rust code
Georges Racinet <georges.racinet@octobus.net>
parents: 44419
diff changeset
    53
#[repr(transparent)]
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    54
pub struct Node {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    55
    data: NodeData,
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    56
}
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    57
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    58
/// The node value for NULL_REVISION
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    59
pub const NULL_NODE: Node = Node {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    60
    data: [0; NODE_BYTES_LENGTH],
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    61
};
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    62
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    63
impl From<NodeData> for Node {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    64
    fn from(data: NodeData) -> Node {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    65
        Node { data }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    66
    }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    67
}
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    68
46037
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
    69
/// Return an error if the slice has an unexpected length
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
    70
impl<'a> TryFrom<&'a [u8]> for &'a Node {
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
    71
    type Error = std::array::TryFromSliceError;
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
    72
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
    73
    #[inline]
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
    74
    fn try_from(bytes: &'a [u8]) -> Result<&'a Node, Self::Error> {
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
    75
        let data = bytes.try_into()?;
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
    76
        // Safety: `#[repr(transparent)]` makes it ok to "wrap" the target
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
    77
        // of a reference to the type of the single field.
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
    78
        Ok(unsafe { std::mem::transmute::<&NodeData, &Node>(data) })
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
    79
    }
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
    80
}
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
    81
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    82
#[derive(Debug, PartialEq)]
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    83
pub enum NodeError {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    84
    ExactLengthRequired(usize, String),
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
    85
    PrefixTooLong(String),
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    86
    HexError(FromHexError, String),
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    87
}
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    88
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    89
/// Low level utility function, also for prefixes
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    90
fn get_nybble(s: &[u8], i: usize) -> u8 {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    91
    if i % 2 == 0 {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    92
        s[i / 2] >> 4
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    93
    } else {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    94
        s[i / 2] & 0x0f
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    95
    }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    96
}
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    97
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    98
impl Node {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    99
    /// Retrieve the `i`th half-byte of the binary data.
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   100
    ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   101
    /// This is also the `i`th hexadecimal digit in numeric form,
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   102
    /// also called a [nybble](https://en.wikipedia.org/wiki/Nibble).
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   103
    pub fn get_nybble(&self, i: usize) -> u8 {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   104
        get_nybble(&self.data, i)
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   105
    }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   106
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   107
    /// Length of the data, in nybbles
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   108
    pub fn nybbles_len(&self) -> usize {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   109
        // public exposure as an instance method only, so that we can
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   110
        // easily support several sizes of hashes if needed in the future.
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   111
        NODE_NYBBLES_LENGTH
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   112
    }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   113
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   114
    /// Convert from hexadecimal string representation
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   115
    ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   116
    /// Exact length is required.
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   117
    ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   118
    /// To be used in FFI and I/O only, in order to facilitate future
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   119
    /// changes of hash format.
46037
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
   120
    pub fn from_hex(hex: impl AsRef<[u8]>) -> Result<Node, NodeError> {
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
   121
        Ok(NodeData::from_hex(hex.as_ref())
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   122
            .map_err(|e| NodeError::from((e, hex)))?
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   123
            .into())
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   124
    }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   125
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   126
    /// Convert to hexadecimal string representation
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   127
    ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   128
    /// To be used in FFI and I/O only, in order to facilitate future
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   129
    /// changes of hash format.
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   130
    pub fn encode_hex(&self) -> String {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   131
        hex::encode(self.data)
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   132
    }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   133
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   134
    /// Provide access to binary data
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   135
    ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   136
    /// This is needed by FFI layers, for instance to return expected
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   137
    /// binary values to Python.
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   138
    pub fn as_bytes(&self) -> &[u8] {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   139
        &self.data
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   140
    }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   141
}
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   142
46037
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
   143
impl<T: AsRef<[u8]>> From<(FromHexError, T)> for NodeError {
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   144
    fn from(err_offender: (FromHexError, T)) -> Self {
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   145
        let (err, offender) = err_offender;
46037
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
   146
        let offender = String::from_utf8_lossy(offender.as_ref()).into_owned();
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   147
        match err {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   148
            FromHexError::InvalidStringLength => {
46037
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
   149
                NodeError::ExactLengthRequired(NODE_NYBBLES_LENGTH, offender)
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   150
            }
46037
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
   151
            _ => NodeError::HexError(err, offender),
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   152
        }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   153
    }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   154
}
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   155
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   156
/// The beginning of a binary revision SHA.
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   157
///
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   158
/// Since it can potentially come from an hexadecimal representation with
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   159
/// odd length, it needs to carry around whether the last 4 bits are relevant
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   160
/// or not.
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   161
#[derive(Debug, PartialEq)]
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   162
pub struct NodePrefix {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   163
    buf: Vec<u8>,
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   164
    is_odd: bool,
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   165
}
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   166
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   167
impl NodePrefix {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   168
    /// Convert from hexadecimal string representation
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   169
    ///
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   170
    /// Similarly to `hex::decode`, can be used with Unicode string types
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   171
    /// (`String`, `&str`) as well as bytes.
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   172
    ///
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   173
    /// To be used in FFI and I/O only, in order to facilitate future
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   174
    /// changes of hash format.
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   175
    pub fn from_hex(hex: impl AsRef<[u8]>) -> Result<Self, NodeError> {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   176
        let hex = hex.as_ref();
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   177
        let len = hex.len();
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   178
        if len > NODE_NYBBLES_LENGTH {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   179
            return Err(NodeError::PrefixTooLong(
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   180
                String::from_utf8_lossy(hex).to_owned().to_string(),
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   181
            ));
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   182
        }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   183
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   184
        let is_odd = len % 2 == 1;
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   185
        let even_part = if is_odd { &hex[..len - 1] } else { hex };
46037
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
   186
        let mut buf: Vec<u8> =
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
   187
            Vec::from_hex(&even_part).map_err(|e| (e, hex))?;
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   188
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   189
        if is_odd {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   190
            let latest_char = char::from(hex[len - 1]);
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   191
            let latest_nybble = latest_char.to_digit(16).ok_or_else(|| {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   192
                (
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   193
                    FromHexError::InvalidHexCharacter {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   194
                        c: latest_char,
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   195
                        index: len - 1,
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   196
                    },
46037
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
   197
                    hex,
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   198
                )
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   199
            })? as u8;
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   200
            buf.push(latest_nybble << 4);
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   201
        }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   202
        Ok(NodePrefix { buf, is_odd })
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   203
    }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   204
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   205
    pub fn borrow(&self) -> NodePrefixRef {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   206
        NodePrefixRef {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   207
            buf: &self.buf,
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   208
            is_odd: self.is_odd,
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   209
        }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   210
    }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   211
}
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   212
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   213
#[derive(Clone, Debug, PartialEq)]
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   214
pub struct NodePrefixRef<'a> {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   215
    buf: &'a [u8],
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   216
    is_odd: bool,
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   217
}
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   218
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   219
impl<'a> NodePrefixRef<'a> {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   220
    pub fn len(&self) -> usize {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   221
        if self.is_odd {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   222
            self.buf.len() * 2 - 1
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   223
        } else {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   224
            self.buf.len() * 2
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   225
        }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   226
    }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   227
44998
26114bd6ec60 rust: do a clippy pass
Raphaël Gomès <rgomes@octobus.net>
parents: 44512
diff changeset
   228
    pub fn is_empty(&self) -> bool {
26114bd6ec60 rust: do a clippy pass
Raphaël Gomès <rgomes@octobus.net>
parents: 44512
diff changeset
   229
        self.len() == 0
26114bd6ec60 rust: do a clippy pass
Raphaël Gomès <rgomes@octobus.net>
parents: 44512
diff changeset
   230
    }
26114bd6ec60 rust: do a clippy pass
Raphaël Gomès <rgomes@octobus.net>
parents: 44512
diff changeset
   231
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   232
    pub fn is_prefix_of(&self, node: &Node) -> bool {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   233
        if self.is_odd {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   234
            let buf = self.buf;
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   235
            let last_pos = buf.len() - 1;
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   236
            node.data.starts_with(buf.split_at(last_pos).0)
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   237
                && node.data[last_pos] >> 4 == buf[last_pos] >> 4
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   238
        } else {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   239
            node.data.starts_with(self.buf)
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   240
        }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   241
    }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   242
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   243
    /// Retrieve the `i`th half-byte from the prefix.
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   244
    ///
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   245
    /// This is also the `i`th hexadecimal digit in numeric form,
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   246
    /// also called a [nybble](https://en.wikipedia.org/wiki/Nibble).
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   247
    pub fn get_nybble(&self, i: usize) -> u8 {
44262
be52b7372ec2 rust-node: avoid meaningless read at the end of odd prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44258
diff changeset
   248
        assert!(i < self.len());
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   249
        get_nybble(self.buf, i)
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   250
    }
44419
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   251
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   252
    /// Return the index first nybble that's different from `node`
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   253
    ///
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   254
    /// If the return value is `None` that means that `self` is
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   255
    /// a prefix of `node`, but the current method is a bit slower
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   256
    /// than `is_prefix_of`.
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   257
    ///
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   258
    /// Returned index is as in `get_nybble`, i.e., starting at 0.
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   259
    pub fn first_different_nybble(&self, node: &Node) -> Option<usize> {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   260
        let buf = self.buf;
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   261
        let until = if self.is_odd {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   262
            buf.len() - 1
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   263
        } else {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   264
            buf.len()
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   265
        };
44998
26114bd6ec60 rust: do a clippy pass
Raphaël Gomès <rgomes@octobus.net>
parents: 44512
diff changeset
   266
        for (i, item) in buf.iter().enumerate().take(until) {
26114bd6ec60 rust: do a clippy pass
Raphaël Gomès <rgomes@octobus.net>
parents: 44512
diff changeset
   267
            if *item != node.data[i] {
26114bd6ec60 rust: do a clippy pass
Raphaël Gomès <rgomes@octobus.net>
parents: 44512
diff changeset
   268
                return if *item & 0xf0 == node.data[i] & 0xf0 {
26114bd6ec60 rust: do a clippy pass
Raphaël Gomès <rgomes@octobus.net>
parents: 44512
diff changeset
   269
                    Some(2 * i + 1)
44419
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   270
                } else {
44998
26114bd6ec60 rust: do a clippy pass
Raphaël Gomès <rgomes@octobus.net>
parents: 44512
diff changeset
   271
                    Some(2 * i)
26114bd6ec60 rust: do a clippy pass
Raphaël Gomès <rgomes@octobus.net>
parents: 44512
diff changeset
   272
                };
44419
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   273
            }
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   274
        }
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   275
        if self.is_odd && buf[until] & 0xf0 != node.data[until] & 0xf0 {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   276
            Some(until * 2)
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   277
        } else {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   278
            None
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   279
        }
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   280
    }
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   281
}
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   282
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   283
/// A shortcut for full `Node` references
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   284
impl<'a> From<&'a Node> for NodePrefixRef<'a> {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   285
    fn from(node: &'a Node) -> Self {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   286
        NodePrefixRef {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   287
            buf: &node.data,
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   288
            is_odd: false,
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   289
        }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   290
    }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   291
}
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   292
46037
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
   293
impl PartialEq<Node> for NodePrefixRef<'_> {
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
   294
    fn eq(&self, other: &Node) -> bool {
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
   295
        !self.is_odd && self.buf == other.data
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
   296
    }
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
   297
}
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
   298
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   299
#[cfg(test)]
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   300
mod tests {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   301
    use super::*;
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   302
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   303
    fn sample_node() -> Node {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   304
        let mut data = [0; NODE_BYTES_LENGTH];
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   305
        data.copy_from_slice(&[
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   306
            0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba,
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   307
            0x98, 0x76, 0x54, 0x32, 0x10, 0xde, 0xad, 0xbe, 0xef,
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   308
        ]);
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   309
        data.into()
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   310
    }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   311
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   312
    /// Pad an hexadecimal string to reach `NODE_NYBBLES_LENGTH`
46037
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
   313
    ///check_hash
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   314
    /// The padding is made with zeros
44258
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44257
diff changeset
   315
    pub fn hex_pad_right(hex: &str) -> String {
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   316
        let mut res = hex.to_string();
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   317
        while res.len() < NODE_NYBBLES_LENGTH {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   318
            res.push('0');
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   319
        }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   320
        res
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   321
    }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   322
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   323
    fn sample_node_hex() -> String {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   324
        hex_pad_right("0123456789abcdeffedcba9876543210deadbeef")
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   325
    }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   326
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   327
    #[test]
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   328
    fn test_node_from_hex() {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   329
        assert_eq!(Node::from_hex(&sample_node_hex()), Ok(sample_node()));
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   330
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   331
        let mut short = hex_pad_right("0123");
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   332
        short.pop();
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   333
        short.pop();
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   334
        assert_eq!(
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   335
            Node::from_hex(&short),
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   336
            Err(NodeError::ExactLengthRequired(NODE_NYBBLES_LENGTH, short)),
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   337
        );
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   338
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   339
        let not_hex = hex_pad_right("012... oops");
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   340
        assert_eq!(
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   341
            Node::from_hex(&not_hex),
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   342
            Err(NodeError::HexError(
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   343
                FromHexError::InvalidHexCharacter { c: '.', index: 3 },
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   344
                not_hex,
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   345
            )),
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   346
        );
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   347
    }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   348
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   349
    #[test]
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   350
    fn test_node_encode_hex() {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   351
        assert_eq!(sample_node().encode_hex(), sample_node_hex());
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   352
    }
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   353
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   354
    #[test]
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   355
    fn test_prefix_from_hex() -> Result<(), NodeError> {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   356
        assert_eq!(
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   357
            NodePrefix::from_hex("0e1")?,
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   358
            NodePrefix {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   359
                buf: vec![14, 16],
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   360
                is_odd: true
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   361
            }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   362
        );
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   363
        assert_eq!(
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   364
            NodePrefix::from_hex("0e1a")?,
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   365
            NodePrefix {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   366
                buf: vec![14, 26],
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   367
                is_odd: false
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   368
            }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   369
        );
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   370
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   371
        // checking limit case
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   372
        let node_as_vec = sample_node().data.iter().cloned().collect();
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   373
        assert_eq!(
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   374
            NodePrefix::from_hex(sample_node_hex())?,
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   375
            NodePrefix {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   376
                buf: node_as_vec,
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   377
                is_odd: false
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   378
            }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   379
        );
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   380
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   381
        Ok(())
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   382
    }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   383
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   384
    #[test]
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   385
    fn test_prefix_from_hex_errors() {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   386
        assert_eq!(
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   387
            NodePrefix::from_hex("testgr"),
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   388
            Err(NodeError::HexError(
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   389
                FromHexError::InvalidHexCharacter { c: 't', index: 0 },
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   390
                "testgr".to_string()
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   391
            ))
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   392
        );
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   393
        let mut long = NULL_NODE.encode_hex();
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   394
        long.push('c');
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   395
        match NodePrefix::from_hex(&long)
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   396
            .expect_err("should be refused as too long")
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   397
        {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   398
            NodeError::PrefixTooLong(s) => assert_eq!(s, long),
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   399
            err => panic!(format!("Should have been TooLong, got {:?}", err)),
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   400
        }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   401
    }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   402
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   403
    #[test]
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   404
    fn test_is_prefix_of() -> Result<(), NodeError> {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   405
        let mut node_data = [0; NODE_BYTES_LENGTH];
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   406
        node_data[0] = 0x12;
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   407
        node_data[1] = 0xca;
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   408
        let node = Node::from(node_data);
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   409
        assert!(NodePrefix::from_hex("12")?.borrow().is_prefix_of(&node));
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   410
        assert!(!NodePrefix::from_hex("1a")?.borrow().is_prefix_of(&node));
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   411
        assert!(NodePrefix::from_hex("12c")?.borrow().is_prefix_of(&node));
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   412
        assert!(!NodePrefix::from_hex("12d")?.borrow().is_prefix_of(&node));
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   413
        Ok(())
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   414
    }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   415
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   416
    #[test]
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   417
    fn test_get_nybble() -> Result<(), NodeError> {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   418
        let prefix = NodePrefix::from_hex("dead6789cafe")?;
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   419
        assert_eq!(prefix.borrow().get_nybble(0), 13);
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   420
        assert_eq!(prefix.borrow().get_nybble(7), 9);
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   421
        Ok(())
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   422
    }
44419
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   423
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   424
    #[test]
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   425
    fn test_first_different_nybble_even_prefix() {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   426
        let prefix = NodePrefix::from_hex("12ca").unwrap();
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   427
        let prefref = prefix.borrow();
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   428
        let mut node = Node::from([0; NODE_BYTES_LENGTH]);
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   429
        assert_eq!(prefref.first_different_nybble(&node), Some(0));
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   430
        node.data[0] = 0x13;
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   431
        assert_eq!(prefref.first_different_nybble(&node), Some(1));
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   432
        node.data[0] = 0x12;
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   433
        assert_eq!(prefref.first_different_nybble(&node), Some(2));
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   434
        node.data[1] = 0xca;
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   435
        // now it is a prefix
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   436
        assert_eq!(prefref.first_different_nybble(&node), None);
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   437
    }
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   438
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   439
    #[test]
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   440
    fn test_first_different_nybble_odd_prefix() {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   441
        let prefix = NodePrefix::from_hex("12c").unwrap();
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   442
        let prefref = prefix.borrow();
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   443
        let mut node = Node::from([0; NODE_BYTES_LENGTH]);
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   444
        assert_eq!(prefref.first_different_nybble(&node), Some(0));
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   445
        node.data[0] = 0x13;
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   446
        assert_eq!(prefref.first_different_nybble(&node), Some(1));
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   447
        node.data[0] = 0x12;
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   448
        assert_eq!(prefref.first_different_nybble(&node), Some(2));
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   449
        node.data[1] = 0xca;
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   450
        // now it is a prefix
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   451
        assert_eq!(prefref.first_different_nybble(&node), None);
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   452
    }
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   453
}
44258
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44257
diff changeset
   454
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44257
diff changeset
   455
#[cfg(test)]
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44257
diff changeset
   456
pub use tests::hex_pad_right;