annotate rust/hg-core/src/revlog/node.rs @ 50222:ecd28d89c29e stable

dirstate-v2: add devel config option to control write behavior This will help us to write predictable tests checking behavior in each case.
author Rapha?l Gom?s <rgomes@octobus.net>
date Tue, 28 Feb 2023 15:49:53 +0100
parents 34decbaf4da3
children c7fb9b74e753
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
44143
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
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46435
diff changeset
11 use crate::errors::HgError;
46391
cfb6c10c08c2 rust: replace an unsafe use of transmute with a safe use of bytes-cast
Simon Sapin <simon.sapin@octobus.net>
parents: 46033
diff changeset
12 use bytes_cast::BytesCast;
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
13 use std::convert::{TryFrom, TryInto};
46427
6380efb82191 rust: replace Node::encode_hex with std::fmt::LowerHex
Simon Sapin <simon.sapin@octobus.net>
parents: 46391
diff changeset
14 use std::fmt;
44143
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 /// 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
17 ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
18 /// 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
19 /// 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
20 /// 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
21 /// the future.
45531
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 44973
diff changeset
22 pub const NODE_BYTES_LENGTH: usize = 20;
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 44973
diff changeset
23
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 44973
diff changeset
24 /// Id of the null node.
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 44973
diff changeset
25 ///
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 44973
diff changeset
26 /// Used to indicate the absence of node.
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 44973
diff changeset
27 pub const NULL_NODE_ID: [u8; NODE_BYTES_LENGTH] = [0u8; NODE_BYTES_LENGTH];
44143
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 /// 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
30 ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
31 /// 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
32 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
33
46744
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46595
diff changeset
34 /// Default for UI presentation
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46595
diff changeset
35 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: 46595
diff changeset
36
44143
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
37 /// 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
38 type NodeData = [u8; NODE_BYTES_LENGTH];
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
39
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
40 /// Binary revision SHA
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
41 ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
42 /// ## Future changes of hash size
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
43 ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
44 /// 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
45 /// 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
46 /// 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
47 ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
48 /// 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
49 /// 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
50 /// if they need a loop boundary.
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
51 ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
52 /// All methods that create a `Node` either take a type that enforces
46428
5893706af3de rust: Simplify error type for reading hex node IDs
Simon Sapin <simon.sapin@octobus.net>
parents: 46427
diff changeset
53 /// the size or return an error at runtime.
44143
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
54 ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
55 /// [`nybbles_len`]: #method.nybbles_len
49175
34decbaf4da3 node: manually implement Debug
Augie Fackler <augie@google.com>
parents: 48421
diff changeset
56 #[derive(Copy, Clone, PartialEq, BytesCast, derive_more::From)]
44502
166349510398 revlog: using two new functions in C capsule from Rust code
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
57 #[repr(transparent)]
44143
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
58 pub struct Node {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
59 data: NodeData,
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
60 }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
61
49175
34decbaf4da3 node: manually implement Debug
Augie Fackler <augie@google.com>
parents: 48421
diff changeset
62 impl fmt::Debug for Node {
34decbaf4da3 node: manually implement Debug
Augie Fackler <augie@google.com>
parents: 48421
diff changeset
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34decbaf4da3 node: manually implement Debug
Augie Fackler <augie@google.com>
parents: 48421
diff changeset
64 let n = format!("{:x?}", self.data);
34decbaf4da3 node: manually implement Debug
Augie Fackler <augie@google.com>
parents: 48421
diff changeset
65 // We're using debug_tuple because it makes the output a little
34decbaf4da3 node: manually implement Debug
Augie Fackler <augie@google.com>
parents: 48421
diff changeset
66 // more compact without losing data.
34decbaf4da3 node: manually implement Debug
Augie Fackler <augie@google.com>
parents: 48421
diff changeset
67 f.debug_tuple("Node").field(&n).finish()
34decbaf4da3 node: manually implement Debug
Augie Fackler <augie@google.com>
parents: 48421
diff changeset
68 }
34decbaf4da3 node: manually implement Debug
Augie Fackler <augie@google.com>
parents: 48421
diff changeset
69 }
34decbaf4da3 node: manually implement Debug
Augie Fackler <augie@google.com>
parents: 48421
diff changeset
70
44143
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
71 /// The node value for NULL_REVISION
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
72 pub const NULL_NODE: Node = Node {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
73 data: [0; NODE_BYTES_LENGTH],
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
74 };
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
75
46033
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45531
diff changeset
76 /// 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: 45531
diff changeset
77 impl<'a> TryFrom<&'a [u8]> for &'a Node {
46391
cfb6c10c08c2 rust: replace an unsafe use of transmute with a safe use of bytes-cast
Simon Sapin <simon.sapin@octobus.net>
parents: 46033
diff changeset
78 type Error = ();
46033
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45531
diff changeset
79
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45531
diff changeset
80 #[inline]
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
81 fn try_from(bytes: &'a [u8]) -> Result<Self, Self::Error> {
46391
cfb6c10c08c2 rust: replace an unsafe use of transmute with a safe use of bytes-cast
Simon Sapin <simon.sapin@octobus.net>
parents: 46033
diff changeset
82 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: 46033
diff changeset
83 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: 46033
diff changeset
84 _ => Err(()),
cfb6c10c08c2 rust: replace an unsafe use of transmute with a safe use of bytes-cast
Simon Sapin <simon.sapin@octobus.net>
parents: 46033
diff changeset
85 }
46033
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45531
diff changeset
86 }
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45531
diff changeset
87 }
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45531
diff changeset
88
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
89 /// 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: 46429
diff changeset
90 impl TryFrom<&'_ [u8]> for Node {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
91 type Error = std::array::TryFromSliceError;
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
92
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
93 #[inline]
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
94 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: 46429
diff changeset
95 let data = bytes.try_into()?;
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
96 Ok(Self { data })
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
97 }
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
98 }
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
99
46595
98a455a62699 rust: Make `DirstateParents`?s fields typed `Node`s
Simon Sapin <simon.sapin@octobus.net>
parents: 46443
diff changeset
100 impl From<&'_ NodeData> for Node {
98a455a62699 rust: Make `DirstateParents`?s fields typed `Node`s
Simon Sapin <simon.sapin@octobus.net>
parents: 46443
diff changeset
101 #[inline]
98a455a62699 rust: Make `DirstateParents`?s fields typed `Node`s
Simon Sapin <simon.sapin@octobus.net>
parents: 46443
diff changeset
102 fn from(data: &'_ NodeData) -> Self {
98a455a62699 rust: Make `DirstateParents`?s fields typed `Node`s
Simon Sapin <simon.sapin@octobus.net>
parents: 46443
diff changeset
103 Self { data: *data }
98a455a62699 rust: Make `DirstateParents`?s fields typed `Node`s
Simon Sapin <simon.sapin@octobus.net>
parents: 46443
diff changeset
104 }
98a455a62699 rust: Make `DirstateParents`?s fields typed `Node`s
Simon Sapin <simon.sapin@octobus.net>
parents: 46443
diff changeset
105 }
98a455a62699 rust: Make `DirstateParents`?s fields typed `Node`s
Simon Sapin <simon.sapin@octobus.net>
parents: 46443
diff changeset
106
46427
6380efb82191 rust: replace Node::encode_hex with std::fmt::LowerHex
Simon Sapin <simon.sapin@octobus.net>
parents: 46391
diff changeset
107 impl fmt::LowerHex for Node {
6380efb82191 rust: replace Node::encode_hex with std::fmt::LowerHex
Simon Sapin <simon.sapin@octobus.net>
parents: 46391
diff changeset
108 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: 46391
diff changeset
109 for &byte in &self.data {
6380efb82191 rust: replace Node::encode_hex with std::fmt::LowerHex
Simon Sapin <simon.sapin@octobus.net>
parents: 46391
diff changeset
110 write!(f, "{:02x}", byte)?
6380efb82191 rust: replace Node::encode_hex with std::fmt::LowerHex
Simon Sapin <simon.sapin@octobus.net>
parents: 46391
diff changeset
111 }
6380efb82191 rust: replace Node::encode_hex with std::fmt::LowerHex
Simon Sapin <simon.sapin@octobus.net>
parents: 46391
diff changeset
112 Ok(())
6380efb82191 rust: replace Node::encode_hex with std::fmt::LowerHex
Simon Sapin <simon.sapin@octobus.net>
parents: 46391
diff changeset
113 }
6380efb82191 rust: replace Node::encode_hex with std::fmt::LowerHex
Simon Sapin <simon.sapin@octobus.net>
parents: 46391
diff changeset
114 }
6380efb82191 rust: replace Node::encode_hex with std::fmt::LowerHex
Simon Sapin <simon.sapin@octobus.net>
parents: 46391
diff changeset
115
46428
5893706af3de rust: Simplify error type for reading hex node IDs
Simon Sapin <simon.sapin@octobus.net>
parents: 46427
diff changeset
116 #[derive(Debug)]
5893706af3de rust: Simplify error type for reading hex node IDs
Simon Sapin <simon.sapin@octobus.net>
parents: 46427
diff changeset
117 pub struct FromHexError;
44143
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
118
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
119 /// 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
120 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
121 if i % 2 == 0 {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
122 s[i / 2] >> 4
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
123 } else {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
124 s[i / 2] & 0x0f
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
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
128 impl Node {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
129 /// 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
130 ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
131 /// 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
132 /// 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
133 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
134 get_nybble(&self.data, i)
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
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
137 /// Length of the data, in nybbles
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
138 pub fn nybbles_len(&self) -> usize {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
139 // 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
140 // 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
141 NODE_NYBBLES_LENGTH
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
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
144 /// Convert from hexadecimal string representation
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
145 ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
146 /// Exact length is required.
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
147 ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
148 /// 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
149 /// changes of hash format.
46428
5893706af3de rust: Simplify error type for reading hex node IDs
Simon Sapin <simon.sapin@octobus.net>
parents: 46427
diff changeset
150 pub fn from_hex(hex: impl AsRef<[u8]>) -> Result<Node, FromHexError> {
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
151 let prefix = NodePrefix::from_hex(hex)?;
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
152 if prefix.nybbles_len() == NODE_NYBBLES_LENGTH {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
153 Ok(Self { data: prefix.data })
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
154 } else {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
155 Err(FromHexError)
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
156 }
44143
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
157 }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
158
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46435
diff changeset
159 /// `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: 46435
diff changeset
160 /// as a changelog or manifest entry.
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46435
diff changeset
161 ///
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46435
diff changeset
162 /// An error is treated as repository corruption.
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46435
diff changeset
163 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: 46435
diff changeset
164 Self::from_hex(hex.as_ref()).map_err(|FromHexError| {
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46435
diff changeset
165 HgError::CorruptedRepository(format!(
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46435
diff changeset
166 "Expected a full hexadecimal node ID, found {}",
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46435
diff changeset
167 String::from_utf8_lossy(hex.as_ref())
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46435
diff changeset
168 ))
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46435
diff changeset
169 })
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46435
diff changeset
170 }
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46435
diff changeset
171
44143
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
172 /// Provide access to binary data
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
173 ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
174 /// 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
175 /// binary values to Python.
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
176 pub fn as_bytes(&self) -> &[u8] {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
177 &self.data
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
178 }
46744
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46595
diff changeset
179
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46595
diff changeset
180 pub fn short(&self) -> NodePrefix {
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46595
diff changeset
181 NodePrefix {
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46595
diff changeset
182 nybbles_len: SHORT_PREFIX_DEFAULT_NYBBLES_LENGTH,
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46595
diff changeset
183 data: self.data,
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46595
diff changeset
184 }
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46595
diff changeset
185 }
48421
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 46744
diff changeset
186
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 46744
diff changeset
187 pub fn pad_to_256_bits(&self) -> [u8; 32] {
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 46744
diff changeset
188 let mut bits = [0; 32];
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 46744
diff changeset
189 bits[..NODE_BYTES_LENGTH].copy_from_slice(&self.data);
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 46744
diff changeset
190 bits
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 46744
diff changeset
191 }
44143
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
192 }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
193
44182
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
194 /// The beginning of a binary revision SHA.
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
195 ///
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
196 /// Since it can potentially come from an hexadecimal representation with
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
197 /// 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: 44143
diff changeset
198 /// or not.
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
199 #[derive(Debug, PartialEq, Copy, Clone)]
44182
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
200 pub struct NodePrefix {
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
201 /// In `1..=NODE_NYBBLES_LENGTH`
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
202 nybbles_len: u8,
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
203 /// 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: 46429
diff changeset
204 /// 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: 46429
diff changeset
205 /// are zero.
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
206 data: NodeData,
44182
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
207 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
208
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
209 impl NodePrefix {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
210 /// Convert from hexadecimal string representation
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
211 ///
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
212 /// 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: 44143
diff changeset
213 /// (`String`, `&str`) as well as bytes.
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
214 ///
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
215 /// 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: 44143
diff changeset
216 /// changes of hash format.
46428
5893706af3de rust: Simplify error type for reading hex node IDs
Simon Sapin <simon.sapin@octobus.net>
parents: 46427
diff changeset
217 pub fn from_hex(hex: impl AsRef<[u8]>) -> Result<Self, FromHexError> {
44182
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
218 let hex = hex.as_ref();
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
219 let len = hex.len();
46429
e61c2dc6e1c2 rust: Exclude empty node prefixes
Simon Sapin <simon.sapin@octobus.net>
parents: 46428
diff changeset
220 if len > NODE_NYBBLES_LENGTH || len == 0 {
46428
5893706af3de rust: Simplify error type for reading hex node IDs
Simon Sapin <simon.sapin@octobus.net>
parents: 46427
diff changeset
221 return Err(FromHexError);
44182
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
222 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
223
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
224 let mut data = [0; NODE_BYTES_LENGTH];
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
225 let mut nybbles_len = 0;
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
226 for &ascii_byte in hex {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
227 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: 46429
diff changeset
228 Some(digit) => digit as u8,
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
229 None => return Err(FromHexError),
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
230 };
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
231 // 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: 46429
diff changeset
232 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: 46429
diff changeset
233 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: 46429
diff changeset
234 nybbles_len += 1;
44182
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
235 }
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
236 Ok(Self { data, nybbles_len })
44182
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
237 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
238
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
239 pub fn nybbles_len(&self) -> usize {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
240 self.nybbles_len as _
44182
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
241 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
242
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
243 pub fn is_prefix_of(&self, node: &Node) -> bool {
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
244 let full_bytes = self.nybbles_len() / 2;
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
245 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: 46429
diff changeset
246 return false;
44182
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
247 }
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
248 if self.nybbles_len() % 2 == 0 {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
249 return true;
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
250 }
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
251 let last = self.nybbles_len() - 1;
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
252 self.get_nybble(last) == node.get_nybble(last)
44182
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
253 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
254
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
255 /// Retrieve the `i`th half-byte from the prefix.
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
256 ///
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
257 /// 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: 44143
diff changeset
258 /// also called a [nybble](https://en.wikipedia.org/wiki/Nibble).
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
259 pub fn get_nybble(&self, i: usize) -> u8 {
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
260 assert!(i < self.nybbles_len());
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
261 get_nybble(&self.data, i)
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
262 }
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
263
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
264 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: 46429
diff changeset
265 (0..self.nybbles_len()).map(move |i| get_nybble(&self.data, i))
44182
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
266 }
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44187
diff changeset
267
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44187
diff changeset
268 /// Return the index first nybble that's different from `node`
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44187
diff changeset
269 ///
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44187
diff changeset
270 /// 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: 44187
diff changeset
271 /// 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: 44187
diff changeset
272 /// than `is_prefix_of`.
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44187
diff changeset
273 ///
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44187
diff changeset
274 /// 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: 44187
diff changeset
275 pub fn first_different_nybble(&self, node: &Node) -> Option<usize> {
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
276 self.iter_nybbles()
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
277 .zip(NodePrefix::from(*node).iter_nybbles())
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
278 .position(|(a, b)| a != b)
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
279 }
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
280 }
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
281
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
282 impl fmt::LowerHex for NodePrefix {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
283 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: 46429
diff changeset
284 let full_bytes = self.nybbles_len() / 2;
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
285 for &byte in &self.data[..full_bytes] {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
286 write!(f, "{:02x}", byte)?
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44187
diff changeset
287 }
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
288 if self.nybbles_len() % 2 == 1 {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
289 let last = self.nybbles_len() - 1;
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
290 write!(f, "{:x}", self.get_nybble(last))?
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
291 }
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
292 Ok(())
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
293 }
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
294 }
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
295
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
296 /// A shortcut for full `Node` references
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
297 impl From<&'_ Node> for NodePrefix {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
298 fn from(node: &'_ Node) -> Self {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
299 NodePrefix {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
300 nybbles_len: node.nybbles_len() as _,
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
301 data: node.data,
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44187
diff changeset
302 }
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44187
diff changeset
303 }
44182
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
304 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
305
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
306 /// A shortcut for full `Node` references
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
307 impl From<Node> for NodePrefix {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
308 fn from(node: Node) -> Self {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
309 NodePrefix {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
310 nybbles_len: node.nybbles_len() as _,
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
311 data: node.data,
44143
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 }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
315
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
316 impl PartialEq<Node> for NodePrefix {
46033
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45531
diff changeset
317 fn eq(&self, other: &Node) -> bool {
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
318 Self::from(*other) == *self
46033
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45531
diff changeset
319 }
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45531
diff changeset
320 }
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 45531
diff changeset
321
44143
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
322 #[cfg(test)]
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
323 mod tests {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
324 use super::*;
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
325
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
326 const SAMPLE_NODE_HEX: &str = "0123456789abcdeffedcba9876543210deadbeef";
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
327 const SAMPLE_NODE: Node = Node {
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
328 data: [
44143
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
329 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
330 0x98, 0x76, 0x54, 0x32, 0x10, 0xde, 0xad, 0xbe, 0xef,
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
331 ],
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
332 };
44143
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
333
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
334 /// Pad an hexadecimal string to reach `NODE_NYBBLES_LENGTH`
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
335 /// The padding is made with zeros.
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44182
diff changeset
336 pub fn hex_pad_right(hex: &str) -> String {
44143
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
337 let mut res = hex.to_string();
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
338 while res.len() < NODE_NYBBLES_LENGTH {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
339 res.push('0');
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
340 }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
341 res
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
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
344 #[test]
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
345 fn test_node_from_hex() {
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
346 let not_hex = "012... oops";
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
347 let too_short = "0123";
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
348 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: 46429
diff changeset
349 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: 46429
diff changeset
350 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: 46429
diff changeset
351 assert!(Node::from_hex(too_short).is_err());
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
352 assert!(Node::from_hex(&too_long).is_err());
44143
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
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
355 #[test]
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
356 fn test_node_encode_hex() {
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
357 assert_eq!(format!("{:x}", SAMPLE_NODE), SAMPLE_NODE_HEX);
44143
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
358 }
44182
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
359
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
360 #[test]
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
361 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: 46429
diff changeset
362 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: 46429
diff changeset
363 assert_eq!(format!("{:x}", NodePrefix::from_hex("0e1a")?), "0e1a");
44182
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
364 assert_eq!(
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
365 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: 46429
diff changeset
366 SAMPLE_NODE_HEX
44182
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
367 );
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
368 Ok(())
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
369 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
370
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
371 #[test]
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
372 fn test_prefix_from_hex_errors() {
46428
5893706af3de rust: Simplify error type for reading hex node IDs
Simon Sapin <simon.sapin@octobus.net>
parents: 46427
diff changeset
373 assert!(NodePrefix::from_hex("testgr").is_err());
46427
6380efb82191 rust: replace Node::encode_hex with std::fmt::LowerHex
Simon Sapin <simon.sapin@octobus.net>
parents: 46391
diff changeset
374 let mut long = format!("{:x}", NULL_NODE);
44182
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
375 long.push('c');
46428
5893706af3de rust: Simplify error type for reading hex node IDs
Simon Sapin <simon.sapin@octobus.net>
parents: 46427
diff changeset
376 assert!(NodePrefix::from_hex(&long).is_err())
44182
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
377 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
378
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
379 #[test]
46428
5893706af3de rust: Simplify error type for reading hex node IDs
Simon Sapin <simon.sapin@octobus.net>
parents: 46427
diff changeset
380 fn test_is_prefix_of() -> Result<(), FromHexError> {
44182
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
381 let mut node_data = [0; NODE_BYTES_LENGTH];
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
382 node_data[0] = 0x12;
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
383 node_data[1] = 0xca;
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
384 let node = Node::from(node_data);
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
385 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: 46429
diff changeset
386 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: 46429
diff changeset
387 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: 46429
diff changeset
388 assert!(!NodePrefix::from_hex("12d")?.is_prefix_of(&node));
44182
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
389 Ok(())
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
390 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
391
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
392 #[test]
46428
5893706af3de rust: Simplify error type for reading hex node IDs
Simon Sapin <simon.sapin@octobus.net>
parents: 46427
diff changeset
393 fn test_get_nybble() -> Result<(), FromHexError> {
44182
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
394 let prefix = NodePrefix::from_hex("dead6789cafe")?;
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
395 assert_eq!(prefix.get_nybble(0), 13);
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
396 assert_eq!(prefix.get_nybble(7), 9);
44182
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
397 Ok(())
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44143
diff changeset
398 }
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44187
diff changeset
399
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44187
diff changeset
400 #[test]
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44187
diff changeset
401 fn test_first_different_nybble_even_prefix() {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44187
diff changeset
402 let prefix = NodePrefix::from_hex("12ca").unwrap();
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44187
diff changeset
403 let mut node = Node::from([0; NODE_BYTES_LENGTH]);
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
404 assert_eq!(prefix.first_different_nybble(&node), Some(0));
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44187
diff changeset
405 node.data[0] = 0x13;
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
406 assert_eq!(prefix.first_different_nybble(&node), Some(1));
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44187
diff changeset
407 node.data[0] = 0x12;
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
408 assert_eq!(prefix.first_different_nybble(&node), Some(2));
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44187
diff changeset
409 node.data[1] = 0xca;
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44187
diff changeset
410 // now it is a prefix
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
411 assert_eq!(prefix.first_different_nybble(&node), None);
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44187
diff changeset
412 }
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44187
diff changeset
413
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44187
diff changeset
414 #[test]
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44187
diff changeset
415 fn test_first_different_nybble_odd_prefix() {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44187
diff changeset
416 let prefix = NodePrefix::from_hex("12c").unwrap();
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44187
diff changeset
417 let mut node = Node::from([0; NODE_BYTES_LENGTH]);
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
418 assert_eq!(prefix.first_different_nybble(&node), Some(0));
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44187
diff changeset
419 node.data[0] = 0x13;
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
420 assert_eq!(prefix.first_different_nybble(&node), Some(1));
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44187
diff changeset
421 node.data[0] = 0x12;
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
422 assert_eq!(prefix.first_different_nybble(&node), Some(2));
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44187
diff changeset
423 node.data[1] = 0xca;
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44187
diff changeset
424 // now it is a prefix
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46429
diff changeset
425 assert_eq!(prefix.first_different_nybble(&node), None);
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44187
diff changeset
426 }
44143
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
427 }
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44182
diff changeset
428
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44182
diff changeset
429 #[cfg(test)]
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44182
diff changeset
430 pub use tests::hex_pad_right;