/__w/smoldot/smoldot/repo/lib/src/trie/branch_search.rs
Line | Count | Source (jump to first uncovered line) |
1 | | // Smoldot |
2 | | // Copyright (C) 2023 Pierre Krieger |
3 | | // SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 |
4 | | |
5 | | // This program is free software: you can redistribute it and/or modify |
6 | | // it under the terms of the GNU General Public License as published by |
7 | | // the Free Software Foundation, either version 3 of the License, or |
8 | | // (at your option) any later version. |
9 | | |
10 | | // This program is distributed in the hope that it will be useful, |
11 | | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | | // GNU General Public License for more details. |
14 | | |
15 | | // You should have received a copy of the GNU General Public License |
16 | | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | | |
18 | | //! Allows searching for the closest branch node in a trie when only the storage trie nodes are |
19 | | //! known. |
20 | | //! |
21 | | //! This module can be used in situations where only the list of trie nodes with a storage value |
22 | | //! is known, such as in the form of a `BTreeMap`, and allows finding the list of branch nodes. |
23 | | |
24 | | use core::iter; |
25 | | |
26 | | use crate::trie; |
27 | | use alloc::vec::{IntoIter, Vec}; |
28 | | |
29 | | pub use crate::trie::Nibble; |
30 | | |
31 | | mod tests; |
32 | | |
33 | | /// Configuration for [`start_branch_search`]. |
34 | | #[derive(Debug, Clone)] |
35 | | pub struct Config<K, P> { |
36 | | /// The search will try to find the closest node whose key is strictly superior or superior |
37 | | /// or equal (see [`Config::or_equal`]) to the value in this field. |
38 | | pub key_before: K, |
39 | | |
40 | | /// If `true`, also include the node whose key is equal to [`Config::key_before`] (if any). |
41 | | /// If `false`, only nodes whose key is strictly superior will be searched. |
42 | | pub or_equal: bool, |
43 | | |
44 | | /// Only search nodes whose key starts with the list of nibbles given in this field. |
45 | | pub prefix: P, |
46 | | |
47 | | /// If `true`, only return nodes that have a storage value associated to them. |
48 | | /// |
49 | | /// > **Note**: This option is provided as a convenience. The entire point of this search |
50 | | /// > is to find branch nodes when only storage nodes are known. |
51 | | pub no_branch_search: bool, |
52 | | } |
53 | | |
54 | | /// Start the search algorithm. |
55 | | // TODO: maybe rename things a bit? it's weird that `NextKey` is returned |
56 | 551k | pub fn start_branch_search( |
57 | 551k | config: Config<impl Iterator<Item = Nibble>, impl Iterator<Item = Nibble>>, |
58 | 551k | ) -> NextKey { |
59 | 551k | NextKey { |
60 | 551k | prefix: config.prefix.collect(), |
61 | 551k | key_before: config.key_before.collect(), |
62 | 551k | or_equal: config.or_equal, |
63 | 551k | inner: NextKeyInner::FirstFound { |
64 | 551k | no_branch_search: config.no_branch_search, |
65 | 551k | }, |
66 | 551k | } |
67 | 551k | } _RINvNtNtCsN16ciHI6Qf_7smoldot4trie13branch_search19start_branch_searchINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterNtNtB4_6nibble6NibbleEB16_EB6_ Line | Count | Source | 56 | 8.25k | pub fn start_branch_search( | 57 | 8.25k | config: Config<impl Iterator<Item = Nibble>, impl Iterator<Item = Nibble>>, | 58 | 8.25k | ) -> NextKey { | 59 | 8.25k | NextKey { | 60 | 8.25k | prefix: config.prefix.collect(), | 61 | 8.25k | key_before: config.key_before.collect(), | 62 | 8.25k | or_equal: config.or_equal, | 63 | 8.25k | inner: NextKeyInner::FirstFound { | 64 | 8.25k | no_branch_search: config.no_branch_search, | 65 | 8.25k | }, | 66 | 8.25k | } | 67 | 8.25k | } |
_RINvNtNtCsN16ciHI6Qf_7smoldot4trie13branch_search19start_branch_searchINtNtNtNtCsaYZPK01V26L_4core4iter8adapters6copied6CopiedINtNtNtB1f_5slice4iter4IterNtNtB4_6nibble6NibbleEEB16_EB6_ Line | Count | Source | 56 | 524k | pub fn start_branch_search( | 57 | 524k | config: Config<impl Iterator<Item = Nibble>, impl Iterator<Item = Nibble>>, | 58 | 524k | ) -> NextKey { | 59 | 524k | NextKey { | 60 | 524k | prefix: config.prefix.collect(), | 61 | 524k | key_before: config.key_before.collect(), | 62 | 524k | or_equal: config.or_equal, | 63 | 524k | inner: NextKeyInner::FirstFound { | 64 | 524k | no_branch_search: config.no_branch_search, | 65 | 524k | }, | 66 | 524k | } | 67 | 524k | } |
_RINvNtNtCsN16ciHI6Qf_7smoldot4trie13branch_search19start_branch_searchINtNtNtNtCsaYZPK01V26L_4core4iter8adapters7flatten7FlatMapINtNtNtB1f_5slice4iter4IterNtNtB4_14calculate_root4NodeEINtNtB1b_5chain5ChainINtNtB1b_6copied6CopiedIB23_NtNtB4_6nibble6NibbleEEINtNtB1f_6option8IntoIterB3J_EENCNvMB2v_NtB2v_9CalcInner26current_iter_node_full_key0EB16_EB6_ Line | Count | Source | 56 | 2.48k | pub fn start_branch_search( | 57 | 2.48k | config: Config<impl Iterator<Item = Nibble>, impl Iterator<Item = Nibble>>, | 58 | 2.48k | ) -> NextKey { | 59 | 2.48k | NextKey { | 60 | 2.48k | prefix: config.prefix.collect(), | 61 | 2.48k | key_before: config.key_before.collect(), | 62 | 2.48k | or_equal: config.or_equal, | 63 | 2.48k | inner: NextKeyInner::FirstFound { | 64 | 2.48k | no_branch_search: config.no_branch_search, | 65 | 2.48k | }, | 66 | 2.48k | } | 67 | 2.48k | } |
_RINvNtNtCseuYC0Zibziv_7smoldot4trie13branch_search19start_branch_searchINtNtNtNtCsaYZPK01V26L_4core4iter8adapters7flatten7FlatMapINtNtNtB1g_5slice4iter4IterNtNtB4_14calculate_root4NodeEINtNtB1c_5chain5ChainINtNtB1c_6copied6CopiedIB24_NtNtB4_6nibble6NibbleEEINtNtB1g_6option8IntoIterB3K_EENCNvMB2w_NtB2w_9CalcInner26current_iter_node_full_key0EB17_EB6_ Line | Count | Source | 56 | 16.1k | pub fn start_branch_search( | 57 | 16.1k | config: Config<impl Iterator<Item = Nibble>, impl Iterator<Item = Nibble>>, | 58 | 16.1k | ) -> NextKey { | 59 | 16.1k | NextKey { | 60 | 16.1k | prefix: config.prefix.collect(), | 61 | 16.1k | key_before: config.key_before.collect(), | 62 | 16.1k | or_equal: config.or_equal, | 63 | 16.1k | inner: NextKeyInner::FirstFound { | 64 | 16.1k | no_branch_search: config.no_branch_search, | 65 | 16.1k | }, | 66 | 16.1k | } | 67 | 16.1k | } |
|
68 | | |
69 | | /// Progress in the search algorithm. |
70 | | pub enum BranchSearch { |
71 | | /// In order to continue, the API user must indicate the trie node with a storage value that |
72 | | /// immediately follows a given one. |
73 | | NextKey(NextKey), |
74 | | /// Search has finished successfully. |
75 | | Found { |
76 | | /// Result of the search. `None` if there is no branch/storage node after |
77 | | /// [`Config::key_before`] in the trie. |
78 | | branch_trie_node_key: Option<BranchTrieNodeKeyIter>, |
79 | | }, |
80 | | } |
81 | | |
82 | | /// Implementation of `Iterator<Item = Nibble>`. See [`BranchSearch::Found::branch_trie_node_key`]. |
83 | | pub struct BranchTrieNodeKeyIter { |
84 | | inner: IntoIter<Nibble>, |
85 | | } |
86 | | |
87 | | impl Iterator for BranchTrieNodeKeyIter { |
88 | | type Item = Nibble; |
89 | | |
90 | 603k | fn next(&mut self) -> Option<Self::Item> { |
91 | 603k | self.inner.next() |
92 | 603k | } _RNvXNtNtCsN16ciHI6Qf_7smoldot4trie13branch_searchNtB2_21BranchTrieNodeKeyIterNtNtNtNtCsaYZPK01V26L_4core4iter6traits8iterator8Iterator4next Line | Count | Source | 90 | 524k | fn next(&mut self) -> Option<Self::Item> { | 91 | 524k | self.inner.next() | 92 | 524k | } |
_RNvXNtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB2_21BranchTrieNodeKeyIterNtNtNtNtCsaYZPK01V26L_4core4iter6traits8iterator8Iterator4next Line | Count | Source | 90 | 79.3k | fn next(&mut self) -> Option<Self::Item> { | 91 | 79.3k | self.inner.next() | 92 | 79.3k | } |
|
93 | | |
94 | 92.1k | fn size_hint(&self) -> (usize, Option<usize>) { |
95 | 92.1k | self.inner.size_hint() |
96 | 92.1k | } _RNvXNtNtCsN16ciHI6Qf_7smoldot4trie13branch_searchNtB2_21BranchTrieNodeKeyIterNtNtNtNtCsaYZPK01V26L_4core4iter6traits8iterator8Iterator9size_hint Line | Count | Source | 94 | 91.2k | fn size_hint(&self) -> (usize, Option<usize>) { | 95 | 91.2k | self.inner.size_hint() | 96 | 91.2k | } |
_RNvXNtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB2_21BranchTrieNodeKeyIterNtNtNtNtCsaYZPK01V26L_4core4iter6traits8iterator8Iterator9size_hint Line | Count | Source | 94 | 882 | fn size_hint(&self) -> (usize, Option<usize>) { | 95 | 882 | self.inner.size_hint() | 96 | 882 | } |
|
97 | | } |
98 | | |
99 | | impl ExactSizeIterator for BranchTrieNodeKeyIter {} |
100 | | |
101 | | /// In order to continue, the API user must indicate the trie node with a storage value that |
102 | | /// immediately follows a given one. |
103 | | pub struct NextKey { |
104 | | inner: NextKeyInner, |
105 | | /// Value passed as [`Config::key_before`]. |
106 | | key_before: Vec<Nibble>, |
107 | | /// Value passed as [`Config::prefix`]. |
108 | | prefix: Vec<Nibble>, |
109 | | /// Value passed as [`Config::or_equal`]. |
110 | | or_equal: bool, |
111 | | } |
112 | | |
113 | | enum NextKeyInner { |
114 | | FirstFound { |
115 | | /// Value passed as [`Config::no_branch_search`]. |
116 | | no_branch_search: bool, |
117 | | }, |
118 | | FurtherRound { |
119 | | /// Must never be empty and must never contain only `f` nibbles. |
120 | | current_found_branch: Vec<Nibble>, |
121 | | }, |
122 | | } |
123 | | |
124 | | impl NextKey { |
125 | | /// The API user must provide the trie node with a storage value whose key is the first one |
126 | | /// that is strictly superior or superior or equal to the key returned by this function. |
127 | 2.04M | pub fn key_before(&'_ self) -> impl Iterator<Item = u8> + '_ { |
128 | 2.04M | trie::nibbles_to_bytes_suffix_extend(match &self.inner { |
129 | 1.85M | NextKeyInner::FirstFound { .. } => either::Left(self.key_before.iter().copied()), |
130 | | NextKeyInner::FurtherRound { |
131 | 190k | current_found_branch, |
132 | 190k | } => { |
133 | 190k | let num_f_nibbles_to_pop = current_found_branch |
134 | 190k | .iter() |
135 | 190k | .rev() |
136 | 202k | .take_while(|n| **n == Nibble::max()) _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot4trie13branch_searchNtB7_7NextKey10key_before0Bb_ Line | Count | Source | 136 | 201k | .take_while(|n| **n == Nibble::max()) |
_RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB7_7NextKey10key_before0Bb_ Line | Count | Source | 136 | 1.34k | .take_while(|n| **n == Nibble::max()) |
|
137 | 190k | .count(); |
138 | 190k | debug_assert!(num_f_nibbles_to_pop < current_found_branch.len()); |
139 | | |
140 | 190k | let len = current_found_branch.len(); |
141 | 190k | let extra_nibble = current_found_branch[len - num_f_nibbles_to_pop - 1] |
142 | 190k | .checked_add(1) |
143 | 190k | .unwrap_or_else(|| unreachable!()0 ); Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot4trie13branch_searchNtB7_7NextKey10key_befores_0Bb_ Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB7_7NextKey10key_befores_0Bb_ |
144 | 190k | |
145 | 190k | either::Right( |
146 | 190k | current_found_branch |
147 | 190k | .iter() |
148 | 190k | .take(len - num_f_nibbles_to_pop - 1) |
149 | 190k | .copied() |
150 | 190k | .chain(iter::once(extra_nibble)), |
151 | 190k | ) |
152 | | } |
153 | | }) |
154 | 2.04M | } _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot4trie13branch_searchNtB5_7NextKey10key_before Line | Count | Source | 127 | 2.02M | pub fn key_before(&'_ self) -> impl Iterator<Item = u8> + '_ { | 128 | 2.02M | trie::nibbles_to_bytes_suffix_extend(match &self.inner { | 129 | 1.83M | NextKeyInner::FirstFound { .. } => either::Left(self.key_before.iter().copied()), | 130 | | NextKeyInner::FurtherRound { | 131 | 189k | current_found_branch, | 132 | 189k | } => { | 133 | 189k | let num_f_nibbles_to_pop = current_found_branch | 134 | 189k | .iter() | 135 | 189k | .rev() | 136 | 189k | .take_while(|n| **n == Nibble::max()) | 137 | 189k | .count(); | 138 | 189k | debug_assert!(num_f_nibbles_to_pop < current_found_branch.len()); | 139 | | | 140 | 189k | let len = current_found_branch.len(); | 141 | 189k | let extra_nibble = current_found_branch[len - num_f_nibbles_to_pop - 1] | 142 | 189k | .checked_add(1) | 143 | 189k | .unwrap_or_else(|| unreachable!()); | 144 | 189k | | 145 | 189k | either::Right( | 146 | 189k | current_found_branch | 147 | 189k | .iter() | 148 | 189k | .take(len - num_f_nibbles_to_pop - 1) | 149 | 189k | .copied() | 150 | 189k | .chain(iter::once(extra_nibble)), | 151 | 189k | ) | 152 | | } | 153 | | }) | 154 | 2.02M | } |
_RNvMs0_NtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB5_7NextKey10key_before Line | Count | Source | 127 | 17.4k | pub fn key_before(&'_ self) -> impl Iterator<Item = u8> + '_ { | 128 | 17.4k | trie::nibbles_to_bytes_suffix_extend(match &self.inner { | 129 | 16.1k | NextKeyInner::FirstFound { .. } => either::Left(self.key_before.iter().copied()), | 130 | | NextKeyInner::FurtherRound { | 131 | 1.30k | current_found_branch, | 132 | 1.30k | } => { | 133 | 1.30k | let num_f_nibbles_to_pop = current_found_branch | 134 | 1.30k | .iter() | 135 | 1.30k | .rev() | 136 | 1.30k | .take_while(|n| **n == Nibble::max()) | 137 | 1.30k | .count(); | 138 | 1.30k | debug_assert!(num_f_nibbles_to_pop < current_found_branch.len()); | 139 | | | 140 | 1.30k | let len = current_found_branch.len(); | 141 | 1.30k | let extra_nibble = current_found_branch[len - num_f_nibbles_to_pop - 1] | 142 | 1.30k | .checked_add(1) | 143 | 1.30k | .unwrap_or_else(|| unreachable!()); | 144 | 1.30k | | 145 | 1.30k | either::Right( | 146 | 1.30k | current_found_branch | 147 | 1.30k | .iter() | 148 | 1.30k | .take(len - num_f_nibbles_to_pop - 1) | 149 | 1.30k | .copied() | 150 | 1.30k | .chain(iter::once(extra_nibble)), | 151 | 1.30k | ) | 152 | | } | 153 | | }) | 154 | 17.4k | } |
|
155 | | |
156 | | /// If `true`, if the key returned by [`NextKey::key_before`] corresponds to a trie node with |
157 | | /// a storage value, then the API user must indicate it. If `false`, it must indicate the key |
158 | | /// strictly superior. |
159 | 85.4k | pub fn or_equal(&self) -> bool { |
160 | 85.4k | match self.inner { |
161 | | NextKeyInner::FirstFound { .. } => { |
162 | | // If `key_before` is for example `0xa`, `key_before()` will return `0xa0` due to |
163 | | // the usage of `nibbles_to_bytes_suffix_extend`. For this reason, we have to |
164 | | // always return `true` if the number of nibbles in `key_before` is uneven. |
165 | 83.3k | self.or_equal || (self.key_before.len() % 2 != 0)29.2k |
166 | | } |
167 | 2.08k | NextKeyInner::FurtherRound { .. } => true, |
168 | | } |
169 | 85.4k | } _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot4trie13branch_searchNtB5_7NextKey8or_equal Line | Count | Source | 159 | 68.0k | pub fn or_equal(&self) -> bool { | 160 | 68.0k | match self.inner { | 161 | | NextKeyInner::FirstFound { .. } => { | 162 | | // If `key_before` is for example `0xa`, `key_before()` will return `0xa0` due to | 163 | | // the usage of `nibbles_to_bytes_suffix_extend`. For this reason, we have to | 164 | | // always return `true` if the number of nibbles in `key_before` is uneven. | 165 | 67.2k | self.or_equal || (self.key_before.len() % 2 != 0)29.2k | 166 | | } | 167 | 787 | NextKeyInner::FurtherRound { .. } => true, | 168 | | } | 169 | 68.0k | } |
_RNvMs0_NtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB5_7NextKey8or_equal Line | Count | Source | 159 | 17.4k | pub fn or_equal(&self) -> bool { | 160 | 17.4k | match self.inner { | 161 | | NextKeyInner::FirstFound { .. } => { | 162 | | // If `key_before` is for example `0xa`, `key_before()` will return `0xa0` due to | 163 | | // the usage of `nibbles_to_bytes_suffix_extend`. For this reason, we have to | 164 | | // always return `true` if the number of nibbles in `key_before` is uneven. | 165 | 16.1k | self.or_equal || (self.key_before.len() % 2 != 0)0 | 166 | | } | 167 | 1.30k | NextKeyInner::FurtherRound { .. } => true, | 168 | | } | 169 | 17.4k | } |
|
170 | | |
171 | | /// The API user must indicate a key that starts with the bytes returned by this function. |
172 | | /// If the first key doesn't start with these bytes, then the API user must indicate `None`. |
173 | 482k | pub fn prefix(&'_ self) -> impl Iterator<Item = u8> + '_ { |
174 | 482k | trie::nibbles_to_bytes_truncate(self.prefix.iter().copied()) |
175 | 482k | } _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot4trie13branch_searchNtB5_7NextKey6prefix Line | Count | Source | 173 | 465k | pub fn prefix(&'_ self) -> impl Iterator<Item = u8> + '_ { | 174 | 465k | trie::nibbles_to_bytes_truncate(self.prefix.iter().copied()) | 175 | 465k | } |
_RNvMs0_NtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB5_7NextKey6prefix Line | Count | Source | 173 | 17.4k | pub fn prefix(&'_ self) -> impl Iterator<Item = u8> + '_ { | 174 | 17.4k | trie::nibbles_to_bytes_truncate(self.prefix.iter().copied()) | 175 | 17.4k | } |
|
176 | | |
177 | | /// Indicate the key. `None` must be passed if [`NextKey::key_before`] is the last key of |
178 | | /// the sub-trie that starts with [`NextKey::prefix`]. |
179 | 600k | pub fn inject( |
180 | 600k | mut self, |
181 | 600k | storage_trie_node_key: Option<impl Iterator<Item = u8>>, |
182 | 600k | ) -> BranchSearch { |
183 | 600k | match (self.inner, storage_trie_node_key) { |
184 | | // No matter what, if we're at the first round and the user injected `None`, that |
185 | | // means `key_before` is equal or superior to the last key of the trie and thus there |
186 | | // can't be any branch node after it. |
187 | 353k | (NextKeyInner::FirstFound { .. }, None) => BranchSearch::Found { |
188 | 353k | branch_trie_node_key: None, |
189 | 353k | }, |
190 | | |
191 | | // If `no_branch_search` is `true`, simply immediately return the value provided by |
192 | | // the user. |
193 | | ( |
194 | | NextKeyInner::FirstFound { |
195 | | no_branch_search: true, |
196 | | .. |
197 | | }, |
198 | 96.9k | Some(storage_trie_node_key), |
199 | 96.9k | ) => { |
200 | 96.9k | let storage_trie_node_key = |
201 | 96.9k | trie::bytes_to_nibbles(storage_trie_node_key).collect::<Vec<_>>(); |
202 | 96.9k | debug_assert!(storage_trie_node_key >= self.key_before); |
203 | | |
204 | | // Due to our usage of `nibbles_to_bytes_truncate` in `prefix()`, we must check |
205 | | // whether the value provided by the user is still within the prefix. |
206 | 96.9k | if !storage_trie_node_key.starts_with(&self.prefix) { |
207 | 37.3k | return BranchSearch::Found { |
208 | 37.3k | branch_trie_node_key: None, |
209 | 37.3k | }; |
210 | 59.6k | } |
211 | 59.6k | |
212 | 59.6k | BranchSearch::Found { |
213 | 59.6k | branch_trie_node_key: Some(BranchTrieNodeKeyIter { |
214 | 59.6k | inner: storage_trie_node_key.into_iter(), |
215 | 59.6k | }), |
216 | 59.6k | } |
217 | | } |
218 | | |
219 | | ( |
220 | | NextKeyInner::FirstFound { |
221 | | no_branch_search: false, |
222 | | .. |
223 | | }, |
224 | 100k | Some(storage_trie_node_key), |
225 | 100k | ) => { |
226 | 100k | let storage_trie_node_key = |
227 | 100k | trie::bytes_to_nibbles(storage_trie_node_key).collect::<Vec<_>>(); |
228 | 100k | debug_assert!(storage_trie_node_key >= self.key_before); |
229 | | |
230 | | // Due to our usage of `nibbles_to_bytes_truncate` in `prefix()`, we must check |
231 | | // whether the value provided by the user is still within the prefix. |
232 | 100k | if !storage_trie_node_key.starts_with(&self.prefix) { |
233 | 39.0k | return BranchSearch::Found { |
234 | 39.0k | branch_trie_node_key: None, |
235 | 39.0k | }; |
236 | 61.9k | } |
237 | 61.9k | |
238 | 61.9k | if storage_trie_node_key.is_empty() |
239 | 50.8k | || storage_trie_node_key.iter().all(47.3k |n| *n == Nibble::max())47.3k _RNCINvMs0_NtNtCsN16ciHI6Qf_7smoldot4trie13branch_searchNtB8_7NextKey6injectINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEE0Bc_ Line | Count | Source | 239 | 123 | || storage_trie_node_key.iter().all(|n| *n == Nibble::max()) |
_RNCINvMs0_NtNtCsN16ciHI6Qf_7smoldot4trie13branch_searchNtB8_7NextKey6injectINtNtNtNtCsaYZPK01V26L_4core4iter8adapters6copied6CopiedINtNtNtB1k_5slice4iter4IterhEEE0Bc_ Line | Count | Source | 239 | 508 | || storage_trie_node_key.iter().all(|n| *n == Nibble::max()) |
_RNCINvMs0_NtNtCsN16ciHI6Qf_7smoldot4trie13branch_searchNtB8_7NextKey6injectINtNvNtBa_6nibble30nibbles_to_bytes_suffix_extend4IterINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterNtB1g_6NibbleEEE0Bc_ Line | Count | Source | 239 | 49.2k | || storage_trie_node_key.iter().all(|n| *n == Nibble::max()) |
Unexecuted instantiation: _RNCINvMs0_NtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB8_7NextKey6injectINtNtNtNtCsaYZPK01V26L_4core4iter8adapters6copied6CopiedINtNtNtB1l_5slice4iter4IterhEEE0CsDDUKWWCHAU_18smoldot_light_wasm _RNCINvMs0_NtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB8_7NextKey6injectINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEE0Bc_ Line | Count | Source | 239 | 1.02k | || storage_trie_node_key.iter().all(|n| *n == Nibble::max()) |
Unexecuted instantiation: _RNCINvMs0_NtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB8_7NextKey6injectINtNtNtNtCsaYZPK01V26L_4core4iter8adapters6copied6CopiedINtNtNtB1l_5slice4iter4IterhEEE0Bc_ Unexecuted instantiation: _RNCINvMs0_NtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB8_7NextKey6injectINtNtNtNtCsaYZPK01V26L_4core4iter8adapters6copied6CopiedINtNtNtB1l_5slice4iter4IterhEEE0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs0_NtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB8_7NextKey6injectINtNtNtNtCsaYZPK01V26L_4core4iter8adapters6copied6CopiedINtNtNtB1l_5slice4iter4IterhEEE0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs0_NtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB8_7NextKey6injectINtNtNtNtCsaYZPK01V26L_4core4iter8adapters6copied6CopiedINtNtNtB1l_5slice4iter4IterhEEE0CsibGXYHQB8Ea_25json_rpc_general_requests |
240 | | { |
241 | 14.5k | return BranchSearch::Found { |
242 | 14.5k | branch_trie_node_key: Some(BranchTrieNodeKeyIter { |
243 | 14.5k | inner: storage_trie_node_key.into_iter(), |
244 | 14.5k | }), |
245 | 14.5k | }; |
246 | 47.3k | } |
247 | 47.3k | |
248 | 47.3k | self.inner = NextKeyInner::FurtherRound { |
249 | 47.3k | current_found_branch: storage_trie_node_key, |
250 | 47.3k | }; |
251 | 47.3k | BranchSearch::NextKey(self) |
252 | | } |
253 | | |
254 | | ( |
255 | | NextKeyInner::FurtherRound { |
256 | 25.3k | mut current_found_branch, |
257 | 25.3k | }, |
258 | 25.3k | Some(storage_trie_node_key), |
259 | 25.3k | ) => { |
260 | 25.3k | let storage_trie_node_key = trie::bytes_to_nibbles(storage_trie_node_key); |
261 | 25.3k | |
262 | 25.3k | let num_common = storage_trie_node_key |
263 | 25.3k | .zip(current_found_branch.iter()) |
264 | 75.2k | .take_while(|(a, b)| a == *b) _RNCINvMs0_NtNtCsN16ciHI6Qf_7smoldot4trie13branch_searchNtB8_7NextKey6injectINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEs_0Bc_ Line | Count | Source | 264 | 4.06k | .take_while(|(a, b)| a == *b) |
_RNCINvMs0_NtNtCsN16ciHI6Qf_7smoldot4trie13branch_searchNtB8_7NextKey6injectINtNtNtNtCsaYZPK01V26L_4core4iter8adapters6copied6CopiedINtNtNtB1k_5slice4iter4IterhEEEs_0Bc_ Line | Count | Source | 264 | 15.5k | .take_while(|(a, b)| a == *b) |
_RNCINvMs0_NtNtCsN16ciHI6Qf_7smoldot4trie13branch_searchNtB8_7NextKey6injectINtNvNtBa_6nibble30nibbles_to_bytes_suffix_extend4IterINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterNtB1g_6NibbleEEEs_0Bc_ Line | Count | Source | 264 | 26.2k | .take_while(|(a, b)| a == *b) |
Unexecuted instantiation: _RNCINvMs0_NtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB8_7NextKey6injectINtNtNtNtCsaYZPK01V26L_4core4iter8adapters6copied6CopiedINtNtNtB1l_5slice4iter4IterhEEEs_0CsDDUKWWCHAU_18smoldot_light_wasm _RNCINvMs0_NtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB8_7NextKey6injectINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEs_0Bc_ Line | Count | Source | 264 | 29.3k | .take_while(|(a, b)| a == *b) |
Unexecuted instantiation: _RNCINvMs0_NtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB8_7NextKey6injectINtNtNtNtCsaYZPK01V26L_4core4iter8adapters6copied6CopiedINtNtNtB1l_5slice4iter4IterhEEEs_0Bc_ Unexecuted instantiation: _RNCINvMs0_NtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB8_7NextKey6injectINtNtNtNtCsaYZPK01V26L_4core4iter8adapters6copied6CopiedINtNtNtB1l_5slice4iter4IterhEEEs_0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs0_NtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB8_7NextKey6injectINtNtNtNtCsaYZPK01V26L_4core4iter8adapters6copied6CopiedINtNtNtB1l_5slice4iter4IterhEEEs_0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs0_NtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB8_7NextKey6injectINtNtNtNtCsaYZPK01V26L_4core4iter8adapters6copied6CopiedINtNtNtB1l_5slice4iter4IterhEEEs_0CsibGXYHQB8Ea_25json_rpc_general_requests |
265 | 25.3k | .count(); |
266 | 25.3k | |
267 | 25.3k | // Check against infinite loops. |
268 | 25.3k | debug_assert!(num_common < current_found_branch.len()); |
269 | | |
270 | 25.3k | if !current_found_branch[..num_common].starts_with(&self.prefix) |
271 | 21.7k | || ¤t_found_branch[..num_common] < &self.key_before |
272 | 9.56k | || (!self.or_equal && current_found_branch[..num_common] == self.key_before8.21k ) |
273 | | { |
274 | 22.7k | return BranchSearch::Found { |
275 | 22.7k | branch_trie_node_key: Some(BranchTrieNodeKeyIter { |
276 | 22.7k | inner: current_found_branch.into_iter(), |
277 | 22.7k | }), |
278 | 22.7k | }; |
279 | 2.55k | } |
280 | 2.55k | |
281 | 2.55k | current_found_branch.truncate(num_common); |
282 | 2.55k | |
283 | 2.55k | if current_found_branch.is_empty() |
284 | 2.53k | || current_found_branch.iter().all(2.52k |n| *n == Nibble::max())2.52k _RNCINvMs0_NtNtCsN16ciHI6Qf_7smoldot4trie13branch_searchNtB8_7NextKey6injectINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEs0_0Bc_ Line | Count | Source | 284 | 37 | || current_found_branch.iter().all(|n| *n == Nibble::max()) |
_RNCINvMs0_NtNtCsN16ciHI6Qf_7smoldot4trie13branch_searchNtB8_7NextKey6injectINtNtNtNtCsaYZPK01V26L_4core4iter8adapters6copied6CopiedINtNtNtB1k_5slice4iter4IterhEEEs0_0Bc_ Line | Count | Source | 284 | 183 | || current_found_branch.iter().all(|n| *n == Nibble::max()) |
_RNCINvMs0_NtNtCsN16ciHI6Qf_7smoldot4trie13branch_searchNtB8_7NextKey6injectINtNvNtBa_6nibble30nibbles_to_bytes_suffix_extend4IterINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterNtB1g_6NibbleEEEs0_0Bc_ Line | Count | Source | 284 | 2.02k | || current_found_branch.iter().all(|n| *n == Nibble::max()) |
Unexecuted instantiation: _RNCINvMs0_NtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB8_7NextKey6injectINtNtNtNtCsaYZPK01V26L_4core4iter8adapters6copied6CopiedINtNtNtB1l_5slice4iter4IterhEEEs0_0CsDDUKWWCHAU_18smoldot_light_wasm _RNCINvMs0_NtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB8_7NextKey6injectINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEs0_0Bc_ Line | Count | Source | 284 | 294 | || current_found_branch.iter().all(|n| *n == Nibble::max()) |
Unexecuted instantiation: _RNCINvMs0_NtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB8_7NextKey6injectINtNtNtNtCsaYZPK01V26L_4core4iter8adapters6copied6CopiedINtNtNtB1l_5slice4iter4IterhEEEs0_0Bc_ Unexecuted instantiation: _RNCINvMs0_NtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB8_7NextKey6injectINtNtNtNtCsaYZPK01V26L_4core4iter8adapters6copied6CopiedINtNtNtB1l_5slice4iter4IterhEEEs0_0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs0_NtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB8_7NextKey6injectINtNtNtNtCsaYZPK01V26L_4core4iter8adapters6copied6CopiedINtNtNtB1l_5slice4iter4IterhEEEs0_0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs0_NtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB8_7NextKey6injectINtNtNtNtCsaYZPK01V26L_4core4iter8adapters6copied6CopiedINtNtNtB1l_5slice4iter4IterhEEEs0_0CsibGXYHQB8Ea_25json_rpc_general_requests |
285 | | { |
286 | 225 | return BranchSearch::Found { |
287 | 225 | branch_trie_node_key: Some(BranchTrieNodeKeyIter { |
288 | 225 | inner: current_found_branch.into_iter(), |
289 | 225 | }), |
290 | 225 | }; |
291 | 2.33k | } |
292 | 2.33k | |
293 | 2.33k | self.inner = NextKeyInner::FurtherRound { |
294 | 2.33k | current_found_branch, |
295 | 2.33k | }; |
296 | 2.33k | BranchSearch::NextKey(self) |
297 | | } |
298 | | |
299 | | // If `current_found_branch` doesn't have any sibling or uncle after it, then we know |
300 | | // that there can't be any more branch node and the search is over. |
301 | | ( |
302 | | NextKeyInner::FurtherRound { |
303 | 24.3k | current_found_branch, |
304 | 24.3k | }, |
305 | 24.3k | None, |
306 | 24.3k | ) => BranchSearch::Found { |
307 | 24.3k | branch_trie_node_key: Some(BranchTrieNodeKeyIter { |
308 | 24.3k | inner: current_found_branch.into_iter(), |
309 | 24.3k | }), |
310 | 24.3k | }, |
311 | | } |
312 | 600k | } _RINvMs0_NtNtCsN16ciHI6Qf_7smoldot4trie13branch_searchNtB6_7NextKey6injectINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEBa_ Line | Count | Source | 179 | 2.04k | pub fn inject( | 180 | 2.04k | mut self, | 181 | 2.04k | storage_trie_node_key: Option<impl Iterator<Item = u8>>, | 182 | 2.04k | ) -> BranchSearch { | 183 | 2.04k | match (self.inner, storage_trie_node_key) { | 184 | | // No matter what, if we're at the first round and the user injected `None`, that | 185 | | // means `key_before` is equal or superior to the last key of the trie and thus there | 186 | | // can't be any branch node after it. | 187 | 1.63k | (NextKeyInner::FirstFound { .. }, None) => BranchSearch::Found { | 188 | 1.63k | branch_trie_node_key: None, | 189 | 1.63k | }, | 190 | | | 191 | | // If `no_branch_search` is `true`, simply immediately return the value provided by | 192 | | // the user. | 193 | | ( | 194 | | NextKeyInner::FirstFound { | 195 | | no_branch_search: true, | 196 | | .. | 197 | | }, | 198 | 0 | Some(storage_trie_node_key), | 199 | 0 | ) => { | 200 | 0 | let storage_trie_node_key = | 201 | 0 | trie::bytes_to_nibbles(storage_trie_node_key).collect::<Vec<_>>(); | 202 | 0 | debug_assert!(storage_trie_node_key >= self.key_before); | 203 | | | 204 | | // Due to our usage of `nibbles_to_bytes_truncate` in `prefix()`, we must check | 205 | | // whether the value provided by the user is still within the prefix. | 206 | 0 | if !storage_trie_node_key.starts_with(&self.prefix) { | 207 | 0 | return BranchSearch::Found { | 208 | 0 | branch_trie_node_key: None, | 209 | 0 | }; | 210 | 0 | } | 211 | 0 |
| 212 | 0 | BranchSearch::Found { | 213 | 0 | branch_trie_node_key: Some(BranchTrieNodeKeyIter { | 214 | 0 | inner: storage_trie_node_key.into_iter(), | 215 | 0 | }), | 216 | 0 | } | 217 | | } | 218 | | | 219 | | ( | 220 | | NextKeyInner::FirstFound { | 221 | | no_branch_search: false, | 222 | | .. | 223 | | }, | 224 | 250 | Some(storage_trie_node_key), | 225 | 250 | ) => { | 226 | 250 | let storage_trie_node_key = | 227 | 250 | trie::bytes_to_nibbles(storage_trie_node_key).collect::<Vec<_>>(); | 228 | 250 | debug_assert!(storage_trie_node_key >= self.key_before); | 229 | | | 230 | | // Due to our usage of `nibbles_to_bytes_truncate` in `prefix()`, we must check | 231 | | // whether the value provided by the user is still within the prefix. | 232 | 250 | if !storage_trie_node_key.starts_with(&self.prefix) { | 233 | 132 | return BranchSearch::Found { | 234 | 132 | branch_trie_node_key: None, | 235 | 132 | }; | 236 | 118 | } | 237 | 118 | | 238 | 118 | if storage_trie_node_key.is_empty() | 239 | 118 | || storage_trie_node_key.iter().all(|n| *n == Nibble::max()) | 240 | | { | 241 | 0 | return BranchSearch::Found { | 242 | 0 | branch_trie_node_key: Some(BranchTrieNodeKeyIter { | 243 | 0 | inner: storage_trie_node_key.into_iter(), | 244 | 0 | }), | 245 | 0 | }; | 246 | 118 | } | 247 | 118 | | 248 | 118 | self.inner = NextKeyInner::FurtherRound { | 249 | 118 | current_found_branch: storage_trie_node_key, | 250 | 118 | }; | 251 | 118 | BranchSearch::NextKey(self) | 252 | | } | 253 | | | 254 | | ( | 255 | | NextKeyInner::FurtherRound { | 256 | 104 | mut current_found_branch, | 257 | 104 | }, | 258 | 104 | Some(storage_trie_node_key), | 259 | 104 | ) => { | 260 | 104 | let storage_trie_node_key = trie::bytes_to_nibbles(storage_trie_node_key); | 261 | 104 | | 262 | 104 | let num_common = storage_trie_node_key | 263 | 104 | .zip(current_found_branch.iter()) | 264 | 104 | .take_while(|(a, b)| a == *b) | 265 | 104 | .count(); | 266 | 104 | | 267 | 104 | // Check against infinite loops. | 268 | 104 | debug_assert!(num_common < current_found_branch.len()); | 269 | | | 270 | 104 | if !current_found_branch[..num_common].starts_with(&self.prefix) | 271 | 37 | || ¤t_found_branch[..num_common] < &self.key_before | 272 | 37 | || (!self.or_equal && current_found_branch[..num_common] == self.key_before0 ) | 273 | | { | 274 | 67 | return BranchSearch::Found { | 275 | 67 | branch_trie_node_key: Some(BranchTrieNodeKeyIter { | 276 | 67 | inner: current_found_branch.into_iter(), | 277 | 67 | }), | 278 | 67 | }; | 279 | 37 | } | 280 | 37 | | 281 | 37 | current_found_branch.truncate(num_common); | 282 | 37 | | 283 | 37 | if current_found_branch.is_empty() | 284 | 36 | || current_found_branch.iter().all(|n| *n == Nibble::max()) | 285 | | { | 286 | 1 | return BranchSearch::Found { | 287 | 1 | branch_trie_node_key: Some(BranchTrieNodeKeyIter { | 288 | 1 | inner: current_found_branch.into_iter(), | 289 | 1 | }), | 290 | 1 | }; | 291 | 36 | } | 292 | 36 | | 293 | 36 | self.inner = NextKeyInner::FurtherRound { | 294 | 36 | current_found_branch, | 295 | 36 | }; | 296 | 36 | BranchSearch::NextKey(self) | 297 | | } | 298 | | | 299 | | // If `current_found_branch` doesn't have any sibling or uncle after it, then we know | 300 | | // that there can't be any more branch node and the search is over. | 301 | | ( | 302 | | NextKeyInner::FurtherRound { | 303 | 50 | current_found_branch, | 304 | 50 | }, | 305 | 50 | None, | 306 | 50 | ) => BranchSearch::Found { | 307 | 50 | branch_trie_node_key: Some(BranchTrieNodeKeyIter { | 308 | 50 | inner: current_found_branch.into_iter(), | 309 | 50 | }), | 310 | 50 | }, | 311 | | } | 312 | 2.04k | } |
_RINvMs0_NtNtCsN16ciHI6Qf_7smoldot4trie13branch_searchNtB6_7NextKey6injectINtNtNtNtCsaYZPK01V26L_4core4iter8adapters6copied6CopiedINtNtNtB1i_5slice4iter4IterhEEEBa_ Line | Count | Source | 179 | 9.51k | pub fn inject( | 180 | 9.51k | mut self, | 181 | 9.51k | storage_trie_node_key: Option<impl Iterator<Item = u8>>, | 182 | 9.51k | ) -> BranchSearch { | 183 | 9.51k | match (self.inner, storage_trie_node_key) { | 184 | | // No matter what, if we're at the first round and the user injected `None`, that | 185 | | // means `key_before` is equal or superior to the last key of the trie and thus there | 186 | | // can't be any branch node after it. | 187 | 7.83k | (NextKeyInner::FirstFound { .. }, None) => BranchSearch::Found { | 188 | 7.83k | branch_trie_node_key: None, | 189 | 7.83k | }, | 190 | | | 191 | | // If `no_branch_search` is `true`, simply immediately return the value provided by | 192 | | // the user. | 193 | | ( | 194 | | NextKeyInner::FirstFound { | 195 | | no_branch_search: true, | 196 | | .. | 197 | | }, | 198 | 10 | Some(storage_trie_node_key), | 199 | 10 | ) => { | 200 | 10 | let storage_trie_node_key = | 201 | 10 | trie::bytes_to_nibbles(storage_trie_node_key).collect::<Vec<_>>(); | 202 | 10 | debug_assert!(storage_trie_node_key >= self.key_before); | 203 | | | 204 | | // Due to our usage of `nibbles_to_bytes_truncate` in `prefix()`, we must check | 205 | | // whether the value provided by the user is still within the prefix. | 206 | 10 | if !storage_trie_node_key.starts_with(&self.prefix) { | 207 | 0 | return BranchSearch::Found { | 208 | 0 | branch_trie_node_key: None, | 209 | 0 | }; | 210 | 10 | } | 211 | 10 | | 212 | 10 | BranchSearch::Found { | 213 | 10 | branch_trie_node_key: Some(BranchTrieNodeKeyIter { | 214 | 10 | inner: storage_trie_node_key.into_iter(), | 215 | 10 | }), | 216 | 10 | } | 217 | | } | 218 | | | 219 | | ( | 220 | | NextKeyInner::FirstFound { | 221 | | no_branch_search: false, | 222 | | .. | 223 | | }, | 224 | 1.00k | Some(storage_trie_node_key), | 225 | 1.00k | ) => { | 226 | 1.00k | let storage_trie_node_key = | 227 | 1.00k | trie::bytes_to_nibbles(storage_trie_node_key).collect::<Vec<_>>(); | 228 | 1.00k | debug_assert!(storage_trie_node_key >= self.key_before); | 229 | | | 230 | | // Due to our usage of `nibbles_to_bytes_truncate` in `prefix()`, we must check | 231 | | // whether the value provided by the user is still within the prefix. | 232 | 1.00k | if !storage_trie_node_key.starts_with(&self.prefix) { | 233 | 513 | return BranchSearch::Found { | 234 | 513 | branch_trie_node_key: None, | 235 | 513 | }; | 236 | 491 | } | 237 | 491 | | 238 | 491 | if storage_trie_node_key.is_empty() | 239 | 491 | || storage_trie_node_key.iter().all(|n| *n == Nibble::max()) | 240 | | { | 241 | 0 | return BranchSearch::Found { | 242 | 0 | branch_trie_node_key: Some(BranchTrieNodeKeyIter { | 243 | 0 | inner: storage_trie_node_key.into_iter(), | 244 | 0 | }), | 245 | 0 | }; | 246 | 491 | } | 247 | 491 | | 248 | 491 | self.inner = NextKeyInner::FurtherRound { | 249 | 491 | current_found_branch: storage_trie_node_key, | 250 | 491 | }; | 251 | 491 | BranchSearch::NextKey(self) | 252 | | } | 253 | | | 254 | | ( | 255 | | NextKeyInner::FurtherRound { | 256 | 416 | mut current_found_branch, | 257 | 416 | }, | 258 | 416 | Some(storage_trie_node_key), | 259 | 416 | ) => { | 260 | 416 | let storage_trie_node_key = trie::bytes_to_nibbles(storage_trie_node_key); | 261 | 416 | | 262 | 416 | let num_common = storage_trie_node_key | 263 | 416 | .zip(current_found_branch.iter()) | 264 | 416 | .take_while(|(a, b)| a == *b) | 265 | 416 | .count(); | 266 | 416 | | 267 | 416 | // Check against infinite loops. | 268 | 416 | debug_assert!(num_common < current_found_branch.len()); | 269 | | | 270 | 416 | if !current_found_branch[..num_common].starts_with(&self.prefix) | 271 | 185 | || ¤t_found_branch[..num_common] < &self.key_before | 272 | 185 | || (!self.or_equal && current_found_branch[..num_common] == self.key_before0 ) | 273 | | { | 274 | 231 | return BranchSearch::Found { | 275 | 231 | branch_trie_node_key: Some(BranchTrieNodeKeyIter { | 276 | 231 | inner: current_found_branch.into_iter(), | 277 | 231 | }), | 278 | 231 | }; | 279 | 185 | } | 280 | 185 | | 281 | 185 | current_found_branch.truncate(num_common); | 282 | 185 | | 283 | 185 | if current_found_branch.is_empty() | 284 | 178 | || current_found_branch.iter().all(|n| *n == Nibble::max()) | 285 | | { | 286 | 7 | return BranchSearch::Found { | 287 | 7 | branch_trie_node_key: Some(BranchTrieNodeKeyIter { | 288 | 7 | inner: current_found_branch.into_iter(), | 289 | 7 | }), | 290 | 7 | }; | 291 | 178 | } | 292 | 178 | | 293 | 178 | self.inner = NextKeyInner::FurtherRound { | 294 | 178 | current_found_branch, | 295 | 178 | }; | 296 | 178 | BranchSearch::NextKey(self) | 297 | | } | 298 | | | 299 | | // If `current_found_branch` doesn't have any sibling or uncle after it, then we know | 300 | | // that there can't be any more branch node and the search is over. | 301 | | ( | 302 | | NextKeyInner::FurtherRound { | 303 | 253 | current_found_branch, | 304 | 253 | }, | 305 | 253 | None, | 306 | 253 | ) => BranchSearch::Found { | 307 | 253 | branch_trie_node_key: Some(BranchTrieNodeKeyIter { | 308 | 253 | inner: current_found_branch.into_iter(), | 309 | 253 | }), | 310 | 253 | }, | 311 | | } | 312 | 9.51k | } |
_RINvMs0_NtNtCsN16ciHI6Qf_7smoldot4trie13branch_searchNtB6_7NextKey6injectINtNvNtB8_6nibble30nibbles_to_bytes_suffix_extend4IterINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterNtB1e_6NibbleEEEBa_ Line | Count | Source | 179 | 571k | pub fn inject( | 180 | 571k | mut self, | 181 | 571k | storage_trie_node_key: Option<impl Iterator<Item = u8>>, | 182 | 571k | ) -> BranchSearch { | 183 | 571k | match (self.inner, storage_trie_node_key) { | 184 | | // No matter what, if we're at the first round and the user injected `None`, that | 185 | | // means `key_before` is equal or superior to the last key of the trie and thus there | 186 | | // can't be any branch node after it. | 187 | 329k | (NextKeyInner::FirstFound { .. }, None) => BranchSearch::Found { | 188 | 329k | branch_trie_node_key: None, | 189 | 329k | }, | 190 | | | 191 | | // If `no_branch_search` is `true`, simply immediately return the value provided by | 192 | | // the user. | 193 | | ( | 194 | | NextKeyInner::FirstFound { | 195 | | no_branch_search: true, | 196 | | .. | 197 | | }, | 198 | 96.9k | Some(storage_trie_node_key), | 199 | 96.9k | ) => { | 200 | 96.9k | let storage_trie_node_key = | 201 | 96.9k | trie::bytes_to_nibbles(storage_trie_node_key).collect::<Vec<_>>(); | 202 | 96.9k | debug_assert!(storage_trie_node_key >= self.key_before); | 203 | | | 204 | | // Due to our usage of `nibbles_to_bytes_truncate` in `prefix()`, we must check | 205 | | // whether the value provided by the user is still within the prefix. | 206 | 96.9k | if !storage_trie_node_key.starts_with(&self.prefix) { | 207 | 37.3k | return BranchSearch::Found { | 208 | 37.3k | branch_trie_node_key: None, | 209 | 37.3k | }; | 210 | 59.6k | } | 211 | 59.6k | | 212 | 59.6k | BranchSearch::Found { | 213 | 59.6k | branch_trie_node_key: Some(BranchTrieNodeKeyIter { | 214 | 59.6k | inner: storage_trie_node_key.into_iter(), | 215 | 59.6k | }), | 216 | 59.6k | } | 217 | | } | 218 | | | 219 | | ( | 220 | | NextKeyInner::FirstFound { | 221 | | no_branch_search: false, | 222 | | .. | 223 | | }, | 224 | 97.7k | Some(storage_trie_node_key), | 225 | 97.7k | ) => { | 226 | 97.7k | let storage_trie_node_key = | 227 | 97.7k | trie::bytes_to_nibbles(storage_trie_node_key).collect::<Vec<_>>(); | 228 | 97.7k | debug_assert!(storage_trie_node_key >= self.key_before); | 229 | | | 230 | | // Due to our usage of `nibbles_to_bytes_truncate` in `prefix()`, we must check | 231 | | // whether the value provided by the user is still within the prefix. | 232 | 97.7k | if !storage_trie_node_key.starts_with(&self.prefix) { | 233 | 37.4k | return BranchSearch::Found { | 234 | 37.4k | branch_trie_node_key: None, | 235 | 37.4k | }; | 236 | 60.2k | } | 237 | 60.2k | | 238 | 60.2k | if storage_trie_node_key.is_empty() | 239 | 45.7k | || storage_trie_node_key.iter().all(|n| *n == Nibble::max()) | 240 | | { | 241 | 14.5k | return BranchSearch::Found { | 242 | 14.5k | branch_trie_node_key: Some(BranchTrieNodeKeyIter { | 243 | 14.5k | inner: storage_trie_node_key.into_iter(), | 244 | 14.5k | }), | 245 | 14.5k | }; | 246 | 45.7k | } | 247 | 45.7k | | 248 | 45.7k | self.inner = NextKeyInner::FurtherRound { | 249 | 45.7k | current_found_branch: storage_trie_node_key, | 250 | 45.7k | }; | 251 | 45.7k | BranchSearch::NextKey(self) | 252 | | } | 253 | | | 254 | | ( | 255 | | NextKeyInner::FurtherRound { | 256 | 23.9k | mut current_found_branch, | 257 | 23.9k | }, | 258 | 23.9k | Some(storage_trie_node_key), | 259 | 23.9k | ) => { | 260 | 23.9k | let storage_trie_node_key = trie::bytes_to_nibbles(storage_trie_node_key); | 261 | 23.9k | | 262 | 23.9k | let num_common = storage_trie_node_key | 263 | 23.9k | .zip(current_found_branch.iter()) | 264 | 23.9k | .take_while(|(a, b)| a == *b) | 265 | 23.9k | .count(); | 266 | 23.9k | | 267 | 23.9k | // Check against infinite loops. | 268 | 23.9k | debug_assert!(num_common < current_found_branch.len()); | 269 | | | 270 | 23.9k | if !current_found_branch[..num_common].starts_with(&self.prefix) | 271 | 21.2k | || ¤t_found_branch[..num_common] < &self.key_before | 272 | 9.02k | || (!self.or_equal && current_found_branch[..num_common] == self.key_before8.21k ) | 273 | | { | 274 | 21.9k | return BranchSearch::Found { | 275 | 21.9k | branch_trie_node_key: Some(BranchTrieNodeKeyIter { | 276 | 21.9k | inner: current_found_branch.into_iter(), | 277 | 21.9k | }), | 278 | 21.9k | }; | 279 | 2.02k | } | 280 | 2.02k | | 281 | 2.02k | current_found_branch.truncate(num_common); | 282 | 2.02k | | 283 | 2.02k | if current_found_branch.is_empty() | 284 | 2.02k | || current_found_branch.iter().all(|n| *n == Nibble::max()) | 285 | | { | 286 | 196 | return BranchSearch::Found { | 287 | 196 | branch_trie_node_key: Some(BranchTrieNodeKeyIter { | 288 | 196 | inner: current_found_branch.into_iter(), | 289 | 196 | }), | 290 | 196 | }; | 291 | 1.82k | } | 292 | 1.82k | | 293 | 1.82k | self.inner = NextKeyInner::FurtherRound { | 294 | 1.82k | current_found_branch, | 295 | 1.82k | }; | 296 | 1.82k | BranchSearch::NextKey(self) | 297 | | } | 298 | | | 299 | | // If `current_found_branch` doesn't have any sibling or uncle after it, then we know | 300 | | // that there can't be any more branch node and the search is over. | 301 | | ( | 302 | | NextKeyInner::FurtherRound { | 303 | 23.5k | current_found_branch, | 304 | 23.5k | }, | 305 | 23.5k | None, | 306 | 23.5k | ) => BranchSearch::Found { | 307 | 23.5k | branch_trie_node_key: Some(BranchTrieNodeKeyIter { | 308 | 23.5k | inner: current_found_branch.into_iter(), | 309 | 23.5k | }), | 310 | 23.5k | }, | 311 | | } | 312 | 571k | } |
Unexecuted instantiation: _RINvMs0_NtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB6_7NextKey6injectINtNtNtNtCsaYZPK01V26L_4core4iter8adapters6copied6CopiedINtNtNtB1j_5slice4iter4IterhEEECsDDUKWWCHAU_18smoldot_light_wasm _RINvMs0_NtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB6_7NextKey6injectINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEBa_ Line | Count | Source | 179 | 17.4k | pub fn inject( | 180 | 17.4k | mut self, | 181 | 17.4k | storage_trie_node_key: Option<impl Iterator<Item = u8>>, | 182 | 17.4k | ) -> BranchSearch { | 183 | 17.4k | match (self.inner, storage_trie_node_key) { | 184 | | // No matter what, if we're at the first round and the user injected `None`, that | 185 | | // means `key_before` is equal or superior to the last key of the trie and thus there | 186 | | // can't be any branch node after it. | 187 | 14.1k | (NextKeyInner::FirstFound { .. }, None) => BranchSearch::Found { | 188 | 14.1k | branch_trie_node_key: None, | 189 | 14.1k | }, | 190 | | | 191 | | // If `no_branch_search` is `true`, simply immediately return the value provided by | 192 | | // the user. | 193 | | ( | 194 | | NextKeyInner::FirstFound { | 195 | | no_branch_search: true, | 196 | | .. | 197 | | }, | 198 | 0 | Some(storage_trie_node_key), | 199 | 0 | ) => { | 200 | 0 | let storage_trie_node_key = | 201 | 0 | trie::bytes_to_nibbles(storage_trie_node_key).collect::<Vec<_>>(); | 202 | 0 | debug_assert!(storage_trie_node_key >= self.key_before); | 203 | | | 204 | | // Due to our usage of `nibbles_to_bytes_truncate` in `prefix()`, we must check | 205 | | // whether the value provided by the user is still within the prefix. | 206 | 0 | if !storage_trie_node_key.starts_with(&self.prefix) { | 207 | 0 | return BranchSearch::Found { | 208 | 0 | branch_trie_node_key: None, | 209 | 0 | }; | 210 | 0 | } | 211 | 0 |
| 212 | 0 | BranchSearch::Found { | 213 | 0 | branch_trie_node_key: Some(BranchTrieNodeKeyIter { | 214 | 0 | inner: storage_trie_node_key.into_iter(), | 215 | 0 | }), | 216 | 0 | } | 217 | | } | 218 | | | 219 | | ( | 220 | | NextKeyInner::FirstFound { | 221 | | no_branch_search: false, | 222 | | .. | 223 | | }, | 224 | 1.99k | Some(storage_trie_node_key), | 225 | 1.99k | ) => { | 226 | 1.99k | let storage_trie_node_key = | 227 | 1.99k | trie::bytes_to_nibbles(storage_trie_node_key).collect::<Vec<_>>(); | 228 | 1.99k | debug_assert!(storage_trie_node_key >= self.key_before); | 229 | | | 230 | | // Due to our usage of `nibbles_to_bytes_truncate` in `prefix()`, we must check | 231 | | // whether the value provided by the user is still within the prefix. | 232 | 1.99k | if !storage_trie_node_key.starts_with(&self.prefix) { | 233 | 987 | return BranchSearch::Found { | 234 | 987 | branch_trie_node_key: None, | 235 | 987 | }; | 236 | 1.00k | } | 237 | 1.00k | | 238 | 1.00k | if storage_trie_node_key.is_empty() | 239 | 1.00k | || storage_trie_node_key.iter().all(|n| *n == Nibble::max()) | 240 | | { | 241 | 0 | return BranchSearch::Found { | 242 | 0 | branch_trie_node_key: Some(BranchTrieNodeKeyIter { | 243 | 0 | inner: storage_trie_node_key.into_iter(), | 244 | 0 | }), | 245 | 0 | }; | 246 | 1.00k | } | 247 | 1.00k | | 248 | 1.00k | self.inner = NextKeyInner::FurtherRound { | 249 | 1.00k | current_found_branch: storage_trie_node_key, | 250 | 1.00k | }; | 251 | 1.00k | BranchSearch::NextKey(self) | 252 | | } | 253 | | | 254 | | ( | 255 | | NextKeyInner::FurtherRound { | 256 | 861 | mut current_found_branch, | 257 | 861 | }, | 258 | 861 | Some(storage_trie_node_key), | 259 | 861 | ) => { | 260 | 861 | let storage_trie_node_key = trie::bytes_to_nibbles(storage_trie_node_key); | 261 | 861 | | 262 | 861 | let num_common = storage_trie_node_key | 263 | 861 | .zip(current_found_branch.iter()) | 264 | 861 | .take_while(|(a, b)| a == *b) | 265 | 861 | .count(); | 266 | 861 | | 267 | 861 | // Check against infinite loops. | 268 | 861 | debug_assert!(num_common < current_found_branch.len()); | 269 | | | 270 | 861 | if !current_found_branch[..num_common].starts_with(&self.prefix) | 271 | 315 | || ¤t_found_branch[..num_common] < &self.key_before | 272 | 315 | || (!self.or_equal && current_found_branch[..num_common] == self.key_before0 ) | 273 | | { | 274 | 546 | return BranchSearch::Found { | 275 | 546 | branch_trie_node_key: Some(BranchTrieNodeKeyIter { | 276 | 546 | inner: current_found_branch.into_iter(), | 277 | 546 | }), | 278 | 546 | }; | 279 | 315 | } | 280 | 315 | | 281 | 315 | current_found_branch.truncate(num_common); | 282 | 315 | | 283 | 315 | if current_found_branch.is_empty() | 284 | 294 | || current_found_branch.iter().all(|n| *n == Nibble::max()) | 285 | | { | 286 | 21 | return BranchSearch::Found { | 287 | 21 | branch_trie_node_key: Some(BranchTrieNodeKeyIter { | 288 | 21 | inner: current_found_branch.into_iter(), | 289 | 21 | }), | 290 | 21 | }; | 291 | 294 | } | 292 | 294 | | 293 | 294 | self.inner = NextKeyInner::FurtherRound { | 294 | 294 | current_found_branch, | 295 | 294 | }; | 296 | 294 | BranchSearch::NextKey(self) | 297 | | } | 298 | | | 299 | | // If `current_found_branch` doesn't have any sibling or uncle after it, then we know | 300 | | // that there can't be any more branch node and the search is over. | 301 | | ( | 302 | | NextKeyInner::FurtherRound { | 303 | 441 | current_found_branch, | 304 | 441 | }, | 305 | 441 | None, | 306 | 441 | ) => BranchSearch::Found { | 307 | 441 | branch_trie_node_key: Some(BranchTrieNodeKeyIter { | 308 | 441 | inner: current_found_branch.into_iter(), | 309 | 441 | }), | 310 | 441 | }, | 311 | | } | 312 | 17.4k | } |
Unexecuted instantiation: _RINvMs0_NtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB6_7NextKey6injectINtNtNtNtCsaYZPK01V26L_4core4iter8adapters6copied6CopiedINtNtNtB1j_5slice4iter4IterhEEEBa_ Unexecuted instantiation: _RINvMs0_NtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB6_7NextKey6injectINtNtNtNtCsaYZPK01V26L_4core4iter8adapters6copied6CopiedINtNtNtB1j_5slice4iter4IterhEEECsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RINvMs0_NtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB6_7NextKey6injectINtNtNtNtCsaYZPK01V26L_4core4iter8adapters6copied6CopiedINtNtNtB1j_5slice4iter4IterhEEECscDgN54JpMGG_6author Unexecuted instantiation: _RINvMs0_NtNtCseuYC0Zibziv_7smoldot4trie13branch_searchNtB6_7NextKey6injectINtNtNtNtCsaYZPK01V26L_4core4iter8adapters6copied6CopiedINtNtNtB1j_5slice4iter4IterhEEECsibGXYHQB8Ea_25json_rpc_general_requests |
313 | | } |