Mercurial > hg
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 /// |