annotate rust/hg-core/src/revlog/nodemap.rs @ 44832:ad1ec40975aa

rust-regex: fix issues with regex anchoring and performance It turns out that the way I tried to work around `regex`'s behavior difference with `re2` and Python's `re` was 1) buggy and 2) much more complicated than needed. In a few words: `regex` adds `.*` on either side of patterns when no start or end anchor is present. My previous workaround put `^` or `$` for every pattern, which is wrong even without the other 2 bugs on top of it. Using `^(?:<patterns>)` right at the end of the `regex` path fixes the issue. I've opened an issue to get a build option instead: https://github.com/rust-lang/regex/issues/675 Differential Revision: https://phab.mercurial-scm.org/D8506
author Rapha?l Gom?s <rgomes@octobus.net>
date Thu, 07 May 2020 23:52:08 +0200
parents d518994384a4
children 26114bd6ec60
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
44142
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
1 // Copyright 2018-2020 Georges Racinet <georges.racinet@octobus.net>
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
2 // and Mercurial contributors
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
3 //
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
4 // This software may be used and distributed according to the terms of the
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
5 // GNU General Public License version 2 or any later version.
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
6 //! Indexing facilities for fast retrieval of `Revision` from `Node`
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
7 //!
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
8 //! This provides a variation on the 16-ary radix tree that is
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
9 //! provided as "nodetree" in revlog.c, ready for append-only persistence
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
10 //! on disk.
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
11 //!
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
12 //! Following existing implicit conventions, the "nodemap" terminology
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
13 //! is used in a more abstract context.
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
14
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
15 use super::{
44387
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
16 node::NULL_NODE, Node, NodeError, NodePrefix, NodePrefixRef, Revision,
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
17 RevlogIndex, NULL_REVISION,
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
18 };
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
19
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
20 use std::cmp::max;
44142
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
21 use std::fmt;
44385
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
22 use std::mem;
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
23 use std::ops::Deref;
44184
220d4d2e3185 rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents: 44183
diff changeset
24 use std::ops::Index;
44385
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
25 use std::slice;
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
26
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
27 #[derive(Debug, PartialEq)]
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
28 pub enum NodeMapError {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
29 MultipleResults,
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
30 InvalidNodePrefix(NodeError),
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
31 /// A `Revision` stored in the nodemap could not be found in the index
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
32 RevisionNotInIndex(Revision),
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
33 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
34
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
35 impl From<NodeError> for NodeMapError {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
36 fn from(err: NodeError) -> Self {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
37 NodeMapError::InvalidNodePrefix(err)
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
38 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
39 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
40
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
41 /// Mapping system from Mercurial nodes to revision numbers.
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
42 ///
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
43 /// ## `RevlogIndex` and `NodeMap`
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
44 ///
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
45 /// One way to think about their relationship is that
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
46 /// the `NodeMap` is a prefix-oriented reverse index of the `Node` information
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
47 /// carried by a [`RevlogIndex`].
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
48 ///
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
49 /// Many of the methods in this trait take a `RevlogIndex` argument
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
50 /// which is used for validation of their results. This index must naturally
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
51 /// be the one the `NodeMap` is about, and it must be consistent.
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
52 ///
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
53 /// Notably, the `NodeMap` must not store
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
54 /// information about more `Revision` values than there are in the index.
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
55 /// In these methods, an encountered `Revision` is not in the index, a
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
56 /// [`RevisionNotInIndex`] error is returned.
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
57 ///
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
58 /// In insert operations, the rule is thus that the `NodeMap` must always
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
59 /// be updated after the `RevlogIndex`
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
60 /// be updated first, and the `NodeMap` second.
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
61 ///
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
62 /// [`RevisionNotInIndex`]: enum.NodeMapError.html#variant.RevisionNotInIndex
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
63 /// [`RevlogIndex`]: ../trait.RevlogIndex.html
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
64 pub trait NodeMap {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
65 /// Find the unique `Revision` having the given `Node`
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
66 ///
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
67 /// If no Revision matches the given `Node`, `Ok(None)` is returned.
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
68 fn find_node(
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
69 &self,
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
70 index: &impl RevlogIndex,
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
71 node: &Node,
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
72 ) -> Result<Option<Revision>, NodeMapError> {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
73 self.find_bin(index, node.into())
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
74 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
75
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
76 /// Find the unique Revision whose `Node` starts with a given binary prefix
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
77 ///
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
78 /// If no Revision matches the given prefix, `Ok(None)` is returned.
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
79 ///
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
80 /// If several Revisions match the given prefix, a [`MultipleResults`]
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
81 /// error is returned.
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
82 fn find_bin<'a>(
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
83 &self,
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
84 idx: &impl RevlogIndex,
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
85 prefix: NodePrefixRef<'a>,
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
86 ) -> Result<Option<Revision>, NodeMapError>;
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
87
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
88 /// Find the unique Revision whose `Node` hexadecimal string representation
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
89 /// starts with a given prefix
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
90 ///
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
91 /// If no Revision matches the given prefix, `Ok(None)` is returned.
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
92 ///
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
93 /// If several Revisions match the given prefix, a [`MultipleResults`]
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
94 /// error is returned.
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
95 fn find_hex(
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
96 &self,
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
97 idx: &impl RevlogIndex,
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
98 prefix: &str,
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
99 ) -> Result<Option<Revision>, NodeMapError> {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
100 self.find_bin(idx, NodePrefix::from_hex(prefix)?.borrow())
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
101 }
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
102
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
103 /// Give the size of the shortest node prefix that determines
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
104 /// the revision uniquely.
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
105 ///
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
106 /// From a binary node prefix, if it is matched in the node map, this
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
107 /// returns the number of hexadecimal digits that would had sufficed
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
108 /// to find the revision uniquely.
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
109 ///
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
110 /// Returns `None` if no `Revision` could be found for the prefix.
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
111 ///
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
112 /// If several Revisions match the given prefix, a [`MultipleResults`]
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
113 /// error is returned.
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
114 fn unique_prefix_len_bin<'a>(
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
115 &self,
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
116 idx: &impl RevlogIndex,
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
117 node_prefix: NodePrefixRef<'a>,
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
118 ) -> Result<Option<usize>, NodeMapError>;
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
119
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
120 /// Same as `unique_prefix_len_bin`, with the hexadecimal representation
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
121 /// of the prefix as input.
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
122 fn unique_prefix_len_hex(
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
123 &self,
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
124 idx: &impl RevlogIndex,
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
125 prefix: &str,
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
126 ) -> Result<Option<usize>, NodeMapError> {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
127 self.unique_prefix_len_bin(idx, NodePrefix::from_hex(prefix)?.borrow())
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
128 }
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
129
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
130 /// Same as `unique_prefix_len_bin`, with a full `Node` as input
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
131 fn unique_prefix_len_node(
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
132 &self,
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
133 idx: &impl RevlogIndex,
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
134 node: &Node,
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
135 ) -> Result<Option<usize>, NodeMapError> {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
136 self.unique_prefix_len_bin(idx, node.into())
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
137 }
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
138 }
44142
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
139
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
140 pub trait MutableNodeMap: NodeMap {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
141 fn insert<I: RevlogIndex>(
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
142 &mut self,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
143 index: &I,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
144 node: &Node,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
145 rev: Revision,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
146 ) -> Result<(), NodeMapError>;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
147 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
148
44142
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
149 /// Low level NodeTree [`Blocks`] elements
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
150 ///
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
151 /// These are exactly as for instance on persistent storage.
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
152 type RawElement = i32;
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
153
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
154 /// High level representation of values in NodeTree
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
155 /// [`Blocks`](struct.Block.html)
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
156 ///
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
157 /// This is the high level representation that most algorithms should
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
158 /// use.
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
159 #[derive(Clone, Debug, Eq, PartialEq)]
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
160 enum Element {
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
161 Rev(Revision),
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
162 Block(usize),
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
163 None,
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
164 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
165
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
166 impl From<RawElement> for Element {
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
167 /// Conversion from low level representation, after endianness conversion.
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
168 ///
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
169 /// See [`Block`](struct.Block.html) for explanation about the encoding.
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
170 fn from(raw: RawElement) -> Element {
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
171 if raw >= 0 {
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
172 Element::Block(raw as usize)
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
173 } else if raw == -1 {
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
174 Element::None
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
175 } else {
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
176 Element::Rev(-raw - 2)
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
177 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
178 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
179 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
180
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
181 impl From<Element> for RawElement {
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
182 fn from(element: Element) -> RawElement {
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
183 match element {
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
184 Element::None => 0,
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
185 Element::Block(i) => i as RawElement,
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
186 Element::Rev(rev) => -rev - 2,
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
187 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
188 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
189 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
190
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
191 /// A logical block of the `NodeTree`, packed with a fixed size.
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
192 ///
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
193 /// These are always used in container types implementing `Index<Block>`,
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
194 /// such as `&Block`
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
195 ///
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
196 /// As an array of integers, its ith element encodes that the
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
197 /// ith potential edge from the block, representing the ith hexadecimal digit
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
198 /// (nybble) `i` is either:
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
199 ///
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
200 /// - absent (value -1)
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
201 /// - another `Block` in the same indexable container (value ≥ 0)
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
202 /// - a `Revision` leaf (value ≤ -2)
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
203 ///
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
204 /// Endianness has to be fixed for consistency on shared storage across
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
205 /// different architectures.
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
206 ///
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
207 /// A key difference with the C `nodetree` is that we need to be
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
208 /// able to represent the [`Block`] at index 0, hence -1 is the empty marker
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
209 /// rather than 0 and the `Revision` range upper limit of -2 instead of -1.
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
210 ///
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
211 /// Another related difference is that `NULL_REVISION` (-1) is not
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
212 /// represented at all, because we want an immutable empty nodetree
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
213 /// to be valid.
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
214
44385
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
215 #[derive(Copy, Clone)]
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
216 pub struct Block([u8; BLOCK_SIZE]);
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
217
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
218 /// Not derivable for arrays of length >32 until const generics are stable
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
219 impl PartialEq for Block {
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
220 fn eq(&self, other: &Self) -> bool {
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
221 &self.0[..] == &other.0[..]
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
222 }
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
223 }
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
224
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
225 pub const BLOCK_SIZE: usize = 64;
44142
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
226
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
227 impl Block {
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
228 fn new() -> Self {
44385
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
229 // -1 in 2's complement to create an absent node
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
230 let byte: u8 = 255;
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
231 Block([byte; BLOCK_SIZE])
44142
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
232 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
233
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
234 fn get(&self, nybble: u8) -> Element {
44385
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
235 let index = nybble as usize * mem::size_of::<RawElement>();
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
236 Element::from(RawElement::from_be_bytes([
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
237 self.0[index],
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
238 self.0[index + 1],
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
239 self.0[index + 2],
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
240 self.0[index + 3],
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
241 ]))
44142
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
242 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
243
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
244 fn set(&mut self, nybble: u8, element: Element) {
44385
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
245 let values = RawElement::to_be_bytes(element.into());
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
246 let index = nybble as usize * mem::size_of::<RawElement>();
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
247 self.0[index] = values[0];
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
248 self.0[index + 1] = values[1];
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
249 self.0[index + 2] = values[2];
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
250 self.0[index + 3] = values[3];
44142
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
251 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
252 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
253
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
254 impl fmt::Debug for Block {
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
255 /// sparse representation for testing and debugging purposes
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
256 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
257 f.debug_map()
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
258 .entries((0..16).filter_map(|i| match self.get(i) {
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
259 Element::None => None,
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
260 element => Some((i, element)),
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
261 }))
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
262 .finish()
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
263 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
264 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
265
44185
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
266 /// A mutable 16-radix tree with the root block logically at the end
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
267 ///
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
268 /// Because of the append only nature of our node trees, we need to
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
269 /// keep the original untouched and store new blocks separately.
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
270 ///
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
271 /// The mutable root `Block` is kept apart so that we don't have to rebump
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
272 /// it on each insertion.
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
273 pub struct NodeTree {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
274 readonly: Box<dyn Deref<Target = [Block]> + Send>,
44185
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
275 growable: Vec<Block>,
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
276 root: Block,
44389
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
277 masked_inner_blocks: usize,
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
278 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
279
44184
220d4d2e3185 rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents: 44183
diff changeset
280 impl Index<usize> for NodeTree {
220d4d2e3185 rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents: 44183
diff changeset
281 type Output = Block;
220d4d2e3185 rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents: 44183
diff changeset
282
220d4d2e3185 rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents: 44183
diff changeset
283 fn index(&self, i: usize) -> &Block {
44185
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
284 let ro_len = self.readonly.len();
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
285 if i < ro_len {
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
286 &self.readonly[i]
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
287 } else if i == ro_len + self.growable.len() {
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
288 &self.root
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
289 } else {
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
290 &self.growable[i - ro_len]
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
291 }
44184
220d4d2e3185 rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents: 44183
diff changeset
292 }
220d4d2e3185 rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents: 44183
diff changeset
293 }
220d4d2e3185 rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents: 44183
diff changeset
294
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
295 /// Return `None` unless the `Node` for `rev` has given prefix in `index`.
44385
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
296 fn has_prefix_or_none(
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
297 idx: &impl RevlogIndex,
44385
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
298 prefix: NodePrefixRef,
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
299 rev: Revision,
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
300 ) -> Result<Option<Revision>, NodeMapError> {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
301 idx.node(rev)
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
302 .ok_or_else(|| NodeMapError::RevisionNotInIndex(rev))
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
303 .map(|node| {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
304 if prefix.is_prefix_of(node) {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
305 Some(rev)
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
306 } else {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
307 None
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
308 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
309 })
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
310 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
311
44387
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
312 /// validate that the candidate's node starts indeed with given prefix,
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
313 /// and treat ambiguities related to `NULL_REVISION`.
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
314 ///
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
315 /// From the data in the NodeTree, one can only conclude that some
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
316 /// revision is the only one for a *subprefix* of the one being looked up.
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
317 fn validate_candidate(
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
318 idx: &impl RevlogIndex,
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
319 prefix: NodePrefixRef,
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
320 candidate: (Option<Revision>, usize),
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
321 ) -> Result<(Option<Revision>, usize), NodeMapError> {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
322 let (rev, steps) = candidate;
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
323 if let Some(nz_nybble) = prefix.first_different_nybble(&NULL_NODE) {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
324 rev.map_or(Ok((None, steps)), |r| {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
325 has_prefix_or_none(idx, prefix, r)
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
326 .map(|opt| (opt, max(steps, nz_nybble + 1)))
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
327 })
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
328 } else {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
329 // the prefix is only made of zeros; NULL_REVISION always matches it
44387
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
330 // and any other *valid* result is an ambiguity
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
331 match rev {
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
332 None => Ok((Some(NULL_REVISION), steps + 1)),
44387
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
333 Some(r) => match has_prefix_or_none(idx, prefix, r)? {
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
334 None => Ok((Some(NULL_REVISION), steps + 1)),
44387
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
335 _ => Err(NodeMapError::MultipleResults),
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
336 },
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
337 }
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
338 }
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
339 }
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
340
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
341 impl NodeTree {
44185
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
342 /// Initiate a NodeTree from an immutable slice-like of `Block`
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
343 ///
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
344 /// We keep `readonly` and clone its root block if it isn't empty.
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
345 fn new(readonly: Box<dyn Deref<Target = [Block]> + Send>) -> Self {
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
346 let root = readonly
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
347 .last()
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
348 .map(|b| b.clone())
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
349 .unwrap_or_else(|| Block::new());
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
350 NodeTree {
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
351 readonly: readonly,
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
352 growable: Vec::new(),
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
353 root: root,
44389
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
354 masked_inner_blocks: 0,
44185
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
355 }
44184
220d4d2e3185 rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents: 44183
diff changeset
356 }
220d4d2e3185 rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents: 44183
diff changeset
357
44385
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
358 /// Create from an opaque bunch of bytes
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
359 ///
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
360 /// The created `NodeTreeBytes` from `buffer`,
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
361 /// of which exactly `amount` bytes are used.
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
362 ///
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
363 /// - `buffer` could be derived from `PyBuffer` and `Mmap` objects.
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
364 /// - `offset` allows for the final file format to include fixed data
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
365 /// (generation number, behavioural flags)
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
366 /// - `amount` is expressed in bytes, and is not automatically derived from
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
367 /// `bytes`, so that a caller that manages them atomically can perform
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
368 /// temporary disk serializations and still rollback easily if needed.
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
369 /// First use-case for this would be to support Mercurial shell hooks.
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
370 ///
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
371 /// panics if `buffer` is smaller than `amount`
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
372 pub fn load_bytes(
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
373 bytes: Box<dyn Deref<Target = [u8]> + Send>,
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
374 amount: usize,
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
375 ) -> Self {
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
376 NodeTree::new(Box::new(NodeTreeBytes::new(bytes, amount)))
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
377 }
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
378
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
379 /// Retrieve added `Block` and the original immutable data
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
380 pub fn into_readonly_and_added(
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
381 self,
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
382 ) -> (Box<dyn Deref<Target = [Block]> + Send>, Vec<Block>) {
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
383 let mut vec = self.growable;
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
384 let readonly = self.readonly;
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
385 if readonly.last() != Some(&self.root) {
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
386 vec.push(self.root);
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
387 }
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
388 (readonly, vec)
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
389 }
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
390
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
391 /// Retrieve added `Blocks` as bytes, ready to be written to persistent
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
392 /// storage
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
393 pub fn into_readonly_and_added_bytes(
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
394 self,
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
395 ) -> (Box<dyn Deref<Target = [Block]> + Send>, Vec<u8>) {
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
396 let (readonly, vec) = self.into_readonly_and_added();
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
397 // Prevent running `v`'s destructor so we are in complete control
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
398 // of the allocation.
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
399 let vec = mem::ManuallyDrop::new(vec);
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
400
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
401 // Transmute the `Vec<Block>` to a `Vec<u8>`. Blocks are contiguous
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
402 // bytes, so this is perfectly safe.
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
403 let bytes = unsafe {
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
404 // Assert that `Block` hasn't been changed and has no padding
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
405 let _: [u8; 4 * BLOCK_SIZE] =
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
406 std::mem::transmute([Block::new(); 4]);
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
407
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
408 // /!\ Any use of `vec` after this is use-after-free.
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
409 // TODO: use `into_raw_parts` once stabilized
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
410 Vec::from_raw_parts(
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
411 vec.as_ptr() as *mut u8,
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
412 vec.len() * BLOCK_SIZE,
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
413 vec.capacity() * BLOCK_SIZE,
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
414 )
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
415 };
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
416 (readonly, bytes)
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
417 }
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
418
44185
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
419 /// Total number of blocks
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
420 fn len(&self) -> usize {
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
421 self.readonly.len() + self.growable.len() + 1
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
422 }
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
423
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
424 /// Implemented for completeness
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
425 ///
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
426 /// A `NodeTree` always has at least the mutable root block.
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
427 #[allow(dead_code)]
44184
220d4d2e3185 rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents: 44183
diff changeset
428 fn is_empty(&self) -> bool {
44185
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
429 false
44184
220d4d2e3185 rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents: 44183
diff changeset
430 }
220d4d2e3185 rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents: 44183
diff changeset
431
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
432 /// Main working method for `NodeTree` searches
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
433 ///
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
434 /// The first returned value is the result of analysing `NodeTree` data
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
435 /// *alone*: whereas `None` guarantees that the given prefix is absent
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
436 /// from the `NodeTree` data (but still could match `NULL_NODE`), with
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
437 /// `Some(rev)`, it is to be understood that `rev` is the unique `Revision`
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
438 /// that could match the prefix. Actually, all that can be inferred from
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
439 /// the `NodeTree` data is that `rev` is the revision with the longest
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
440 /// common node prefix with the given prefix.
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
441 ///
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
442 /// The second returned value is the size of the smallest subprefix
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
443 /// of `prefix` that would give the same result, i.e. not the
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
444 /// `MultipleResults` error variant (again, using only the data of the
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
445 /// `NodeTree`).
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
446 fn lookup(
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
447 &self,
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
448 prefix: NodePrefixRef,
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
449 ) -> Result<(Option<Revision>, usize), NodeMapError> {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
450 for (i, visit_item) in self.visit(prefix).enumerate() {
44186
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
451 if let Some(opt) = visit_item.final_revision() {
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
452 return Ok((opt, i + 1));
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
453 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
454 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
455 Err(NodeMapError::MultipleResults)
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
456 }
44186
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
457
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
458 fn visit<'n, 'p>(
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
459 &'n self,
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
460 prefix: NodePrefixRef<'p>,
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
461 ) -> NodeTreeVisitor<'n, 'p> {
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
462 NodeTreeVisitor {
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
463 nt: self,
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
464 prefix: prefix,
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
465 visit: self.len() - 1,
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
466 nybble_idx: 0,
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
467 done: false,
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
468 }
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
469 }
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
470 /// Return a mutable reference for `Block` at index `idx`.
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
471 ///
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
472 /// If `idx` lies in the immutable area, then the reference is to
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
473 /// a newly appended copy.
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
474 ///
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
475 /// Returns (new_idx, glen, mut_ref) where
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
476 ///
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
477 /// - `new_idx` is the index of the mutable `Block`
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
478 /// - `mut_ref` is a mutable reference to the mutable Block.
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
479 /// - `glen` is the new length of `self.growable`
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
480 ///
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
481 /// Note: the caller wouldn't be allowed to query `self.growable.len()`
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
482 /// itself because of the mutable borrow taken with the returned `Block`
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
483 fn mutable_block(&mut self, idx: usize) -> (usize, &mut Block, usize) {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
484 let ro_blocks = &self.readonly;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
485 let ro_len = ro_blocks.len();
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
486 let glen = self.growable.len();
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
487 if idx < ro_len {
44389
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
488 self.masked_inner_blocks += 1;
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
489 // TODO OPTIM I think this makes two copies
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
490 self.growable.push(ro_blocks[idx].clone());
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
491 (glen + ro_len, &mut self.growable[glen], glen + 1)
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
492 } else if glen + ro_len == idx {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
493 (idx, &mut self.root, glen)
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
494 } else {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
495 (idx, &mut self.growable[idx - ro_len], glen)
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
496 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
497 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
498
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
499 /// Main insertion method
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
500 ///
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
501 /// This will dive in the node tree to find the deepest `Block` for
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
502 /// `node`, split it as much as needed and record `node` in there.
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
503 /// The method then backtracks, updating references in all the visited
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
504 /// blocks from the root.
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
505 ///
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
506 /// All the mutated `Block` are copied first to the growable part if
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
507 /// needed. That happens for those in the immutable part except the root.
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
508 pub fn insert<I: RevlogIndex>(
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
509 &mut self,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
510 index: &I,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
511 node: &Node,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
512 rev: Revision,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
513 ) -> Result<(), NodeMapError> {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
514 let ro_len = &self.readonly.len();
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
515
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
516 let mut visit_steps: Vec<_> = self.visit(node.into()).collect();
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
517 let read_nybbles = visit_steps.len();
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
518 // visit_steps cannot be empty, since we always visit the root block
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
519 let deepest = visit_steps.pop().unwrap();
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
520
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
521 let (mut block_idx, mut block, mut glen) =
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
522 self.mutable_block(deepest.block_idx);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
523
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
524 if let Element::Rev(old_rev) = deepest.element {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
525 let old_node = index
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
526 .node(old_rev)
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
527 .ok_or_else(|| NodeMapError::RevisionNotInIndex(old_rev))?;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
528 if old_node == node {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
529 return Ok(()); // avoid creating lots of useless blocks
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
530 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
531
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
532 // Looping over the tail of nybbles in both nodes, creating
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
533 // new blocks until we find the difference
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
534 let mut new_block_idx = ro_len + glen;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
535 let mut nybble = deepest.nybble;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
536 for nybble_pos in read_nybbles..node.nybbles_len() {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
537 block.set(nybble, Element::Block(new_block_idx));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
538
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
539 let new_nybble = node.get_nybble(nybble_pos);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
540 let old_nybble = old_node.get_nybble(nybble_pos);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
541
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
542 if old_nybble == new_nybble {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
543 self.growable.push(Block::new());
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
544 block = &mut self.growable[glen];
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
545 glen += 1;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
546 new_block_idx += 1;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
547 nybble = new_nybble;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
548 } else {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
549 let mut new_block = Block::new();
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
550 new_block.set(old_nybble, Element::Rev(old_rev));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
551 new_block.set(new_nybble, Element::Rev(rev));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
552 self.growable.push(new_block);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
553 break;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
554 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
555 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
556 } else {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
557 // Free slot in the deepest block: no splitting has to be done
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
558 block.set(deepest.nybble, Element::Rev(rev));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
559 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
560
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
561 // Backtrack over visit steps to update references
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
562 while let Some(visited) = visit_steps.pop() {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
563 let to_write = Element::Block(block_idx);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
564 if visit_steps.is_empty() {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
565 self.root.set(visited.nybble, to_write);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
566 break;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
567 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
568 let (new_idx, block, _) = self.mutable_block(visited.block_idx);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
569 if block.get(visited.nybble) == to_write {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
570 break;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
571 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
572 block.set(visited.nybble, to_write);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
573 block_idx = new_idx;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
574 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
575 Ok(())
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
576 }
44389
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
577
44390
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
578 /// Make the whole `NodeTree` logically empty, without touching the
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
579 /// immutable part.
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
580 pub fn invalidate_all(&mut self) {
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
581 self.root = Block::new();
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
582 self.growable = Vec::new();
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
583 self.masked_inner_blocks = self.readonly.len();
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
584 }
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
585
44389
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
586 /// Return the number of blocks in the readonly part that are currently
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
587 /// masked in the mutable part.
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
588 ///
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
589 /// The `NodeTree` structure has no efficient way to know how many blocks
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
590 /// are already unreachable in the readonly part.
44390
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
591 ///
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
592 /// After a call to `invalidate_all()`, the returned number can be actually
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
593 /// bigger than the whole readonly part, a conventional way to mean that
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
594 /// all the readonly blocks have been masked. This is what is really
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
595 /// useful to the caller and does not require to know how many were
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
596 /// actually unreachable to begin with.
44389
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
597 pub fn masked_readonly_blocks(&self) -> usize {
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
598 if let Some(readonly_root) = self.readonly.last() {
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
599 if readonly_root == &self.root {
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
600 return 0;
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
601 }
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
602 } else {
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
603 return 0;
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
604 }
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
605 self.masked_inner_blocks + 1
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
606 }
44186
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
607 }
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
608
44385
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
609 pub struct NodeTreeBytes {
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
610 buffer: Box<dyn Deref<Target = [u8]> + Send>,
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
611 len_in_blocks: usize,
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
612 }
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
613
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
614 impl NodeTreeBytes {
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
615 fn new(
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
616 buffer: Box<dyn Deref<Target = [u8]> + Send>,
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
617 amount: usize,
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
618 ) -> Self {
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
619 assert!(buffer.len() >= amount);
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
620 let len_in_blocks = amount / BLOCK_SIZE;
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
621 NodeTreeBytes {
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
622 buffer,
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
623 len_in_blocks,
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
624 }
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
625 }
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
626 }
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
627
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
628 impl Deref for NodeTreeBytes {
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
629 type Target = [Block];
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
630
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
631 fn deref(&self) -> &[Block] {
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
632 unsafe {
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
633 slice::from_raw_parts(
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
634 (&self.buffer).as_ptr() as *const Block,
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
635 self.len_in_blocks,
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
636 )
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
637 }
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
638 }
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
639 }
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
640
44186
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
641 struct NodeTreeVisitor<'n, 'p> {
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
642 nt: &'n NodeTree,
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
643 prefix: NodePrefixRef<'p>,
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
644 visit: usize,
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
645 nybble_idx: usize,
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
646 done: bool,
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
647 }
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
648
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
649 #[derive(Debug, PartialEq, Clone)]
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
650 struct NodeTreeVisitItem {
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
651 block_idx: usize,
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
652 nybble: u8,
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
653 element: Element,
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
654 }
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
655
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
656 impl<'n, 'p> Iterator for NodeTreeVisitor<'n, 'p> {
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
657 type Item = NodeTreeVisitItem;
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
658
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
659 fn next(&mut self) -> Option<Self::Item> {
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
660 if self.done || self.nybble_idx >= self.prefix.len() {
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
661 return None;
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
662 }
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
663
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
664 let nybble = self.prefix.get_nybble(self.nybble_idx);
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
665 self.nybble_idx += 1;
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
666
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
667 let visit = self.visit;
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
668 let element = self.nt[visit].get(nybble);
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
669 if let Element::Block(idx) = element {
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
670 self.visit = idx;
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
671 } else {
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
672 self.done = true;
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
673 }
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
674
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
675 Some(NodeTreeVisitItem {
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
676 block_idx: visit,
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
677 nybble: nybble,
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
678 element: element,
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
679 })
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
680 }
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
681 }
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
682
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
683 impl NodeTreeVisitItem {
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
684 // Return `Some(opt)` if this item is final, with `opt` being the
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
685 // `Revision` that it may represent.
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
686 //
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
687 // If the item is not terminal, return `None`
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
688 fn final_revision(&self) -> Option<Option<Revision>> {
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
689 match self.element {
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
690 Element::Block(_) => None,
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
691 Element::Rev(r) => Some(Some(r)),
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
692 Element::None => Some(None),
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
693 }
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
694 }
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
695 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
696
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
697 impl From<Vec<Block>> for NodeTree {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
698 fn from(vec: Vec<Block>) -> Self {
44185
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
699 Self::new(Box::new(vec))
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
700 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
701 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
702
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
703 impl fmt::Debug for NodeTree {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
704 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44185
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
705 let readonly: &[Block] = &*self.readonly;
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
706 write!(
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
707 f,
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
708 "readonly: {:?}, growable: {:?}, root: {:?}",
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
709 readonly, self.growable, self.root
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
710 )
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
711 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
712 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
713
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
714 impl Default for NodeTree {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
715 /// Create a fully mutable empty NodeTree
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
716 fn default() -> Self {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
717 NodeTree::new(Box::new(Vec::new()))
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
718 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
719 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
720
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
721 impl NodeMap for NodeTree {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
722 fn find_bin<'a>(
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
723 &self,
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
724 idx: &impl RevlogIndex,
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
725 prefix: NodePrefixRef<'a>,
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
726 ) -> Result<Option<Revision>, NodeMapError> {
44387
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
727 validate_candidate(idx, prefix.clone(), self.lookup(prefix)?)
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
728 .map(|(opt, _shortest)| opt)
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
729 }
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
730
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
731 fn unique_prefix_len_bin<'a>(
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
732 &self,
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
733 idx: &impl RevlogIndex,
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
734 prefix: NodePrefixRef<'a>,
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
735 ) -> Result<Option<usize>, NodeMapError> {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
736 validate_candidate(idx, prefix.clone(), self.lookup(prefix)?)
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
737 .map(|(opt, shortest)| opt.map(|_rev| shortest))
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
738 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
739 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
740
44142
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
741 #[cfg(test)]
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
742 mod tests {
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
743 use super::NodeMapError::*;
44142
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
744 use super::*;
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
745 use crate::revlog::node::{hex_pad_right, Node};
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
746 use std::collections::HashMap;
44142
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
747
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
748 /// Creates a `Block` using a syntax close to the `Debug` output
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
749 macro_rules! block {
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
750 {$($nybble:tt : $variant:ident($val:tt)),*} => (
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
751 {
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
752 let mut block = Block::new();
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
753 $(block.set($nybble, Element::$variant($val)));*;
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
754 block
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
755 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
756 )
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
757 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
758
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
759 #[test]
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
760 fn test_block_debug() {
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
761 let mut block = Block::new();
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
762 block.set(1, Element::Rev(3));
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
763 block.set(10, Element::Block(0));
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
764 assert_eq!(format!("{:?}", block), "{1: Rev(3), 10: Block(0)}");
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
765 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
766
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
767 #[test]
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
768 fn test_block_macro() {
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
769 let block = block! {5: Block(2)};
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
770 assert_eq!(format!("{:?}", block), "{5: Block(2)}");
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
771
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
772 let block = block! {13: Rev(15), 5: Block(2)};
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
773 assert_eq!(format!("{:?}", block), "{5: Block(2), 13: Rev(15)}");
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
774 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
775
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
776 #[test]
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
777 fn test_raw_block() {
44385
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
778 let mut raw = [255u8; 64];
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
779
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
780 let mut counter = 0;
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
781 for val in [0, 15, -2, -1, -3].iter() {
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
782 for byte in RawElement::to_be_bytes(*val).iter() {
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
783 raw[counter] = *byte;
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
784 counter += 1;
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
785 }
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
786 }
44142
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
787 let block = Block(raw);
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
788 assert_eq!(block.get(0), Element::Block(0));
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
789 assert_eq!(block.get(1), Element::Block(15));
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
790 assert_eq!(block.get(3), Element::None);
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
791 assert_eq!(block.get(2), Element::Rev(0));
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
792 assert_eq!(block.get(4), Element::Rev(1));
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
793 }
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
794
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
795 type TestIndex = HashMap<Revision, Node>;
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
796
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
797 impl RevlogIndex for TestIndex {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
798 fn node(&self, rev: Revision) -> Option<&Node> {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
799 self.get(&rev)
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
800 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
801
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
802 fn len(&self) -> usize {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
803 self.len()
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
804 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
805 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
806
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
807 /// Pad hexadecimal Node prefix with zeros on the right
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
808 ///
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
809 /// This avoids having to repeatedly write very long hexadecimal
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
810 /// strings for test data, and brings actual hash size independency.
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
811 #[cfg(test)]
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
812 fn pad_node(hex: &str) -> Node {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
813 Node::from_hex(&hex_pad_right(hex)).unwrap()
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
814 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
815
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
816 /// Pad hexadecimal Node prefix with zeros on the right, then insert
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
817 fn pad_insert(idx: &mut TestIndex, rev: Revision, hex: &str) {
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
818 idx.insert(rev, pad_node(hex));
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
819 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
820
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
821 fn sample_nodetree() -> NodeTree {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
822 NodeTree::from(vec![
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
823 block![0: Rev(9)],
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
824 block![0: Rev(0), 1: Rev(9)],
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
825 block![0: Block(1), 1:Rev(1)],
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
826 ])
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
827 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
828
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
829 #[test]
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
830 fn test_nt_debug() {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
831 let nt = sample_nodetree();
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
832 assert_eq!(
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
833 format!("{:?}", nt),
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
834 "readonly: \
44185
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
835 [{0: Rev(9)}, {0: Rev(0), 1: Rev(9)}, {0: Block(1), 1: Rev(1)}], \
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
836 growable: [], \
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
837 root: {0: Block(1), 1: Rev(1)}",
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
838 );
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
839 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
840
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
841 #[test]
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
842 fn test_immutable_find_simplest() -> Result<(), NodeMapError> {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
843 let mut idx: TestIndex = HashMap::new();
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
844 pad_insert(&mut idx, 1, "1234deadcafe");
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
845
44185
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
846 let nt = NodeTree::from(vec![block! {1: Rev(1)}]);
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
847 assert_eq!(nt.find_hex(&idx, "1")?, Some(1));
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
848 assert_eq!(nt.find_hex(&idx, "12")?, Some(1));
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
849 assert_eq!(nt.find_hex(&idx, "1234de")?, Some(1));
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
850 assert_eq!(nt.find_hex(&idx, "1a")?, None);
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
851 assert_eq!(nt.find_hex(&idx, "ab")?, None);
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
852
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
853 // and with full binary Nodes
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
854 assert_eq!(nt.find_node(&idx, idx.get(&1).unwrap())?, Some(1));
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
855 let unknown = Node::from_hex(&hex_pad_right("3d")).unwrap();
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
856 assert_eq!(nt.find_node(&idx, &unknown)?, None);
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
857 Ok(())
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
858 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
859
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
860 #[test]
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
861 fn test_immutable_find_one_jump() {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
862 let mut idx = TestIndex::new();
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
863 pad_insert(&mut idx, 9, "012");
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
864 pad_insert(&mut idx, 0, "00a");
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
865
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
866 let nt = sample_nodetree();
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
867
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
868 assert_eq!(nt.find_hex(&idx, "0"), Err(MultipleResults));
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
869 assert_eq!(nt.find_hex(&idx, "01"), Ok(Some(9)));
44387
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
870 assert_eq!(nt.find_hex(&idx, "00"), Err(MultipleResults));
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
871 assert_eq!(nt.find_hex(&idx, "00a"), Ok(Some(0)));
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
872 assert_eq!(nt.unique_prefix_len_hex(&idx, "00a"), Ok(Some(3)));
44387
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
873 assert_eq!(nt.find_hex(&idx, "000"), Ok(Some(NULL_REVISION)));
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
874 }
44185
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
875
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
876 #[test]
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
877 fn test_mutated_find() -> Result<(), NodeMapError> {
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
878 let mut idx = TestIndex::new();
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
879 pad_insert(&mut idx, 9, "012");
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
880 pad_insert(&mut idx, 0, "00a");
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
881 pad_insert(&mut idx, 2, "cafe");
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
882 pad_insert(&mut idx, 3, "15");
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
883 pad_insert(&mut idx, 1, "10");
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
884
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
885 let nt = NodeTree {
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
886 readonly: sample_nodetree().readonly,
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
887 growable: vec![block![0: Rev(1), 5: Rev(3)]],
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
888 root: block![0: Block(1), 1:Block(3), 12: Rev(2)],
44389
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
889 masked_inner_blocks: 1,
44185
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
890 };
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
891 assert_eq!(nt.find_hex(&idx, "10")?, Some(1));
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
892 assert_eq!(nt.find_hex(&idx, "c")?, Some(2));
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
893 assert_eq!(nt.unique_prefix_len_hex(&idx, "c")?, Some(1));
44387
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
894 assert_eq!(nt.find_hex(&idx, "00"), Err(MultipleResults));
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
895 assert_eq!(nt.find_hex(&idx, "000")?, Some(NULL_REVISION));
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
896 assert_eq!(nt.unique_prefix_len_hex(&idx, "000")?, Some(3));
44185
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
897 assert_eq!(nt.find_hex(&idx, "01")?, Some(9));
44389
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
898 assert_eq!(nt.masked_readonly_blocks(), 2);
44185
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
899 Ok(())
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
900 }
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
901
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
902 struct TestNtIndex {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
903 index: TestIndex,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
904 nt: NodeTree,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
905 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
906
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
907 impl TestNtIndex {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
908 fn new() -> Self {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
909 TestNtIndex {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
910 index: HashMap::new(),
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
911 nt: NodeTree::default(),
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
912 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
913 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
914
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
915 fn insert(
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
916 &mut self,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
917 rev: Revision,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
918 hex: &str,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
919 ) -> Result<(), NodeMapError> {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
920 let node = pad_node(hex);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
921 self.index.insert(rev, node.clone());
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
922 self.nt.insert(&self.index, &node, rev)?;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
923 Ok(())
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
924 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
925
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
926 fn find_hex(
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
927 &self,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
928 prefix: &str,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
929 ) -> Result<Option<Revision>, NodeMapError> {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
930 self.nt.find_hex(&self.index, prefix)
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
931 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
932
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
933 fn unique_prefix_len_hex(
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
934 &self,
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
935 prefix: &str,
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
936 ) -> Result<Option<usize>, NodeMapError> {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
937 self.nt.unique_prefix_len_hex(&self.index, prefix)
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
938 }
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
939
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
940 /// Drain `added` and restart a new one
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
941 fn commit(self) -> Self {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
942 let mut as_vec: Vec<Block> =
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
943 self.nt.readonly.iter().map(|block| block.clone()).collect();
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
944 as_vec.extend(self.nt.growable);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
945 as_vec.push(self.nt.root);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
946
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
947 Self {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
948 index: self.index,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
949 nt: NodeTree::from(as_vec).into(),
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
950 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
951 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
952 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
953
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
954 #[test]
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
955 fn test_insert_full_mutable() -> Result<(), NodeMapError> {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
956 let mut idx = TestNtIndex::new();
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
957 idx.insert(0, "1234")?;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
958 assert_eq!(idx.find_hex("1")?, Some(0));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
959 assert_eq!(idx.find_hex("12")?, Some(0));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
960
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
961 // let's trigger a simple split
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
962 idx.insert(1, "1a34")?;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
963 assert_eq!(idx.nt.growable.len(), 1);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
964 assert_eq!(idx.find_hex("12")?, Some(0));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
965 assert_eq!(idx.find_hex("1a")?, Some(1));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
966
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
967 // reinserting is a no_op
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
968 idx.insert(1, "1a34")?;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
969 assert_eq!(idx.nt.growable.len(), 1);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
970 assert_eq!(idx.find_hex("12")?, Some(0));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
971 assert_eq!(idx.find_hex("1a")?, Some(1));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
972
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
973 idx.insert(2, "1a01")?;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
974 assert_eq!(idx.nt.growable.len(), 2);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
975 assert_eq!(idx.find_hex("1a"), Err(NodeMapError::MultipleResults));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
976 assert_eq!(idx.find_hex("12")?, Some(0));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
977 assert_eq!(idx.find_hex("1a3")?, Some(1));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
978 assert_eq!(idx.find_hex("1a0")?, Some(2));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
979 assert_eq!(idx.find_hex("1a12")?, None);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
980
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
981 // now let's make it split and create more than one additional block
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
982 idx.insert(3, "1a345")?;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
983 assert_eq!(idx.nt.growable.len(), 4);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
984 assert_eq!(idx.find_hex("1a340")?, Some(1));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
985 assert_eq!(idx.find_hex("1a345")?, Some(3));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
986 assert_eq!(idx.find_hex("1a341")?, None);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
987
44389
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
988 // there's no readonly block to mask
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
989 assert_eq!(idx.nt.masked_readonly_blocks(), 0);
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
990 Ok(())
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
991 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
992
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
993 #[test]
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
994 fn test_unique_prefix_len_zero_prefix() {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
995 let mut idx = TestNtIndex::new();
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
996 idx.insert(0, "00000abcd").unwrap();
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
997
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
998 assert_eq!(idx.find_hex("000"), Err(NodeMapError::MultipleResults));
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
999 // in the nodetree proper, this will be found at the first nybble
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
1000 // yet the correct answer for unique_prefix_len is not 1, nor 1+1,
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
1001 // but the first difference with `NULL_NODE`
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
1002 assert_eq!(idx.unique_prefix_len_hex("00000a"), Ok(Some(6)));
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
1003 assert_eq!(idx.unique_prefix_len_hex("00000ab"), Ok(Some(6)));
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
1004
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
1005 // same with odd result
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
1006 idx.insert(1, "00123").unwrap();
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
1007 assert_eq!(idx.unique_prefix_len_hex("001"), Ok(Some(3)));
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
1008 assert_eq!(idx.unique_prefix_len_hex("0012"), Ok(Some(3)));
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
1009
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
1010 // these are unchanged of course
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
1011 assert_eq!(idx.unique_prefix_len_hex("00000a"), Ok(Some(6)));
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
1012 assert_eq!(idx.unique_prefix_len_hex("00000ab"), Ok(Some(6)));
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
1013 }
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
1014
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
1015 #[test]
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1016 fn test_insert_extreme_splitting() -> Result<(), NodeMapError> {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1017 // check that the splitting loop is long enough
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1018 let mut nt_idx = TestNtIndex::new();
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1019 let nt = &mut nt_idx.nt;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1020 let idx = &mut nt_idx.index;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1021
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1022 let node0_hex = hex_pad_right("444444");
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1023 let mut node1_hex = hex_pad_right("444444").clone();
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1024 node1_hex.pop();
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1025 node1_hex.push('5');
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1026 let node0 = Node::from_hex(&node0_hex).unwrap();
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1027 let node1 = Node::from_hex(&node1_hex).unwrap();
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1028
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1029 idx.insert(0, node0.clone());
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1030 nt.insert(idx, &node0, 0)?;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1031 idx.insert(1, node1.clone());
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1032 nt.insert(idx, &node1, 1)?;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1033
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1034 assert_eq!(nt.find_bin(idx, (&node0).into())?, Some(0));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1035 assert_eq!(nt.find_bin(idx, (&node1).into())?, Some(1));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1036 Ok(())
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1037 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1038
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1039 #[test]
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1040 fn test_insert_partly_immutable() -> Result<(), NodeMapError> {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1041 let mut idx = TestNtIndex::new();
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1042 idx.insert(0, "1234")?;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1043 idx.insert(1, "1235")?;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1044 idx.insert(2, "131")?;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1045 idx.insert(3, "cafe")?;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1046 let mut idx = idx.commit();
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1047 assert_eq!(idx.find_hex("1234")?, Some(0));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1048 assert_eq!(idx.find_hex("1235")?, Some(1));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1049 assert_eq!(idx.find_hex("131")?, Some(2));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1050 assert_eq!(idx.find_hex("cafe")?, Some(3));
44389
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
1051 // we did not add anything since init from readonly
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
1052 assert_eq!(idx.nt.masked_readonly_blocks(), 0);
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1053
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1054 idx.insert(4, "123A")?;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1055 assert_eq!(idx.find_hex("1234")?, Some(0));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1056 assert_eq!(idx.find_hex("1235")?, Some(1));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1057 assert_eq!(idx.find_hex("131")?, Some(2));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1058 assert_eq!(idx.find_hex("cafe")?, Some(3));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1059 assert_eq!(idx.find_hex("123A")?, Some(4));
44389
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
1060 // we masked blocks for all prefixes of "123", including the root
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
1061 assert_eq!(idx.nt.masked_readonly_blocks(), 4);
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1062
44389
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
1063 eprintln!("{:?}", idx.nt);
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1064 idx.insert(5, "c0")?;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1065 assert_eq!(idx.find_hex("cafe")?, Some(3));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1066 assert_eq!(idx.find_hex("c0")?, Some(5));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1067 assert_eq!(idx.find_hex("c1")?, None);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1068 assert_eq!(idx.find_hex("1234")?, Some(0));
44389
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
1069 // inserting "c0" is just splitting the 'c' slot of the mutable root,
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
1070 // it doesn't mask anything
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
1071 assert_eq!(idx.nt.masked_readonly_blocks(), 4);
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1072
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1073 Ok(())
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1074 }
44385
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1075
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1076 #[test]
44390
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1077 fn test_invalidate_all() -> Result<(), NodeMapError> {
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1078 let mut idx = TestNtIndex::new();
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1079 idx.insert(0, "1234")?;
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1080 idx.insert(1, "1235")?;
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1081 idx.insert(2, "131")?;
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1082 idx.insert(3, "cafe")?;
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1083 let mut idx = idx.commit();
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1084
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1085 idx.nt.invalidate_all();
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1086
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1087 assert_eq!(idx.find_hex("1234")?, None);
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1088 assert_eq!(idx.find_hex("1235")?, None);
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1089 assert_eq!(idx.find_hex("131")?, None);
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1090 assert_eq!(idx.find_hex("cafe")?, None);
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1091 // all the readonly blocks have been masked, this is the
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1092 // conventional expected response
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1093 assert_eq!(idx.nt.masked_readonly_blocks(), idx.nt.readonly.len() + 1);
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1094 Ok(())
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1095 }
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1096
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1097 #[test]
44385
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1098 fn test_into_added_empty() {
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1099 assert!(sample_nodetree().into_readonly_and_added().1.is_empty());
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1100 assert!(sample_nodetree()
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1101 .into_readonly_and_added_bytes()
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1102 .1
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1103 .is_empty());
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1104 }
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1105
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1106 #[test]
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1107 fn test_into_added_bytes() -> Result<(), NodeMapError> {
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1108 let mut idx = TestNtIndex::new();
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1109 idx.insert(0, "1234")?;
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1110 let mut idx = idx.commit();
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1111 idx.insert(4, "cafe")?;
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1112 let (_, bytes) = idx.nt.into_readonly_and_added_bytes();
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1113
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1114 // only the root block has been changed
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1115 assert_eq!(bytes.len(), BLOCK_SIZE);
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1116 // big endian for -2
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1117 assert_eq!(&bytes[4..2 * 4], [255, 255, 255, 254]);
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1118 // big endian for -6
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1119 assert_eq!(&bytes[12 * 4..13 * 4], [255, 255, 255, 250]);
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1120 Ok(())
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1121 }
44142
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
1122 }