Mercurial > public > mercurial-scm > hg
annotate rust/hg-core/src/revlog/node.rs @ 44183:e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
We're defining here only a small part of the immutable
methods it will have at the end. This is so we can
focus in the following changesets on the needed abstractions
for a mutable append-only serializable version.
The first implementor exposes the actual lookup
algorithm in its simplest form. It will have to be expanded
to account for the missing methods, and the special cases
related to NULL_NODE.
Differential Revision: https://phab.mercurial-scm.org/D7791
author | Georges Racinet <georges.racinet@octobus.net> |
---|---|
date | Thu, 23 Jan 2020 17:18:13 +0100 |
parents | 9896a8d0d3d2 |
children | be52b7372ec2 |
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 |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
11 use hex::{self, FromHex, FromHexError}; |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
12 |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
13 /// 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
|
14 /// |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
15 /// 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
|
16 /// 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
|
17 /// 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
|
18 /// the future. |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
19 const NODE_BYTES_LENGTH: usize = 20; |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
20 |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
21 /// 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
|
22 /// |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
23 /// 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
|
24 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
|
25 |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
26 /// 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
|
27 type NodeData = [u8; NODE_BYTES_LENGTH]; |
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 /// Binary revision SHA |
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 /// ## Future changes of hash size |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
32 /// |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
33 /// 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
|
34 /// 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
|
35 /// 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
|
36 /// |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
37 /// 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
|
38 /// 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
|
39 /// if they need a loop boundary. |
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 /// All methods that create a `Node` either take a type that enforces |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
42 /// the size or fail immediately at runtime with [`ExactLengthRequired`]. |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
43 /// |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
44 /// [`nybbles_len`]: #method.nybbles_len |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
45 /// [`ExactLengthRequired`]: struct.NodeError#variant.ExactLengthRequired |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
46 #[derive(Clone, Debug, PartialEq)] |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
47 pub struct Node { |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
48 data: NodeData, |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
49 } |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
50 |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
51 /// The node value for NULL_REVISION |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
52 pub const NULL_NODE: Node = Node { |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
53 data: [0; NODE_BYTES_LENGTH], |
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 |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
56 impl From<NodeData> for Node { |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
57 fn from(data: NodeData) -> Node { |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
58 Node { data } |
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 } |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
61 |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
62 #[derive(Debug, PartialEq)] |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
63 pub enum NodeError { |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
64 ExactLengthRequired(usize, String), |
44182
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
65 PrefixTooLong(String), |
44143
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
66 HexError(FromHexError, String), |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
67 } |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
68 |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
69 /// 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
|
70 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
|
71 if i % 2 == 0 { |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
72 s[i / 2] >> 4 |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
73 } else { |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
74 s[i / 2] & 0x0f |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
75 } |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
76 } |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
77 |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
78 impl Node { |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
79 /// 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
|
80 /// |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
81 /// 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
|
82 /// 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
|
83 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
|
84 get_nybble(&self.data, i) |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
85 } |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
86 |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
87 /// Length of the data, in nybbles |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
88 pub fn nybbles_len(&self) -> usize { |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
89 // 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
|
90 // 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
|
91 NODE_NYBBLES_LENGTH |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
92 } |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
93 |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
94 /// Convert from hexadecimal string representation |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
95 /// |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
96 /// Exact length is required. |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
97 /// |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
98 /// 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
|
99 /// changes of hash format. |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
100 pub fn from_hex(hex: &str) -> Result<Node, NodeError> { |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
101 Ok(NodeData::from_hex(hex) |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
102 .map_err(|e| NodeError::from((e, hex)))? |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
103 .into()) |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
104 } |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
105 |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
106 /// Convert to hexadecimal string representation |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
107 /// |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
108 /// 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
|
109 /// changes of hash format. |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
110 pub fn encode_hex(&self) -> String { |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
111 hex::encode(self.data) |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
112 } |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
113 |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
114 /// Provide access to binary data |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
115 /// |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
116 /// 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
|
117 /// binary values to Python. |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
118 pub fn as_bytes(&self) -> &[u8] { |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
119 &self.data |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
120 } |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
121 } |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
122 |
44182
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
123 impl<T: AsRef<str>> From<(FromHexError, T)> for NodeError { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
124 fn from(err_offender: (FromHexError, T)) -> Self { |
44143
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
125 let (err, offender) = err_offender; |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
126 match err { |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
127 FromHexError::InvalidStringLength => { |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
128 NodeError::ExactLengthRequired( |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
129 NODE_NYBBLES_LENGTH, |
44182
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
130 offender.as_ref().to_owned(), |
44143
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
131 ) |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
132 } |
44182
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
133 _ => NodeError::HexError(err, offender.as_ref().to_owned()), |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
134 } |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
135 } |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
136 } |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
137 |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
138 /// The beginning of a binary revision SHA. |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
139 /// |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
140 /// 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
|
141 /// 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
|
142 /// or not. |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
143 #[derive(Debug, PartialEq)] |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
144 pub struct NodePrefix { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
145 buf: Vec<u8>, |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
146 is_odd: bool, |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
147 } |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
148 |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
149 impl NodePrefix { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
150 /// Convert from hexadecimal string representation |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
151 /// |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
152 /// 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
|
153 /// (`String`, `&str`) as well as bytes. |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
154 /// |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
155 /// 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
|
156 /// changes of hash format. |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
157 pub fn from_hex(hex: impl AsRef<[u8]>) -> Result<Self, NodeError> { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
158 let hex = hex.as_ref(); |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
159 let len = hex.len(); |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
160 if len > NODE_NYBBLES_LENGTH { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
161 return Err(NodeError::PrefixTooLong( |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
162 String::from_utf8_lossy(hex).to_owned().to_string(), |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
163 )); |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
164 } |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
165 |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
166 let is_odd = len % 2 == 1; |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
167 let even_part = if is_odd { &hex[..len - 1] } else { hex }; |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
168 let mut buf: Vec<u8> = Vec::from_hex(&even_part) |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
169 .map_err(|e| (e, String::from_utf8_lossy(hex)))?; |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
170 |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
171 if is_odd { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
172 let latest_char = char::from(hex[len - 1]); |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
173 let latest_nybble = latest_char.to_digit(16).ok_or_else(|| { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
174 ( |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
175 FromHexError::InvalidHexCharacter { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
176 c: latest_char, |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
177 index: len - 1, |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
178 }, |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
179 String::from_utf8_lossy(hex), |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
180 ) |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
181 })? as u8; |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
182 buf.push(latest_nybble << 4); |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
183 } |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
184 Ok(NodePrefix { buf, is_odd }) |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
185 } |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
186 |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
187 pub fn borrow(&self) -> NodePrefixRef { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
188 NodePrefixRef { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
189 buf: &self.buf, |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
190 is_odd: self.is_odd, |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
191 } |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
192 } |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
193 } |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
194 |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
195 #[derive(Clone, Debug, PartialEq)] |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
196 pub struct NodePrefixRef<'a> { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
197 buf: &'a [u8], |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
198 is_odd: bool, |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
199 } |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
200 |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
201 impl<'a> NodePrefixRef<'a> { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
202 pub fn len(&self) -> usize { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
203 if self.is_odd { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
204 self.buf.len() * 2 - 1 |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
205 } else { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
206 self.buf.len() * 2 |
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 |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
210 pub fn is_prefix_of(&self, node: &Node) -> bool { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
211 if self.is_odd { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
212 let buf = self.buf; |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
213 let last_pos = buf.len() - 1; |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
214 node.data.starts_with(buf.split_at(last_pos).0) |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
215 && node.data[last_pos] >> 4 == buf[last_pos] >> 4 |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
216 } else { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
217 node.data.starts_with(self.buf) |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
218 } |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
219 } |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
220 |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
221 /// 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
|
222 /// |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
223 /// 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
|
224 /// 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
|
225 pub fn get_nybble(&self, i: usize) -> u8 { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
226 get_nybble(self.buf, i) |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
227 } |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
228 } |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
229 |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
230 /// A shortcut for full `Node` references |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
231 impl<'a> From<&'a Node> for NodePrefixRef<'a> { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
232 fn from(node: &'a Node) -> Self { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
233 NodePrefixRef { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
234 buf: &node.data, |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
235 is_odd: false, |
44143
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
236 } |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
237 } |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
238 } |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
239 |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
240 #[cfg(test)] |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
241 mod tests { |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
242 use super::*; |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
243 |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
244 fn sample_node() -> Node { |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
245 let mut data = [0; NODE_BYTES_LENGTH]; |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
246 data.copy_from_slice(&[ |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
247 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
|
248 0x98, 0x76, 0x54, 0x32, 0x10, 0xde, 0xad, 0xbe, 0xef, |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
249 ]); |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
250 data.into() |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
251 } |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
252 |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
253 /// Pad an hexadecimal string to reach `NODE_NYBBLES_LENGTH` |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
254 /// |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
255 /// 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
|
256 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
|
257 let mut res = hex.to_string(); |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
258 while res.len() < NODE_NYBBLES_LENGTH { |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
259 res.push('0'); |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
260 } |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
261 res |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
262 } |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
263 |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
264 fn sample_node_hex() -> String { |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
265 hex_pad_right("0123456789abcdeffedcba9876543210deadbeef") |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
266 } |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
267 |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
268 #[test] |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
269 fn test_node_from_hex() { |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
270 assert_eq!(Node::from_hex(&sample_node_hex()), Ok(sample_node())); |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
271 |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
272 let mut short = hex_pad_right("0123"); |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
273 short.pop(); |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
274 short.pop(); |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
275 assert_eq!( |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
276 Node::from_hex(&short), |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
277 Err(NodeError::ExactLengthRequired(NODE_NYBBLES_LENGTH, short)), |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
278 ); |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
279 |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
280 let not_hex = hex_pad_right("012... oops"); |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
281 assert_eq!( |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
282 Node::from_hex(¬_hex), |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
283 Err(NodeError::HexError( |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
284 FromHexError::InvalidHexCharacter { c: '.', index: 3 }, |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
285 not_hex, |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
286 )), |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
287 ); |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
288 } |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
289 |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
290 #[test] |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
291 fn test_node_encode_hex() { |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
292 assert_eq!(sample_node().encode_hex(), sample_node_hex()); |
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
293 } |
44182
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
294 |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
295 #[test] |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
296 fn test_prefix_from_hex() -> Result<(), NodeError> { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
297 assert_eq!( |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
298 NodePrefix::from_hex("0e1")?, |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
299 NodePrefix { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
300 buf: vec![14, 16], |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
301 is_odd: true |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
302 } |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
303 ); |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
304 assert_eq!( |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
305 NodePrefix::from_hex("0e1a")?, |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
306 NodePrefix { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
307 buf: vec![14, 26], |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
308 is_odd: false |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
309 } |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
310 ); |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
311 |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
312 // checking limit case |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
313 let node_as_vec = sample_node().data.iter().cloned().collect(); |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
314 assert_eq!( |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
315 NodePrefix::from_hex(sample_node_hex())?, |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
316 NodePrefix { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
317 buf: node_as_vec, |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
318 is_odd: false |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
319 } |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
320 ); |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
321 |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
322 Ok(()) |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
323 } |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
324 |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
325 #[test] |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
326 fn test_prefix_from_hex_errors() { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
327 assert_eq!( |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
328 NodePrefix::from_hex("testgr"), |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
329 Err(NodeError::HexError( |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
330 FromHexError::InvalidHexCharacter { c: 't', index: 0 }, |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
331 "testgr".to_string() |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
332 )) |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
333 ); |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
334 let mut long = NULL_NODE.encode_hex(); |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
335 long.push('c'); |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
336 match NodePrefix::from_hex(&long) |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
337 .expect_err("should be refused as too long") |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
338 { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
339 NodeError::PrefixTooLong(s) => assert_eq!(s, long), |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
340 err => panic!(format!("Should have been TooLong, got {:?}", err)), |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
341 } |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
342 } |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
343 |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
344 #[test] |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
345 fn test_is_prefix_of() -> Result<(), NodeError> { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
346 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
|
347 node_data[0] = 0x12; |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
348 node_data[1] = 0xca; |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
349 let node = Node::from(node_data); |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
350 assert!(NodePrefix::from_hex("12")?.borrow().is_prefix_of(&node)); |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
351 assert!(!NodePrefix::from_hex("1a")?.borrow().is_prefix_of(&node)); |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
352 assert!(NodePrefix::from_hex("12c")?.borrow().is_prefix_of(&node)); |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
353 assert!(!NodePrefix::from_hex("12d")?.borrow().is_prefix_of(&node)); |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
354 Ok(()) |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
355 } |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
356 |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
357 #[test] |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
358 fn test_get_nybble() -> Result<(), NodeError> { |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
359 let prefix = NodePrefix::from_hex("dead6789cafe")?; |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
360 assert_eq!(prefix.borrow().get_nybble(0), 13); |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
361 assert_eq!(prefix.borrow().get_nybble(7), 9); |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
362 Ok(()) |
9896a8d0d3d2
rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents:
44143
diff
changeset
|
363 } |
44143
7f86426fdd2c
rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
364 } |
44183
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44182
diff
changeset
|
365 |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44182
diff
changeset
|
366 #[cfg(test)] |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44182
diff
changeset
|
367 pub use tests::hex_pad_right; |