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