rust/hg-core/src/revlog/node.rs
author Raphaël Gomès <rgomes@octobus.net>
Mon, 06 Nov 2023 11:06:08 +0100
changeset 51118 532e74ad3ff6
parent 50000 2202832b35e8
child 51210 b4d152a28742
permissions -rw-r--r--
rust: run a clippy pass with the latest stable version Our current version of clippy is older than the latest stable. The newest version has new lints that are moslty good advice, so let's apply them ahead of time. This has the added benefit of reducing the noise for developpers like myself that use clippy as an IDE helper, as well as being more prepared for a future clippy upgrade.
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
46511
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46503
diff changeset
    11
use crate::errors::HgError;
46463
cfb6c10c08c2 rust: replace an unsafe use of transmute with a safe use of bytes-cast
Simon Sapin <simon.sapin@octobus.net>
parents: 46037
diff changeset
    12
use bytes_cast::BytesCast;
46495
6380efb82191 rust: replace Node::encode_hex with std::fmt::LowerHex
Simon Sapin <simon.sapin@octobus.net>
parents: 46463
diff changeset
    13
use std::fmt;
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    14
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    15
/// 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
    16
///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    17
/// 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
    18
/// 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
    19
/// 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
    20
/// the future.
45537
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 44998
diff changeset
    21
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
    22
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 44998
diff changeset
    23
/// Id of the null node.
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 44998
diff changeset
    24
///
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 44998
diff changeset
    25
/// 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
    26
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
    27
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    28
/// 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
    29
///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    30
/// 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
    31
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
    32
46757
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46634
diff changeset
    33
/// Default for UI presentation
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46634
diff changeset
    34
const SHORT_PREFIX_DEFAULT_NYBBLES_LENGTH: u8 = 12;
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46634
diff changeset
    35
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    36
/// 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
    37
type NodeData = [u8; NODE_BYTES_LENGTH];
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
/// Binary revision SHA
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    40
///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    41
/// ## Future changes of hash size
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
/// 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
    44
/// 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
    45
/// 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
    46
///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    47
/// 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
    48
/// 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
    49
/// if they need a loop boundary.
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    50
///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    51
/// All methods that create a `Node` either take a type that enforces
46496
5893706af3de rust: Simplify error type for reading hex node IDs
Simon Sapin <simon.sapin@octobus.net>
parents: 46495
diff changeset
    52
/// the size or return an error at runtime.
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    53
///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    54
/// [`nybbles_len`]: #method.nybbles_len
49210
34decbaf4da3 node: manually implement Debug
Augie Fackler <augie@google.com>
parents: 48467
diff changeset
    55
#[derive(Copy, Clone, PartialEq, BytesCast, derive_more::From)]
44512
166349510398 revlog: using two new functions in C capsule from Rust code
Georges Racinet <georges.racinet@octobus.net>
parents: 44419
diff changeset
    56
#[repr(transparent)]
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    57
pub struct Node {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    58
    data: NodeData,
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    59
}
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    60
49210
34decbaf4da3 node: manually implement Debug
Augie Fackler <augie@google.com>
parents: 48467
diff changeset
    61
impl fmt::Debug for Node {
34decbaf4da3 node: manually implement Debug
Augie Fackler <augie@google.com>
parents: 48467
diff changeset
    62
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34decbaf4da3 node: manually implement Debug
Augie Fackler <augie@google.com>
parents: 48467
diff changeset
    63
        let n = format!("{:x?}", self.data);
34decbaf4da3 node: manually implement Debug
Augie Fackler <augie@google.com>
parents: 48467
diff changeset
    64
        // We're using debug_tuple because it makes the output a little
34decbaf4da3 node: manually implement Debug
Augie Fackler <augie@google.com>
parents: 48467
diff changeset
    65
        // more compact without losing data.
34decbaf4da3 node: manually implement Debug
Augie Fackler <augie@google.com>
parents: 48467
diff changeset
    66
        f.debug_tuple("Node").field(&n).finish()
34decbaf4da3 node: manually implement Debug
Augie Fackler <augie@google.com>
parents: 48467
diff changeset
    67
    }
34decbaf4da3 node: manually implement Debug
Augie Fackler <augie@google.com>
parents: 48467
diff changeset
    68
}
34decbaf4da3 node: manually implement Debug
Augie Fackler <augie@google.com>
parents: 48467
diff changeset
    69
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    70
/// The node value for NULL_REVISION
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    71
pub const NULL_NODE: Node = Node {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    72
    data: [0; NODE_BYTES_LENGTH],
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    73
};
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    74
46037
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
    75
/// 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
    76
impl<'a> TryFrom<&'a [u8]> for &'a Node {
46463
cfb6c10c08c2 rust: replace an unsafe use of transmute with a safe use of bytes-cast
Simon Sapin <simon.sapin@octobus.net>
parents: 46037
diff changeset
    77
    type Error = ();
46037
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
    78
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
    79
    #[inline]
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
    80
    fn try_from(bytes: &'a [u8]) -> Result<Self, Self::Error> {
46463
cfb6c10c08c2 rust: replace an unsafe use of transmute with a safe use of bytes-cast
Simon Sapin <simon.sapin@octobus.net>
parents: 46037
diff changeset
    81
        match Node::from_bytes(bytes) {
cfb6c10c08c2 rust: replace an unsafe use of transmute with a safe use of bytes-cast
Simon Sapin <simon.sapin@octobus.net>
parents: 46037
diff changeset
    82
            Ok((node, rest)) if rest.is_empty() => Ok(node),
cfb6c10c08c2 rust: replace an unsafe use of transmute with a safe use of bytes-cast
Simon Sapin <simon.sapin@octobus.net>
parents: 46037
diff changeset
    83
            _ => Err(()),
cfb6c10c08c2 rust: replace an unsafe use of transmute with a safe use of bytes-cast
Simon Sapin <simon.sapin@octobus.net>
parents: 46037
diff changeset
    84
        }
46037
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
    85
    }
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
    86
}
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
    87
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
    88
/// Return an error if the slice has an unexpected length
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
    89
impl TryFrom<&'_ [u8]> for Node {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
    90
    type Error = std::array::TryFromSliceError;
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
    91
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
    92
    #[inline]
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
    93
    fn try_from(bytes: &'_ [u8]) -> Result<Self, Self::Error> {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
    94
        let data = bytes.try_into()?;
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
    95
        Ok(Self { data })
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
    96
    }
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
    97
}
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
    98
46634
98a455a62699 rust: Make `DirstateParents`’s fields typed `Node`s
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    99
impl From<&'_ NodeData> for Node {
98a455a62699 rust: Make `DirstateParents`’s fields typed `Node`s
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
   100
    #[inline]
98a455a62699 rust: Make `DirstateParents`’s fields typed `Node`s
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
   101
    fn from(data: &'_ NodeData) -> Self {
98a455a62699 rust: Make `DirstateParents`’s fields typed `Node`s
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
   102
        Self { data: *data }
98a455a62699 rust: Make `DirstateParents`’s fields typed `Node`s
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
   103
    }
98a455a62699 rust: Make `DirstateParents`’s fields typed `Node`s
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
   104
}
98a455a62699 rust: Make `DirstateParents`’s fields typed `Node`s
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
   105
46495
6380efb82191 rust: replace Node::encode_hex with std::fmt::LowerHex
Simon Sapin <simon.sapin@octobus.net>
parents: 46463
diff changeset
   106
impl fmt::LowerHex for Node {
6380efb82191 rust: replace Node::encode_hex with std::fmt::LowerHex
Simon Sapin <simon.sapin@octobus.net>
parents: 46463
diff changeset
   107
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6380efb82191 rust: replace Node::encode_hex with std::fmt::LowerHex
Simon Sapin <simon.sapin@octobus.net>
parents: 46463
diff changeset
   108
        for &byte in &self.data {
6380efb82191 rust: replace Node::encode_hex with std::fmt::LowerHex
Simon Sapin <simon.sapin@octobus.net>
parents: 46463
diff changeset
   109
            write!(f, "{:02x}", byte)?
6380efb82191 rust: replace Node::encode_hex with std::fmt::LowerHex
Simon Sapin <simon.sapin@octobus.net>
parents: 46463
diff changeset
   110
        }
6380efb82191 rust: replace Node::encode_hex with std::fmt::LowerHex
Simon Sapin <simon.sapin@octobus.net>
parents: 46463
diff changeset
   111
        Ok(())
6380efb82191 rust: replace Node::encode_hex with std::fmt::LowerHex
Simon Sapin <simon.sapin@octobus.net>
parents: 46463
diff changeset
   112
    }
6380efb82191 rust: replace Node::encode_hex with std::fmt::LowerHex
Simon Sapin <simon.sapin@octobus.net>
parents: 46463
diff changeset
   113
}
6380efb82191 rust: replace Node::encode_hex with std::fmt::LowerHex
Simon Sapin <simon.sapin@octobus.net>
parents: 46463
diff changeset
   114
46496
5893706af3de rust: Simplify error type for reading hex node IDs
Simon Sapin <simon.sapin@octobus.net>
parents: 46495
diff changeset
   115
#[derive(Debug)]
5893706af3de rust: Simplify error type for reading hex node IDs
Simon Sapin <simon.sapin@octobus.net>
parents: 46495
diff changeset
   116
pub struct FromHexError;
44228
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
/// 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
   119
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
   120
    if i % 2 == 0 {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   121
        s[i / 2] >> 4
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   122
    } else {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   123
        s[i / 2] & 0x0f
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
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   127
impl Node {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   128
    /// 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
   129
    ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   130
    /// 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
   131
    /// 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
   132
    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
   133
        get_nybble(&self.data, i)
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   134
    }
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
    /// Length of the data, in nybbles
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   137
    pub fn nybbles_len(&self) -> usize {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   138
        // 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
   139
        // 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
   140
        NODE_NYBBLES_LENGTH
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
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   143
    /// Convert from hexadecimal string representation
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   144
    ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   145
    /// Exact length is required.
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   146
    ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   147
    /// 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
   148
    /// changes of hash format.
46496
5893706af3de rust: Simplify error type for reading hex node IDs
Simon Sapin <simon.sapin@octobus.net>
parents: 46495
diff changeset
   149
    pub fn from_hex(hex: impl AsRef<[u8]>) -> Result<Node, FromHexError> {
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   150
        let prefix = NodePrefix::from_hex(hex)?;
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   151
        if prefix.nybbles_len() == NODE_NYBBLES_LENGTH {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   152
            Ok(Self { data: prefix.data })
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   153
        } else {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   154
            Err(FromHexError)
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   155
        }
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   156
    }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   157
46511
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46503
diff changeset
   158
    /// `from_hex`, but for input from an internal file of the repository such
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46503
diff changeset
   159
    /// as a changelog or manifest entry.
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46503
diff changeset
   160
    ///
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46503
diff changeset
   161
    /// An error is treated as repository corruption.
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46503
diff changeset
   162
    pub fn from_hex_for_repo(hex: impl AsRef<[u8]>) -> Result<Node, HgError> {
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46503
diff changeset
   163
        Self::from_hex(hex.as_ref()).map_err(|FromHexError| {
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46503
diff changeset
   164
            HgError::CorruptedRepository(format!(
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46503
diff changeset
   165
                "Expected a full hexadecimal node ID, found {}",
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46503
diff changeset
   166
                String::from_utf8_lossy(hex.as_ref())
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46503
diff changeset
   167
            ))
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46503
diff changeset
   168
        })
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46503
diff changeset
   169
    }
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46503
diff changeset
   170
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   171
    /// Provide access to binary data
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   172
    ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   173
    /// 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
   174
    /// binary values to Python.
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   175
    pub fn as_bytes(&self) -> &[u8] {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   176
        &self.data
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   177
    }
46757
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46634
diff changeset
   178
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46634
diff changeset
   179
    pub fn short(&self) -> NodePrefix {
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46634
diff changeset
   180
        NodePrefix {
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46634
diff changeset
   181
            nybbles_len: SHORT_PREFIX_DEFAULT_NYBBLES_LENGTH,
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46634
diff changeset
   182
            data: self.data,
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46634
diff changeset
   183
        }
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46634
diff changeset
   184
    }
48467
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 46757
diff changeset
   185
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 46757
diff changeset
   186
    pub fn pad_to_256_bits(&self) -> [u8; 32] {
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 46757
diff changeset
   187
        let mut bits = [0; 32];
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 46757
diff changeset
   188
        bits[..NODE_BYTES_LENGTH].copy_from_slice(&self.data);
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 46757
diff changeset
   189
        bits
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 46757
diff changeset
   190
    }
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   191
}
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   192
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   193
/// The beginning of a binary revision SHA.
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   194
///
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   195
/// 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
   196
/// 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
   197
/// or not.
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   198
#[derive(Debug, PartialEq, Copy, Clone)]
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   199
pub struct NodePrefix {
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   200
    /// In `1..=NODE_NYBBLES_LENGTH`
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   201
    nybbles_len: u8,
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   202
    /// The first `4 * length_in_nybbles` bits are used (considering bits
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   203
    /// within a bytes in big-endian: most significant first), the rest
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   204
    /// are zero.
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   205
    data: NodeData,
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   206
}
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   207
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   208
impl NodePrefix {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   209
    /// Convert from hexadecimal string representation
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
    /// 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
   212
    /// (`String`, `&str`) as well as bytes.
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   213
    ///
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   214
    /// 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
   215
    /// changes of hash format.
46496
5893706af3de rust: Simplify error type for reading hex node IDs
Simon Sapin <simon.sapin@octobus.net>
parents: 46495
diff changeset
   216
    pub fn from_hex(hex: impl AsRef<[u8]>) -> Result<Self, FromHexError> {
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   217
        let hex = hex.as_ref();
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   218
        let len = hex.len();
46497
e61c2dc6e1c2 rust: Exclude empty node prefixes
Simon Sapin <simon.sapin@octobus.net>
parents: 46496
diff changeset
   219
        if len > NODE_NYBBLES_LENGTH || len == 0 {
46496
5893706af3de rust: Simplify error type for reading hex node IDs
Simon Sapin <simon.sapin@octobus.net>
parents: 46495
diff changeset
   220
            return Err(FromHexError);
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   221
        }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   222
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   223
        let mut data = [0; NODE_BYTES_LENGTH];
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   224
        let mut nybbles_len = 0;
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   225
        for &ascii_byte in hex {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   226
            let nybble = match char::from(ascii_byte).to_digit(16) {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   227
                Some(digit) => digit as u8,
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   228
                None => return Err(FromHexError),
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   229
            };
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   230
            // Fill in the upper half of a byte first, then the lower half.
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   231
            let shift = if nybbles_len % 2 == 0 { 4 } else { 0 };
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   232
            data[nybbles_len as usize / 2] |= nybble << shift;
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   233
            nybbles_len += 1;
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   234
        }
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   235
        Ok(Self { data, nybbles_len })
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   236
    }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   237
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   238
    pub fn nybbles_len(&self) -> usize {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   239
        self.nybbles_len as _
44257
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
    pub fn is_prefix_of(&self, node: &Node) -> bool {
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   243
        let full_bytes = self.nybbles_len() / 2;
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   244
        if self.data[..full_bytes] != node.data[..full_bytes] {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   245
            return false;
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   246
        }
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   247
        if self.nybbles_len() % 2 == 0 {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   248
            return true;
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   249
        }
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   250
        let last = self.nybbles_len() - 1;
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   251
        self.get_nybble(last) == node.get_nybble(last)
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   252
    }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   253
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   254
    /// 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
   255
    ///
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   256
    /// 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
   257
    /// 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
   258
    pub fn get_nybble(&self, i: usize) -> u8 {
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   259
        assert!(i < self.nybbles_len());
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   260
        get_nybble(&self.data, i)
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   261
    }
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   262
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   263
    fn iter_nybbles(&self) -> impl Iterator<Item = u8> + '_ {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   264
        (0..self.nybbles_len()).map(move |i| get_nybble(&self.data, i))
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   265
    }
44419
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   266
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   267
    /// 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
   268
    ///
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   269
    /// 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
   270
    /// 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
   271
    /// than `is_prefix_of`.
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   272
    ///
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   273
    /// 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
   274
    pub fn first_different_nybble(&self, node: &Node) -> Option<usize> {
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   275
        self.iter_nybbles()
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   276
            .zip(NodePrefix::from(*node).iter_nybbles())
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   277
            .position(|(a, b)| a != b)
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   278
    }
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   279
}
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   280
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   281
impl fmt::LowerHex for NodePrefix {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   282
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   283
        let full_bytes = self.nybbles_len() / 2;
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   284
        for &byte in &self.data[..full_bytes] {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   285
            write!(f, "{:02x}", byte)?
44419
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   286
        }
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   287
        if self.nybbles_len() % 2 == 1 {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   288
            let last = self.nybbles_len() - 1;
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   289
            write!(f, "{:x}", self.get_nybble(last))?
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   290
        }
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   291
        Ok(())
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   292
    }
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   293
}
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   294
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   295
/// A shortcut for full `Node` references
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   296
impl From<&'_ Node> for NodePrefix {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   297
    fn from(node: &'_ Node) -> Self {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   298
        NodePrefix {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   299
            nybbles_len: node.nybbles_len() as _,
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   300
            data: node.data,
44419
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   301
        }
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   302
    }
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   303
}
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   304
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   305
/// A shortcut for full `Node` references
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   306
impl From<Node> for NodePrefix {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   307
    fn from(node: Node) -> Self {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   308
        NodePrefix {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   309
            nybbles_len: node.nybbles_len() as _,
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   310
            data: node.data,
44228
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
    }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   313
}
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   314
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   315
impl PartialEq<Node> for NodePrefix {
46037
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
   316
    fn eq(&self, other: &Node) -> bool {
50000
2202832b35e8 rust-nodemap: implement `PartialEq` without allocation
Raphaël Gomès <rgomes@octobus.net>
parents: 49749
diff changeset
   317
        self.data == other.data && self.nybbles_len() == other.nybbles_len()
46037
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
   318
    }
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
   319
}
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45537
diff changeset
   320
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   321
#[cfg(test)]
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   322
mod tests {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   323
    use super::*;
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   324
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   325
    const SAMPLE_NODE_HEX: &str = "0123456789abcdeffedcba9876543210deadbeef";
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   326
    const SAMPLE_NODE: Node = Node {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   327
        data: [
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   328
            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
   329
            0x98, 0x76, 0x54, 0x32, 0x10, 0xde, 0xad, 0xbe, 0xef,
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   330
        ],
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   331
    };
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   332
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   333
    /// Pad an hexadecimal string to reach `NODE_NYBBLES_LENGTH`
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   334
    /// 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
   335
    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
   336
        let mut res = hex.to_string();
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   337
        while res.len() < NODE_NYBBLES_LENGTH {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   338
            res.push('0');
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   339
        }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   340
        res
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   341
    }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   342
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   343
    #[test]
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   344
    fn test_node_from_hex() {
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   345
        let not_hex = "012... oops";
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   346
        let too_short = "0123";
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   347
        let too_long = format!("{}0", SAMPLE_NODE_HEX);
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   348
        assert_eq!(Node::from_hex(SAMPLE_NODE_HEX).unwrap(), SAMPLE_NODE);
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   349
        assert!(Node::from_hex(not_hex).is_err());
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   350
        assert!(Node::from_hex(too_short).is_err());
51118
532e74ad3ff6 rust: run a clippy pass with the latest stable version
Raphaël Gomès <rgomes@octobus.net>
parents: 50000
diff changeset
   351
        assert!(Node::from_hex(too_long).is_err());
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   352
    }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   353
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   354
    #[test]
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   355
    fn test_node_encode_hex() {
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   356
        assert_eq!(format!("{:x}", SAMPLE_NODE), SAMPLE_NODE_HEX);
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   357
    }
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   358
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   359
    #[test]
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   360
    fn test_prefix_from_to_hex() -> Result<(), FromHexError> {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   361
        assert_eq!(format!("{:x}", NodePrefix::from_hex("0e1")?), "0e1");
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   362
        assert_eq!(format!("{:x}", NodePrefix::from_hex("0e1a")?), "0e1a");
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   363
        assert_eq!(
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   364
            format!("{:x}", NodePrefix::from_hex(SAMPLE_NODE_HEX)?),
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   365
            SAMPLE_NODE_HEX
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   366
        );
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   367
        Ok(())
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
    #[test]
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   371
    fn test_prefix_from_hex_errors() {
46496
5893706af3de rust: Simplify error type for reading hex node IDs
Simon Sapin <simon.sapin@octobus.net>
parents: 46495
diff changeset
   372
        assert!(NodePrefix::from_hex("testgr").is_err());
46495
6380efb82191 rust: replace Node::encode_hex with std::fmt::LowerHex
Simon Sapin <simon.sapin@octobus.net>
parents: 46463
diff changeset
   373
        let mut long = format!("{:x}", NULL_NODE);
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   374
        long.push('c');
46496
5893706af3de rust: Simplify error type for reading hex node IDs
Simon Sapin <simon.sapin@octobus.net>
parents: 46495
diff changeset
   375
        assert!(NodePrefix::from_hex(&long).is_err())
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   376
    }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   377
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   378
    #[test]
46496
5893706af3de rust: Simplify error type for reading hex node IDs
Simon Sapin <simon.sapin@octobus.net>
parents: 46495
diff changeset
   379
    fn test_is_prefix_of() -> Result<(), FromHexError> {
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   380
        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
   381
        node_data[0] = 0x12;
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   382
        node_data[1] = 0xca;
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   383
        let node = Node::from(node_data);
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   384
        assert!(NodePrefix::from_hex("12")?.is_prefix_of(&node));
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   385
        assert!(!NodePrefix::from_hex("1a")?.is_prefix_of(&node));
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   386
        assert!(NodePrefix::from_hex("12c")?.is_prefix_of(&node));
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   387
        assert!(!NodePrefix::from_hex("12d")?.is_prefix_of(&node));
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   388
        Ok(())
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   389
    }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   390
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   391
    #[test]
46496
5893706af3de rust: Simplify error type for reading hex node IDs
Simon Sapin <simon.sapin@octobus.net>
parents: 46495
diff changeset
   392
    fn test_get_nybble() -> Result<(), FromHexError> {
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   393
        let prefix = NodePrefix::from_hex("dead6789cafe")?;
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   394
        assert_eq!(prefix.get_nybble(0), 13);
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   395
        assert_eq!(prefix.get_nybble(7), 9);
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   396
        Ok(())
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
   397
    }
44419
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   398
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   399
    #[test]
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   400
    fn test_first_different_nybble_even_prefix() {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   401
        let prefix = NodePrefix::from_hex("12ca").unwrap();
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   402
        let mut node = Node::from([0; NODE_BYTES_LENGTH]);
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   403
        assert_eq!(prefix.first_different_nybble(&node), Some(0));
44419
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   404
        node.data[0] = 0x13;
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   405
        assert_eq!(prefix.first_different_nybble(&node), Some(1));
44419
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   406
        node.data[0] = 0x12;
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   407
        assert_eq!(prefix.first_different_nybble(&node), Some(2));
44419
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   408
        node.data[1] = 0xca;
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   409
        // now it is a prefix
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   410
        assert_eq!(prefix.first_different_nybble(&node), None);
44419
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   411
    }
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   412
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   413
    #[test]
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   414
    fn test_first_different_nybble_odd_prefix() {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   415
        let prefix = NodePrefix::from_hex("12c").unwrap();
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   416
        let mut node = Node::from([0; NODE_BYTES_LENGTH]);
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   417
        assert_eq!(prefix.first_different_nybble(&node), Some(0));
44419
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   418
        node.data[0] = 0x13;
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   419
        assert_eq!(prefix.first_different_nybble(&node), Some(1));
44419
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   420
        node.data[0] = 0x12;
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   421
        assert_eq!(prefix.first_different_nybble(&node), Some(2));
44419
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   422
        node.data[1] = 0xca;
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   423
        // now it is a prefix
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46497
diff changeset
   424
        assert_eq!(prefix.first_different_nybble(&node), None);
44419
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
   425
    }
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   426
}
44258
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44257
diff changeset
   427
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44257
diff changeset
   428
#[cfg(test)]
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44257
diff changeset
   429
pub use tests::hex_pad_right;