annotate rust/hg-core/src/revlog/nodemap.rs @ 53040:cdd7bf612c7b stable tip

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