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