comparison rust/hg-core/src/revlog/nodemap.rs @ 50419:3894763d92f8

rustdoc: nodemap doc refreshing Not pretending to be comprehensive. - correcting some inconsistencies - adding a few missing doc-comments - adding more cross references (in some cases it's right beside the current documentation item, but it will nevertheless also be useful, because `rustdoc` will warn us if inconsistencies arise).
author Georges Racinet <georges.racinet@octobus.net>
date Mon, 03 Apr 2023 16:29:30 +0200
parents f2deaca3450e
children 1928b770e3e7 eccf7dc7c91e
comparison
equal deleted inserted replaced
50418:f2deaca3450e 50419:3894763d92f8
24 use std::ops::Index; 24 use std::ops::Index;
25 25
26 #[derive(Debug, PartialEq)] 26 #[derive(Debug, PartialEq)]
27 pub enum NodeMapError { 27 pub enum NodeMapError {
28 /// A `NodePrefix` matches several [`Revision`]s. 28 /// A `NodePrefix` matches several [`Revision`]s.
29 ///
30 /// This can be returned by methods meant for (at most) one match.
29 MultipleResults, 31 MultipleResults,
30 /// A `Revision` stored in the nodemap could not be found in the index 32 /// A `Revision` stored in the nodemap could not be found in the index
31 RevisionNotInIndex(Revision), 33 RevisionNotInIndex(Revision),
32 } 34 }
33 35
34 /// Mapping system from Mercurial nodes to revision numbers. 36 /// Mapping system from Mercurial nodes to revision numbers.
35 /// 37 ///
36 /// ## `RevlogIndex` and `NodeMap` 38 /// ## `RevlogIndex` and `NodeMap`
37 /// 39 ///
38 /// One way to think about their relationship is that 40 /// One way to think about their relationship is that
39 /// the `NodeMap` is a prefix-oriented reverse index of the `Node` information 41 /// the `NodeMap` is a prefix-oriented reverse index of the [`Node`]
40 /// carried by a [`RevlogIndex`]. 42 /// information carried by a [`RevlogIndex`].
41 /// 43 ///
42 /// Many of the methods in this trait take a `RevlogIndex` argument 44 /// Many of the methods in this trait take a `RevlogIndex` argument
43 /// which is used for validation of their results. This index must naturally 45 /// which is used for validation of their results. This index must naturally
44 /// be the one the `NodeMap` is about, and it must be consistent. 46 /// be the one the `NodeMap` is about, and it must be consistent.
45 /// 47 ///
46 /// Notably, the `NodeMap` must not store 48 /// Notably, the `NodeMap` must not store
47 /// information about more `Revision` values than there are in the index. 49 /// information about more `Revision` values than there are in the index.
48 /// In these methods, an encountered `Revision` is not in the index, a 50 /// In these methods, an encountered `Revision` is not in the index, a
49 /// [`RevisionNotInIndex`] error is returned. 51 /// [RevisionNotInIndex](NodeMapError) error is returned.
50 /// 52 ///
51 /// In insert operations, the rule is thus that the `NodeMap` must always 53 /// In insert operations, the rule is thus that the `NodeMap` must always
52 /// be updated after the `RevlogIndex` 54 /// be updated after the `RevlogIndex` it is about.
53 /// be updated first, and the `NodeMap` second.
54 ///
55 /// [`RevisionNotInIndex`]: enum.NodeMapError.html#variant.RevisionNotInIndex
56 /// [`RevlogIndex`]: ../trait.RevlogIndex.html
57 pub trait NodeMap { 55 pub trait NodeMap {
58 /// Find the unique `Revision` having the given `Node` 56 /// Find the unique `Revision` having the given `Node`
59 /// 57 ///
60 /// If no Revision matches the given `Node`, `Ok(None)` is returned. 58 /// If no Revision matches the given `Node`, `Ok(None)` is returned.
61 fn find_node( 59 fn find_node(
93 &self, 91 &self,
94 idx: &impl RevlogIndex, 92 idx: &impl RevlogIndex,
95 node_prefix: NodePrefix, 93 node_prefix: NodePrefix,
96 ) -> Result<Option<usize>, NodeMapError>; 94 ) -> Result<Option<usize>, NodeMapError>;
97 95
98 /// Same as `unique_prefix_len_bin`, with a full `Node` as input 96 /// Same as [unique_prefix_len_bin](Self::unique_prefix_len_bin), with
97 /// a full [`Node`] as input
99 fn unique_prefix_len_node( 98 fn unique_prefix_len_node(
100 &self, 99 &self,
101 idx: &impl RevlogIndex, 100 idx: &impl RevlogIndex,
102 node: &Node, 101 node: &Node,
103 ) -> Result<Option<usize>, NodeMapError> { 102 ) -> Result<Option<usize>, NodeMapError> {
155 Element::Rev(rev) => -rev - 2, 154 Element::Rev(rev) => -rev - 2,
156 }) 155 })
157 } 156 }
158 } 157 }
159 158
160 /// A logical block of the `NodeTree`, packed with a fixed size. 159 const ELEMENTS_PER_BLOCK: usize = 16; // number of different values in a nybble
160
161 /// A logical block of the [`NodeTree`], packed with a fixed size.
161 /// 162 ///
162 /// These are always used in container types implementing `Index<Block>`, 163 /// These are always used in container types implementing `Index<Block>`,
163 /// such as `&Block` 164 /// such as `&Block`
164 /// 165 ///
165 /// As an array of integers, its ith element encodes that the 166 /// As an array of integers, its ith element encodes that the
178 /// rather than 0 and the [`Revision`] range upper limit of -2 instead of -1. 179 /// rather than 0 and the [`Revision`] range upper limit of -2 instead of -1.
179 /// 180 ///
180 /// Another related difference is that `NULL_REVISION` (-1) is not 181 /// Another related difference is that `NULL_REVISION` (-1) is not
181 /// represented at all, because we want an immutable empty nodetree 182 /// represented at all, because we want an immutable empty nodetree
182 /// to be valid. 183 /// to be valid.
183
184 const ELEMENTS_PER_BLOCK: usize = 16; // number of different values in a nybble
185
186 #[derive(Copy, Clone, BytesCast, PartialEq)] 184 #[derive(Copy, Clone, BytesCast, PartialEq)]
187 #[repr(transparent)] 185 #[repr(transparent)]
188 pub struct Block([RawElement; ELEMENTS_PER_BLOCK]); 186 pub struct Block([RawElement; ELEMENTS_PER_BLOCK]);
189 187
190 impl Block { 188 impl Block {
217 /// A mutable 16-radix tree with the root block logically at the end 215 /// A mutable 16-radix tree with the root block logically at the end
218 /// 216 ///
219 /// Because of the append only nature of our node trees, we need to 217 /// Because of the append only nature of our node trees, we need to
220 /// keep the original untouched and store new blocks separately. 218 /// keep the original untouched and store new blocks separately.
221 /// 219 ///
222 /// The mutable root `Block` is kept apart so that we don't have to rebump 220 /// The mutable root [`Block`] is kept apart so that we don't have to rebump
223 /// it on each insertion. 221 /// it on each insertion.
224 pub struct NodeTree { 222 pub struct NodeTree {
225 readonly: Box<dyn Deref<Target = [Block]> + Send>, 223 readonly: Box<dyn Deref<Target = [Block]> + Send>,
226 growable: Vec<Block>, 224 growable: Vec<Block>,
227 root: Block, 225 root: Block,
241 &self.growable[i - ro_len] 239 &self.growable[i - ro_len]
242 } 240 }
243 } 241 }
244 } 242 }
245 243
246 /// Return `None` unless the `Node` for `rev` has given prefix in `index`. 244 /// Return `None` unless the [`Node`] for `rev` has given prefix in `idx`.
247 fn has_prefix_or_none( 245 fn has_prefix_or_none(
248 idx: &impl RevlogIndex, 246 idx: &impl RevlogIndex,
249 prefix: NodePrefix, 247 prefix: NodePrefix,
250 rev: Revision, 248 rev: Revision,
251 ) -> Result<Option<Revision>, NodeMapError> { 249 ) -> Result<Option<Revision>, NodeMapError> {
259 } 257 }
260 }) 258 })
261 } 259 }
262 260
263 /// validate that the candidate's node starts indeed with given prefix, 261 /// validate that the candidate's node starts indeed with given prefix,
264 /// and treat ambiguities related to `NULL_REVISION`. 262 /// and treat ambiguities related to [`NULL_REVISION`].
265 /// 263 ///
266 /// From the data in the NodeTree, one can only conclude that some 264 /// From the data in the NodeTree, one can only conclude that some
267 /// revision is the only one for a *subprefix* of the one being looked up. 265 /// revision is the only one for a *subprefix* of the one being looked up.
268 fn validate_candidate( 266 fn validate_candidate(
269 idx: &impl RevlogIndex, 267 idx: &impl RevlogIndex,
303 } 301 }
304 } 302 }
305 303
306 /// Create from an opaque bunch of bytes 304 /// Create from an opaque bunch of bytes
307 /// 305 ///
308 /// The created `NodeTreeBytes` from `buffer`, 306 /// The created [`NodeTreeBytes`] from `bytes`,
309 /// of which exactly `amount` bytes are used. 307 /// of which exactly `amount` bytes are used.
310 /// 308 ///
311 /// - `buffer` could be derived from `PyBuffer` and `Mmap` objects. 309 /// - `buffer` could be derived from `PyBuffer` and `Mmap` objects.
312 /// - `offset` allows for the final file format to include fixed data
313 /// (generation number, behavioural flags)
314 /// - `amount` is expressed in bytes, and is not automatically derived from 310 /// - `amount` is expressed in bytes, and is not automatically derived from
315 /// `bytes`, so that a caller that manages them atomically can perform 311 /// `bytes`, so that a caller that manages them atomically can perform
316 /// temporary disk serializations and still rollback easily if needed. 312 /// temporary disk serializations and still rollback easily if needed.
317 /// First use-case for this would be to support Mercurial shell hooks. 313 /// First use-case for this would be to support Mercurial shell hooks.
318 /// 314 ///