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