annotate rust/hg-core/src/revlog/nodemap.rs @ 50818:28c0fcff24e5 stable

rhg: fix the bug where sparse config is interpreted as relglob instead of glob relglob apparently (in contrast with relpath) matches everywhere in the tree, whereas glob only matches at the root. The python version interprets these patterns as "glob" (see "normalize(include, b'glob', ...)" in match.py)
author Arseniy Alekseyev <aalekseyev@janestreet.com>
date Thu, 10 Aug 2023 19:00:19 +0100
parents 3894763d92f8
children 1928b770e3e7 eccf7dc7c91e
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
44142
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
1 // Copyright 2018-2020 Georges Racinet <georges.racinet@octobus.net>
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
2 // and Mercurial contributors
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
3 //
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
4 // This software may be used and distributed according to the terms of the
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
5 // GNU General Public License version 2 or any later version.
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
6 //! Indexing facilities for fast retrieval of `Revision` from `Node`
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
7 //!
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
8 //! This provides a variation on the 16-ary radix tree that is
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
9 //! provided as "nodetree" in revlog.c, ready for append-only persistence
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
10 //! on disk.
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
11 //!
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
12 //! Following existing implicit conventions, the "nodemap" terminology
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
13 //! is used in a more abstract context.
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
14
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
15 use super::{
46432
18a261b11b20 rust: Remove hex parsing from the nodemap
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
16 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
17 };
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
18
46390
0800aa42bb4c rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents: 44973
diff changeset
19 use bytes_cast::{unaligned, BytesCast};
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
20 use std::cmp::max;
44142
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
21 use std::fmt;
46390
0800aa42bb4c rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents: 44973
diff changeset
22 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
23 use std::ops::Deref;
44184
220d4d2e3185 rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents: 44183
diff changeset
24 use std::ops::Index;
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
25
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
26 #[derive(Debug, PartialEq)]
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
27 pub enum NodeMapError {
50415
f2deaca3450e rustdoc: fixed or introduced crossrefs in nodemap.rs
Georges Racinet <georges.racinet@octobus.net>
parents: 50412
diff changeset
28 /// A `NodePrefix` matches several [`Revision`]s.
50416
3894763d92f8 rustdoc: nodemap doc refreshing
Georges Racinet <georges.racinet@octobus.net>
parents: 50415
diff changeset
29 ///
3894763d92f8 rustdoc: nodemap doc refreshing
Georges Racinet <georges.racinet@octobus.net>
parents: 50415
diff changeset
30 /// 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
31 MultipleResults,
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
32 /// A `Revision` stored in the nodemap could not be found in the index
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
33 RevisionNotInIndex(Revision),
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
34 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
35
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
36 /// 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
37 ///
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
38 /// ## `RevlogIndex` and `NodeMap`
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 /// One way to think about their relationship is that
50416
3894763d92f8 rustdoc: nodemap doc refreshing
Georges Racinet <georges.racinet@octobus.net>
parents: 50415
diff changeset
41 /// the `NodeMap` is a prefix-oriented reverse index of the [`Node`]
3894763d92f8 rustdoc: nodemap doc refreshing
Georges Racinet <georges.racinet@octobus.net>
parents: 50415
diff changeset
42 /// information carried by a [`RevlogIndex`].
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
43 ///
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
44 /// 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
45 /// 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
46 /// 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
47 ///
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
48 /// Notably, the `NodeMap` must not store
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
49 /// 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
50 /// In these methods, an encountered `Revision` is not in the index, a
50416
3894763d92f8 rustdoc: nodemap doc refreshing
Georges Racinet <georges.racinet@octobus.net>
parents: 50415
diff changeset
51 /// [RevisionNotInIndex](NodeMapError) error is returned.
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
52 ///
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
53 /// In insert operations, the rule is thus that the `NodeMap` must always
50416
3894763d92f8 rustdoc: nodemap doc refreshing
Georges Racinet <georges.racinet@octobus.net>
parents: 50415
diff changeset
54 /// 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
55 pub trait NodeMap {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
56 /// 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
57 ///
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
58 /// 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
59 fn find_node(
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
60 &self,
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
61 index: &impl RevlogIndex,
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
62 node: &Node,
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
63 ) -> Result<Option<Revision>, NodeMapError> {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
64 self.find_bin(index, node.into())
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
65 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
66
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
67 /// 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
68 ///
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
69 /// 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
70 ///
50412
331a3cbe1c9e rustdoc: fixed warnings about links
Georges Racinet <georges.racinet@octobus.net>
parents: 49930
diff changeset
71 /// If several Revisions match the given prefix, a
331a3cbe1c9e rustdoc: fixed warnings about links
Georges Racinet <georges.racinet@octobus.net>
parents: 49930
diff changeset
72 /// [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
73 fn find_bin(
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
74 &self,
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
75 idx: &impl RevlogIndex,
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46428
diff changeset
76 prefix: NodePrefix,
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
77 ) -> Result<Option<Revision>, NodeMapError>;
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
78
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
79 /// 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
80 /// the revision uniquely.
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
81 ///
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
82 /// 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
83 /// 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
84 /// to find the revision uniquely.
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
85 ///
50415
f2deaca3450e rustdoc: fixed or introduced crossrefs in nodemap.rs
Georges Racinet <georges.racinet@octobus.net>
parents: 50412
diff changeset
86 /// 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
87 ///
50412
331a3cbe1c9e rustdoc: fixed warnings about links
Georges Racinet <georges.racinet@octobus.net>
parents: 49930
diff changeset
88 /// If several Revisions match the given prefix, a
331a3cbe1c9e rustdoc: fixed warnings about links
Georges Racinet <georges.racinet@octobus.net>
parents: 49930
diff changeset
89 /// [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
90 fn unique_prefix_len_bin(
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
91 &self,
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
92 idx: &impl RevlogIndex,
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46428
diff changeset
93 node_prefix: NodePrefix,
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
94 ) -> Result<Option<usize>, NodeMapError>;
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
95
50416
3894763d92f8 rustdoc: nodemap doc refreshing
Georges Racinet <georges.racinet@octobus.net>
parents: 50415
diff changeset
96 /// Same as [unique_prefix_len_bin](Self::unique_prefix_len_bin), with
3894763d92f8 rustdoc: nodemap doc refreshing
Georges Racinet <georges.racinet@octobus.net>
parents: 50415
diff changeset
97 /// a full [`Node`] as input
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
98 fn unique_prefix_len_node(
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
99 &self,
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
100 idx: &impl RevlogIndex,
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
101 node: &Node,
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
102 ) -> Result<Option<usize>, NodeMapError> {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
103 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
104 }
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
105 }
44142
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
106
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
107 pub trait MutableNodeMap: NodeMap {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
108 fn insert<I: RevlogIndex>(
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
109 &mut self,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
110 index: &I,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
111 node: &Node,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
112 rev: Revision,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
113 ) -> Result<(), NodeMapError>;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
114 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
115
50412
331a3cbe1c9e rustdoc: fixed warnings about links
Georges Racinet <georges.racinet@octobus.net>
parents: 49930
diff changeset
116 /// Low level NodeTree [`Block`] elements
44142
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
117 ///
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
118 /// 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
119 type RawElement = unaligned::I32Be;
44142
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
120
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
121 /// High level representation of values in NodeTree
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
122 /// [`Blocks`](struct.Block.html)
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
123 ///
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
124 /// 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
125 /// use.
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
126 #[derive(Clone, Debug, Eq, PartialEq)]
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
127 enum Element {
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
128 Rev(Revision),
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
129 Block(usize),
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
130 None,
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
131 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
132
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
133 impl From<RawElement> for Element {
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
134 /// 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
135 ///
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
136 /// 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
137 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
138 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
139 if int >= 0 {
0800aa42bb4c rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents: 44973
diff changeset
140 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
141 } else if int == -1 {
44142
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
142 Element::None
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
143 } else {
46390
0800aa42bb4c rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents: 44973
diff changeset
144 Element::Rev(-int - 2)
44142
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
145 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
146 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
147 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
148
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
149 impl From<Element> for RawElement {
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
150 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
151 RawElement::from(match element {
44142
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
152 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
153 Element::Block(i) => i as i32,
44142
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
154 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
155 })
44142
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
156 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
157 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
158
50416
3894763d92f8 rustdoc: nodemap doc refreshing
Georges Racinet <georges.racinet@octobus.net>
parents: 50415
diff changeset
159 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: 50415
diff changeset
160
3894763d92f8 rustdoc: nodemap doc refreshing
Georges Racinet <georges.racinet@octobus.net>
parents: 50415
diff changeset
161 /// 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
162 ///
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
163 /// 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
164 /// such as `&Block`
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
165 ///
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
166 /// 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
167 /// 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
168 /// (nybble) `i` is either:
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 /// - absent (value -1)
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
171 /// - another `Block` in the same indexable container (value ≥ 0)
50415
f2deaca3450e rustdoc: fixed or introduced crossrefs in nodemap.rs
Georges Racinet <georges.racinet@octobus.net>
parents: 50412
diff changeset
172 /// - a [`Revision`] leaf (value ≤ -2)
44142
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 /// 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
175 /// different architectures.
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
176 ///
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
177 /// 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
178 /// able to represent the [`Block`] at index 0, hence -1 is the empty marker
50415
f2deaca3450e rustdoc: fixed or introduced crossrefs in nodemap.rs
Georges Racinet <georges.racinet@octobus.net>
parents: 50412
diff changeset
179 /// 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
180 ///
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
181 /// 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
182 /// 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
183 /// 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
184 #[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
185 #[repr(transparent)]
0800aa42bb4c rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents: 44973
diff changeset
186 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
187
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
188 impl Block {
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
189 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
190 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
191 Block([absent_node; ELEMENTS_PER_BLOCK])
44142
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
192 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
193
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
194 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
195 self.0[nybble as usize].into()
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 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
199 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
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
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
203 impl fmt::Debug for Block {
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
204 /// sparse representation for testing and debugging purposes
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
205 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
206 f.debug_map()
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
207 .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
208 Element::None => None,
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
209 element => Some((i, element)),
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
210 }))
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
211 .finish()
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
212 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
213 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
214
44185
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
215 /// 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
216 ///
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
217 /// 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
218 /// 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
219 ///
50416
3894763d92f8 rustdoc: nodemap doc refreshing
Georges Racinet <georges.racinet@octobus.net>
parents: 50415
diff changeset
220 /// 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
221 /// it on each insertion.
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
222 pub struct NodeTree {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
223 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
224 growable: Vec<Block>,
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
225 root: Block,
44389
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
226 masked_inner_blocks: usize,
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
227 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
228
44184
220d4d2e3185 rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents: 44183
diff changeset
229 impl Index<usize> for NodeTree {
220d4d2e3185 rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents: 44183
diff changeset
230 type Output = Block;
220d4d2e3185 rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents: 44183
diff changeset
231
220d4d2e3185 rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents: 44183
diff changeset
232 fn index(&self, i: usize) -> &Block {
44185
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
233 let ro_len = self.readonly.len();
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
234 if i < ro_len {
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
235 &self.readonly[i]
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
236 } 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
237 &self.root
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
238 } else {
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
239 &self.growable[i - ro_len]
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
240 }
44184
220d4d2e3185 rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents: 44183
diff changeset
241 }
220d4d2e3185 rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents: 44183
diff changeset
242 }
220d4d2e3185 rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents: 44183
diff changeset
243
50416
3894763d92f8 rustdoc: nodemap doc refreshing
Georges Racinet <georges.racinet@octobus.net>
parents: 50415
diff changeset
244 /// 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
245 fn has_prefix_or_none(
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
246 idx: &impl RevlogIndex,
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46428
diff changeset
247 prefix: NodePrefix,
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
248 rev: Revision,
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
249 ) -> Result<Option<Revision>, NodeMapError> {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
250 idx.node(rev)
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49095
diff changeset
251 .ok_or(NodeMapError::RevisionNotInIndex(rev))
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
252 .map(|node| {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
253 if prefix.is_prefix_of(node) {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
254 Some(rev)
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
255 } else {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
256 None
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
257 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
258 })
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
259 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
260
44387
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
261 /// validate that the candidate's node starts indeed with given prefix,
50416
3894763d92f8 rustdoc: nodemap doc refreshing
Georges Racinet <georges.racinet@octobus.net>
parents: 50415
diff changeset
262 /// 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
263 ///
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
264 /// 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
265 /// 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
266 fn validate_candidate(
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
267 idx: &impl RevlogIndex,
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46428
diff changeset
268 prefix: NodePrefix,
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
269 candidate: (Option<Revision>, usize),
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
270 ) -> Result<(Option<Revision>, usize), NodeMapError> {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
271 let (rev, steps) = candidate;
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
272 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
273 rev.map_or(Ok((None, steps)), |r| {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
274 has_prefix_or_none(idx, prefix, r)
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
275 .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
276 })
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
277 } else {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
278 // 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
279 // 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
280 match rev {
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
281 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
282 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
283 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
284 _ => Err(NodeMapError::MultipleResults),
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
285 },
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
286 }
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
287 }
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
288 }
00d251d32007 rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents: 44385
diff changeset
289
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
290 impl NodeTree {
44185
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
291 /// 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
292 ///
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
293 /// 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
294 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
295 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
296 NodeTree {
44973
26114bd6ec60 rust: do a clippy pass
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44390
diff changeset
297 readonly,
44185
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
298 growable: Vec::new(),
44973
26114bd6ec60 rust: do a clippy pass
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44390
diff changeset
299 root,
44389
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
300 masked_inner_blocks: 0,
44185
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
301 }
44184
220d4d2e3185 rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents: 44183
diff changeset
302 }
220d4d2e3185 rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents: 44183
diff changeset
303
44385
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
304 /// Create from an opaque bunch of bytes
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
305 ///
50416
3894763d92f8 rustdoc: nodemap doc refreshing
Georges Racinet <georges.racinet@octobus.net>
parents: 50415
diff changeset
306 /// The created [`NodeTreeBytes`] from `bytes`,
44385
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
307 /// of which exactly `amount` bytes are used.
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
308 ///
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
309 /// - `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
310 /// - `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
311 /// `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
312 /// 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
313 /// 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
314 ///
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
315 /// panics if `buffer` is smaller than `amount`
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
316 pub fn load_bytes(
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
317 bytes: Box<dyn Deref<Target = [u8]> + Send>,
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
318 amount: usize,
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
319 ) -> Self {
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
320 NodeTree::new(Box::new(NodeTreeBytes::new(bytes, amount)))
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
321 }
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
322
50415
f2deaca3450e rustdoc: fixed or introduced crossrefs in nodemap.rs
Georges Racinet <georges.racinet@octobus.net>
parents: 50412
diff changeset
323 /// 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
324 pub fn into_readonly_and_added(
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
325 self,
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
326 ) -> (Box<dyn Deref<Target = [Block]> + Send>, Vec<Block>) {
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
327 let mut vec = self.growable;
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
328 let readonly = self.readonly;
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
329 if readonly.last() != Some(&self.root) {
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
330 vec.push(self.root);
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
331 }
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
332 (readonly, vec)
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
333 }
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
334
50415
f2deaca3450e rustdoc: fixed or introduced crossrefs in nodemap.rs
Georges Racinet <georges.racinet@octobus.net>
parents: 50412
diff changeset
335 /// 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
336 /// storage
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
337 pub fn into_readonly_and_added_bytes(
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
338 self,
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
339 ) -> (Box<dyn Deref<Target = [Block]> + Send>, Vec<u8>) {
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
340 let (readonly, vec) = self.into_readonly_and_added();
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
341 // 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
342 // of the allocation.
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
343 let vec = mem::ManuallyDrop::new(vec);
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
344
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
345 // 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
346 // bytes, so this is perfectly safe.
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
347 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
348 // 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
349 // (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
350 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
351 assert_eq!(align_of::<Block>(), 1);
44385
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 // /!\ 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
354 // TODO: use `into_raw_parts` once stabilized
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
355 Vec::from_raw_parts(
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
356 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
357 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
358 vec.capacity() * size_of::<Block>(),
44385
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
359 )
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
360 };
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
361 (readonly, bytes)
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
362 }
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
363
44185
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
364 /// Total number of blocks
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
365 fn len(&self) -> usize {
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
366 self.readonly.len() + self.growable.len() + 1
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
367 }
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
368
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
369 /// Implemented for completeness
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
370 ///
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
371 /// 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
372 #[allow(dead_code)]
44184
220d4d2e3185 rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents: 44183
diff changeset
373 fn is_empty(&self) -> bool {
44185
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
374 false
44184
220d4d2e3185 rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents: 44183
diff changeset
375 }
220d4d2e3185 rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents: 44183
diff changeset
376
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
377 /// Main working method for `NodeTree` searches
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
378 ///
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
379 /// 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
380 /// *alone*: whereas `None` guarantees that the given prefix is absent
50415
f2deaca3450e rustdoc: fixed or introduced crossrefs in nodemap.rs
Georges Racinet <georges.racinet@octobus.net>
parents: 50412
diff changeset
381 /// 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: 50412
diff changeset
382 /// `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: 50412
diff changeset
383 /// [`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: 50412
diff changeset
384 /// be inferred from
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
385 /// 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
386 /// common node prefix with the given prefix.
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
387 ///
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
388 /// 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
389 /// of `prefix` that would give the same result, i.e. not the
50415
f2deaca3450e rustdoc: fixed or introduced crossrefs in nodemap.rs
Georges Racinet <georges.racinet@octobus.net>
parents: 50412
diff changeset
390 /// [MultipleResults](NodeMapError) error variant (again, using only the
f2deaca3450e rustdoc: fixed or introduced crossrefs in nodemap.rs
Georges Racinet <georges.racinet@octobus.net>
parents: 50412
diff changeset
391 /// data of the [`NodeTree`]).
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
392 fn lookup(
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
393 &self,
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46428
diff changeset
394 prefix: NodePrefix,
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
395 ) -> Result<(Option<Revision>, usize), NodeMapError> {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
396 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
397 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
398 return Ok((opt, i + 1));
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
399 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
400 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
401 Err(NodeMapError::MultipleResults)
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
402 }
44186
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
403
49095
b97835b2e2d4 rust-nodemap: remove unnecessary explicit lifetime
Martin von Zweigbergk <martinvonz@google.com>
parents: 46432
diff changeset
404 fn visit(&self, prefix: NodePrefix) -> NodeTreeVisitor {
44186
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
405 NodeTreeVisitor {
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
406 nt: self,
44973
26114bd6ec60 rust: do a clippy pass
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44390
diff changeset
407 prefix,
44186
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
408 visit: self.len() - 1,
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
409 nybble_idx: 0,
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
410 done: false,
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
411 }
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
412 }
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
413 /// Return a mutable reference for `Block` at index `idx`.
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
414 ///
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
415 /// 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
416 /// a newly appended copy.
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
417 ///
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
418 /// Returns (new_idx, glen, mut_ref) where
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
419 ///
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
420 /// - `new_idx` is the index of the mutable `Block`
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
421 /// - `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
422 /// - `glen` is the new length of `self.growable`
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
423 ///
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
424 /// 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
425 /// 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
426 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
427 let ro_blocks = &self.readonly;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
428 let ro_len = ro_blocks.len();
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
429 let glen = self.growable.len();
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
430 if idx < ro_len {
44389
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
431 self.masked_inner_blocks += 1;
44973
26114bd6ec60 rust: do a clippy pass
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44390
diff changeset
432 self.growable.push(ro_blocks[idx]);
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
433 (glen + ro_len, &mut self.growable[glen], glen + 1)
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
434 } else if glen + ro_len == idx {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
435 (idx, &mut self.root, glen)
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
436 } else {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
437 (idx, &mut self.growable[idx - ro_len], glen)
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
438 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
439 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
440
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
441 /// Main insertion method
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
442 ///
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
443 /// 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
444 /// `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
445 /// 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
446 /// blocks from the root.
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
447 ///
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
448 /// 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
449 /// 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
450 pub fn insert<I: RevlogIndex>(
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
451 &mut self,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
452 index: &I,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
453 node: &Node,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
454 rev: Revision,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
455 ) -> Result<(), NodeMapError> {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
456 let ro_len = &self.readonly.len();
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 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
459 let read_nybbles = visit_steps.len();
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
460 // 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
461 let deepest = visit_steps.pop().unwrap();
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
462
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
463 let (mut block_idx, mut block, mut glen) =
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
464 self.mutable_block(deepest.block_idx);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
465
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
466 if let Element::Rev(old_rev) = deepest.element {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
467 let old_node = index
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
468 .node(old_rev)
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49095
diff changeset
469 .ok_or(NodeMapError::RevisionNotInIndex(old_rev))?;
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
470 if old_node == node {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
471 return Ok(()); // avoid creating lots of useless blocks
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
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
474 // 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
475 // new blocks until we find the difference
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
476 let mut new_block_idx = ro_len + glen;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
477 let mut nybble = deepest.nybble;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
478 for nybble_pos in read_nybbles..node.nybbles_len() {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
479 block.set(nybble, Element::Block(new_block_idx));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
480
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
481 let new_nybble = node.get_nybble(nybble_pos);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
482 let old_nybble = old_node.get_nybble(nybble_pos);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
483
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
484 if old_nybble == new_nybble {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
485 self.growable.push(Block::new());
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
486 block = &mut self.growable[glen];
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
487 glen += 1;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
488 new_block_idx += 1;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
489 nybble = new_nybble;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
490 } else {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
491 let mut new_block = Block::new();
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
492 new_block.set(old_nybble, Element::Rev(old_rev));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
493 new_block.set(new_nybble, Element::Rev(rev));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
494 self.growable.push(new_block);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
495 break;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
496 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
497 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
498 } else {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
499 // Free slot in the deepest block: no splitting has to be done
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
500 block.set(deepest.nybble, Element::Rev(rev));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
501 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
502
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
503 // Backtrack over visit steps to update references
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
504 while let Some(visited) = visit_steps.pop() {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
505 let to_write = Element::Block(block_idx);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
506 if visit_steps.is_empty() {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
507 self.root.set(visited.nybble, to_write);
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 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
511 if block.get(visited.nybble) == to_write {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
512 break;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
513 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
514 block.set(visited.nybble, to_write);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
515 block_idx = new_idx;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
516 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
517 Ok(())
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
518 }
44389
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
519
44390
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
520 /// 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
521 /// immutable part.
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
522 pub fn invalidate_all(&mut self) {
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
523 self.root = Block::new();
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
524 self.growable = Vec::new();
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
525 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
526 }
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
527
44389
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
528 /// 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
529 /// masked in the mutable part.
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
530 ///
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
531 /// 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
532 /// 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
533 ///
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
534 /// 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
535 /// 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
536 /// 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
537 /// 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
538 /// actually unreachable to begin with.
44389
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
539 pub fn masked_readonly_blocks(&self) -> usize {
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
540 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
541 if readonly_root == &self.root {
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
542 return 0;
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 } else {
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
545 return 0;
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
546 }
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
547 self.masked_inner_blocks + 1
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
548 }
44186
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
549 }
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
550
44385
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
551 pub struct NodeTreeBytes {
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
552 buffer: Box<dyn Deref<Target = [u8]> + Send>,
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
553 len_in_blocks: usize,
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
554 }
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
555
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
556 impl NodeTreeBytes {
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
557 fn new(
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
558 buffer: Box<dyn Deref<Target = [u8]> + Send>,
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
559 amount: usize,
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
560 ) -> Self {
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
561 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
562 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
563 NodeTreeBytes {
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
564 buffer,
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
565 len_in_blocks,
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
566 }
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
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
570 impl Deref for NodeTreeBytes {
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
571 type Target = [Block];
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
572
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
573 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
574 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
575 // `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
576 // large enough.
0800aa42bb4c rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents: 44973
diff changeset
577 .unwrap()
0800aa42bb4c rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents: 44973
diff changeset
578 .0
44385
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
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46428
diff changeset
582 struct NodeTreeVisitor<'n> {
44186
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
583 nt: &'n NodeTree,
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46428
diff changeset
584 prefix: NodePrefix,
44186
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
585 visit: usize,
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
586 nybble_idx: usize,
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
587 done: bool,
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
588 }
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
589
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
590 #[derive(Debug, PartialEq, Clone)]
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
591 struct NodeTreeVisitItem {
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
592 block_idx: usize,
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
593 nybble: u8,
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
594 element: Element,
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
595 }
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
596
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46428
diff changeset
597 impl<'n> Iterator for NodeTreeVisitor<'n> {
44186
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
598 type Item = NodeTreeVisitItem;
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
599
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
600 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
601 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
602 return None;
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
603 }
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
604
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
605 let nybble = self.prefix.get_nybble(self.nybble_idx);
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
606 self.nybble_idx += 1;
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
607
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
608 let visit = self.visit;
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
609 let element = self.nt[visit].get(nybble);
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
610 if let Element::Block(idx) = element {
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
611 self.visit = idx;
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
612 } else {
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
613 self.done = true;
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
614 }
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
615
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
616 Some(NodeTreeVisitItem {
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
617 block_idx: visit,
44973
26114bd6ec60 rust: do a clippy pass
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44390
diff changeset
618 nybble,
26114bd6ec60 rust: do a clippy pass
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44390
diff changeset
619 element,
44186
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 }
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
622 }
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
623
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
624 impl NodeTreeVisitItem {
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
625 // Return `Some(opt)` if this item is final, with `opt` being the
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
626 // `Revision` that it may represent.
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 // If the item is not terminal, return `None`
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
629 fn final_revision(&self) -> Option<Option<Revision>> {
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
630 match self.element {
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
631 Element::Block(_) => None,
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
632 Element::Rev(r) => Some(Some(r)),
796d05f3fa84 rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents: 44185
diff changeset
633 Element::None => Some(None),
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 }
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
636 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
637
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
638 impl From<Vec<Block>> for NodeTree {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
639 fn from(vec: Vec<Block>) -> Self {
44185
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
640 Self::new(Box::new(vec))
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
641 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
642 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
643
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
644 impl fmt::Debug for NodeTree {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
645 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44185
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
646 let readonly: &[Block] = &*self.readonly;
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
647 write!(
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
648 f,
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
649 "readonly: {:?}, growable: {:?}, root: {:?}",
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
650 readonly, self.growable, self.root
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
651 )
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
652 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
653 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
654
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
655 impl Default for NodeTree {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
656 /// Create a fully mutable empty NodeTree
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
657 fn default() -> Self {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
658 NodeTree::new(Box::new(Vec::new()))
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
659 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
660 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
661
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
662 impl NodeMap for NodeTree {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
663 fn find_bin<'a>(
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
664 &self,
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
665 idx: &impl RevlogIndex,
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46428
diff changeset
666 prefix: NodePrefix,
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
667 ) -> 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
668 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
669 .map(|(opt, _shortest)| opt)
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
670 }
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
671
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
672 fn unique_prefix_len_bin<'a>(
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
673 &self,
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
674 idx: &impl RevlogIndex,
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46428
diff changeset
675 prefix: NodePrefix,
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
676 ) -> 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
677 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
678 .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
679 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
680 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
681
44142
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
682 #[cfg(test)]
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
683 mod tests {
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
684 use super::NodeMapError::*;
44142
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
685 use super::*;
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
686 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
687 use std::collections::HashMap;
44142
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
688
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
689 /// 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
690 macro_rules! block {
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
691 {$($nybble:tt : $variant:ident($val:tt)),*} => (
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
692 {
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
693 let mut block = Block::new();
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
694 $(block.set($nybble, Element::$variant($val)));*;
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
695 block
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
696 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
697 )
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
698 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
699
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
700 #[test]
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
701 fn test_block_debug() {
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
702 let mut block = Block::new();
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
703 block.set(1, Element::Rev(3));
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
704 block.set(10, Element::Block(0));
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
705 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
706 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
707
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
708 #[test]
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
709 fn test_block_macro() {
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
710 let block = block! {5: Block(2)};
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
711 assert_eq!(format!("{:?}", block), "{5: Block(2)}");
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
712
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
713 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
714 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
715 }
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
716
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
717 #[test]
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
718 fn test_raw_block() {
44385
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
719 let mut raw = [255u8; 64];
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
720
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
721 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
722 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
723 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
724 raw[counter] = *byte;
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
725 counter += 1;
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
726 }
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
727 }
46390
0800aa42bb4c rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents: 44973
diff changeset
728 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
729 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
730 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
731 assert_eq!(block.get(3), Element::None);
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
732 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
733 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
734 }
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
735
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
736 type TestIndex = HashMap<Revision, Node>;
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
737
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
738 impl RevlogIndex for TestIndex {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
739 fn node(&self, rev: Revision) -> Option<&Node> {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
740 self.get(&rev)
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
741 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
742
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
743 fn len(&self) -> usize {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
744 self.len()
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
745 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
746 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
747
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
748 /// 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
749 ///
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
750 /// 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
751 /// 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
752 #[cfg(test)]
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
753 fn pad_node(hex: &str) -> Node {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
754 Node::from_hex(&hex_pad_right(hex)).unwrap()
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
755 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
756
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
757 /// 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
758 fn pad_insert(idx: &mut TestIndex, rev: Revision, hex: &str) {
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
759 idx.insert(rev, pad_node(hex));
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
760 }
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 fn sample_nodetree() -> NodeTree {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
763 NodeTree::from(vec![
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
764 block![0: Rev(9)],
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
765 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
766 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
767 ])
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
768 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
769
46432
18a261b11b20 rust: Remove hex parsing from the nodemap
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
770 fn hex(s: &str) -> NodePrefix {
18a261b11b20 rust: Remove hex parsing from the nodemap
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
771 NodePrefix::from_hex(s).unwrap()
18a261b11b20 rust: Remove hex parsing from the nodemap
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
772 }
18a261b11b20 rust: Remove hex parsing from the nodemap
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
773
44183
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
774 #[test]
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
775 fn test_nt_debug() {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
776 let nt = sample_nodetree();
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
777 assert_eq!(
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
778 format!("{:?}", nt),
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
779 "readonly: \
44185
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
780 [{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
781 growable: [], \
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
782 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
783 );
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 #[test]
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
787 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
788 let mut idx: TestIndex = HashMap::new();
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
789 pad_insert(&mut idx, 1, "1234deadcafe");
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
790
44185
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
791 let nt = NodeTree::from(vec![block! {1: Rev(1)}]);
46432
18a261b11b20 rust: Remove hex parsing from the nodemap
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
792 assert_eq!(nt.find_bin(&idx, hex("1"))?, Some(1));
18a261b11b20 rust: Remove hex parsing from the nodemap
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
793 assert_eq!(nt.find_bin(&idx, hex("12"))?, Some(1));
18a261b11b20 rust: Remove hex parsing from the nodemap
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
794 assert_eq!(nt.find_bin(&idx, hex("1234de"))?, Some(1));
18a261b11b20 rust: Remove hex parsing from the nodemap
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
795 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
796 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
797
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
798 // and with full binary Nodes
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
799 assert_eq!(nt.find_node(&idx, idx.get(&1).unwrap())?, Some(1));
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
800 let unknown = Node::from_hex(&hex_pad_right("3d")).unwrap();
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
801 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
802 Ok(())
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
803 }
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
804
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
805 #[test]
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
806 fn test_immutable_find_one_jump() {
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
807 let mut idx = TestIndex::new();
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
808 pad_insert(&mut idx, 9, "012");
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
809 pad_insert(&mut idx, 0, "00a");
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
810
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
811 let nt = sample_nodetree();
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44142
diff changeset
812
46432
18a261b11b20 rust: Remove hex parsing from the nodemap
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
813 assert_eq!(nt.find_bin(&idx, hex("0")), Err(MultipleResults));
18a261b11b20 rust: Remove hex parsing from the nodemap
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
814 assert_eq!(nt.find_bin(&idx, hex("01")), Ok(Some(9)));
18a261b11b20 rust: Remove hex parsing from the nodemap
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
815 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
816 assert_eq!(nt.find_bin(&idx, hex("00a")), Ok(Some(0)));
18a261b11b20 rust: Remove hex parsing from the nodemap
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
817 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
818 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
819 }
44185
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
820
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
821 #[test]
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
822 fn test_mutated_find() -> Result<(), NodeMapError> {
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
823 let mut idx = TestIndex::new();
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
824 pad_insert(&mut idx, 9, "012");
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
825 pad_insert(&mut idx, 0, "00a");
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
826 pad_insert(&mut idx, 2, "cafe");
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
827 pad_insert(&mut idx, 3, "15");
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
828 pad_insert(&mut idx, 1, "10");
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
829
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
830 let nt = NodeTree {
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
831 readonly: sample_nodetree().readonly,
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
832 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
833 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
834 masked_inner_blocks: 1,
44185
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
835 };
46432
18a261b11b20 rust: Remove hex parsing from the nodemap
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
836 assert_eq!(nt.find_bin(&idx, hex("10"))?, Some(1));
18a261b11b20 rust: Remove hex parsing from the nodemap
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
837 assert_eq!(nt.find_bin(&idx, hex("c"))?, Some(2));
18a261b11b20 rust: Remove hex parsing from the nodemap
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
838 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
839 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
840 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
841 assert_eq!(nt.unique_prefix_len_bin(&idx, hex("000"))?, Some(3));
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("01"))?, Some(9));
44389
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
843 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
844 Ok(())
a19331456d48 rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents: 44184
diff changeset
845 }
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
846
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
847 struct TestNtIndex {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
848 index: TestIndex,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
849 nt: NodeTree,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
850 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
851
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
852 impl TestNtIndex {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
853 fn new() -> Self {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
854 TestNtIndex {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
855 index: HashMap::new(),
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
856 nt: NodeTree::default(),
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
857 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
858 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
859
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
860 fn insert(
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
861 &mut self,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
862 rev: Revision,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
863 hex: &str,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
864 ) -> Result<(), NodeMapError> {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
865 let node = pad_node(hex);
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49095
diff changeset
866 self.index.insert(rev, node);
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
867 self.nt.insert(&self.index, &node, rev)?;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
868 Ok(())
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
869 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
870
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
871 fn find_hex(
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
872 &self,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
873 prefix: &str,
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
874 ) -> Result<Option<Revision>, NodeMapError> {
46432
18a261b11b20 rust: Remove hex parsing from the nodemap
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
875 self.nt.find_bin(&self.index, hex(prefix))
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
876 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
877
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
878 fn unique_prefix_len_hex(
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
879 &self,
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
880 prefix: &str,
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
881 ) -> Result<Option<usize>, NodeMapError> {
46432
18a261b11b20 rust: Remove hex parsing from the nodemap
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
882 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
883 }
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
884
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
885 /// Drain `added` and restart a new one
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
886 fn commit(self) -> Self {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
887 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
888 self.nt.readonly.iter().copied().collect();
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
889 as_vec.extend(self.nt.growable);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
890 as_vec.push(self.nt.root);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
891
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
892 Self {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
893 index: self.index,
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49095
diff changeset
894 nt: NodeTree::from(as_vec),
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
895 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
896 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
897 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
898
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
899 #[test]
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
900 fn test_insert_full_mutable() -> Result<(), NodeMapError> {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
901 let mut idx = TestNtIndex::new();
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
902 idx.insert(0, "1234")?;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
903 assert_eq!(idx.find_hex("1")?, Some(0));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
904 assert_eq!(idx.find_hex("12")?, Some(0));
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 // let's trigger a simple split
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
907 idx.insert(1, "1a34")?;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
908 assert_eq!(idx.nt.growable.len(), 1);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
909 assert_eq!(idx.find_hex("12")?, Some(0));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
910 assert_eq!(idx.find_hex("1a")?, Some(1));
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 // reinserting is a no_op
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
913 idx.insert(1, "1a34")?;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
914 assert_eq!(idx.nt.growable.len(), 1);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
915 assert_eq!(idx.find_hex("12")?, Some(0));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
916 assert_eq!(idx.find_hex("1a")?, Some(1));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
917
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
918 idx.insert(2, "1a01")?;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
919 assert_eq!(idx.nt.growable.len(), 2);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
920 assert_eq!(idx.find_hex("1a"), Err(NodeMapError::MultipleResults));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
921 assert_eq!(idx.find_hex("12")?, Some(0));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
922 assert_eq!(idx.find_hex("1a3")?, Some(1));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
923 assert_eq!(idx.find_hex("1a0")?, Some(2));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
924 assert_eq!(idx.find_hex("1a12")?, None);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
925
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
926 // now let's make it split and create more than one additional block
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
927 idx.insert(3, "1a345")?;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
928 assert_eq!(idx.nt.growable.len(), 4);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
929 assert_eq!(idx.find_hex("1a340")?, Some(1));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
930 assert_eq!(idx.find_hex("1a345")?, Some(3));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
931 assert_eq!(idx.find_hex("1a341")?, None);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
932
44389
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
933 // there's no readonly block to mask
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
934 assert_eq!(idx.nt.masked_readonly_blocks(), 0);
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
935 Ok(())
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
936 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
937
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
938 #[test]
44388
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
939 fn test_unique_prefix_len_zero_prefix() {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
940 let mut idx = TestNtIndex::new();
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
941 idx.insert(0, "00000abcd").unwrap();
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
942
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
943 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
944 // 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
945 // 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
946 // but the first difference with `NULL_NODE`
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
947 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
948 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
949
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
950 // same with odd result
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
951 idx.insert(1, "00123").unwrap();
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
952 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
953 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
954
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
955 // these are unchanged of course
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
956 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
957 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
958 }
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
959
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44387
diff changeset
960 #[test]
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
961 fn test_insert_extreme_splitting() -> Result<(), NodeMapError> {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
962 // check that the splitting loop is long enough
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
963 let mut nt_idx = TestNtIndex::new();
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
964 let nt = &mut nt_idx.nt;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
965 let idx = &mut nt_idx.index;
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 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
968 let mut node1_hex = hex_pad_right("444444");
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
969 node1_hex.pop();
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
970 node1_hex.push('5');
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
971 let node0 = Node::from_hex(&node0_hex).unwrap();
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
972 let node1 = Node::from_hex(&node1_hex).unwrap();
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
973
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49095
diff changeset
974 idx.insert(0, node0);
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
975 nt.insert(idx, &node0, 0)?;
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49095
diff changeset
976 idx.insert(1, node1);
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
977 nt.insert(idx, &node1, 1)?;
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 assert_eq!(nt.find_bin(idx, (&node0).into())?, Some(0));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
980 assert_eq!(nt.find_bin(idx, (&node1).into())?, Some(1));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
981 Ok(())
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
982 }
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
983
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
984 #[test]
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
985 fn test_insert_partly_immutable() -> Result<(), NodeMapError> {
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
986 let mut idx = TestNtIndex::new();
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
987 idx.insert(0, "1234")?;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
988 idx.insert(1, "1235")?;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
989 idx.insert(2, "131")?;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
990 idx.insert(3, "cafe")?;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
991 let mut idx = idx.commit();
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
992 assert_eq!(idx.find_hex("1234")?, Some(0));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
993 assert_eq!(idx.find_hex("1235")?, Some(1));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
994 assert_eq!(idx.find_hex("131")?, Some(2));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
995 assert_eq!(idx.find_hex("cafe")?, Some(3));
44389
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
996 // 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
997 assert_eq!(idx.nt.masked_readonly_blocks(), 0);
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
998
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
999 idx.insert(4, "123A")?;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1000 assert_eq!(idx.find_hex("1234")?, Some(0));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1001 assert_eq!(idx.find_hex("1235")?, Some(1));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1002 assert_eq!(idx.find_hex("131")?, Some(2));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1003 assert_eq!(idx.find_hex("cafe")?, Some(3));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1004 assert_eq!(idx.find_hex("123A")?, Some(4));
44389
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
1005 // 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
1006 assert_eq!(idx.nt.masked_readonly_blocks(), 4);
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1007
44389
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
1008 eprintln!("{:?}", idx.nt);
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1009 idx.insert(5, "c0")?;
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1010 assert_eq!(idx.find_hex("cafe")?, Some(3));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1011 assert_eq!(idx.find_hex("c0")?, Some(5));
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1012 assert_eq!(idx.find_hex("c1")?, None);
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1013 assert_eq!(idx.find_hex("1234")?, Some(0));
44389
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
1014 // 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
1015 // it doesn't mask anything
6329ce04c69f rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents: 44388
diff changeset
1016 assert_eq!(idx.nt.masked_readonly_blocks(), 4);
44356
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1017
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1018 Ok(())
d2da8667125b rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents: 44186
diff changeset
1019 }
44385
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1020
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1021 #[test]
44390
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1022 fn test_invalidate_all() -> Result<(), NodeMapError> {
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1023 let mut idx = TestNtIndex::new();
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1024 idx.insert(0, "1234")?;
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1025 idx.insert(1, "1235")?;
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1026 idx.insert(2, "131")?;
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1027 idx.insert(3, "cafe")?;
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1028 let mut idx = idx.commit();
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1029
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1030 idx.nt.invalidate_all();
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1031
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1032 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
1033 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
1034 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
1035 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
1036 // 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
1037 // conventional expected response
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1038 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
1039 Ok(())
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1040 }
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1041
d518994384a4 rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents: 44389
diff changeset
1042 #[test]
44385
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1043 fn test_into_added_empty() {
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1044 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
1045 assert!(sample_nodetree()
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1046 .into_readonly_and_added_bytes()
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1047 .1
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1048 .is_empty());
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1049 }
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1050
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1051 #[test]
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1052 fn test_into_added_bytes() -> Result<(), NodeMapError> {
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1053 let mut idx = TestNtIndex::new();
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1054 idx.insert(0, "1234")?;
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1055 let mut idx = idx.commit();
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1056 idx.insert(4, "cafe")?;
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1057 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
1058
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1059 // 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
1060 assert_eq!(bytes.len(), size_of::<Block>());
44385
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1061 // big endian for -2
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1062 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
1063 // big endian for -6
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1064 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
1065 Ok(())
a98ba6983a63 rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents: 44356
diff changeset
1066 }
44142
63db6657d280 rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
1067 }