everscale_types/dict/ops/
get.rs1use crate::cell::*;
2use crate::dict::{make_leaf, read_label, split_edge, Branch};
3use crate::error::Error;
4
5pub fn dict_get<'a: 'b, 'b>(
7 dict: Option<&'a Cell>,
8 key_bit_len: u16,
9 mut key: CellSlice<'b>,
10 context: &mut dyn CellContext,
11) -> Result<Option<CellSlice<'a>>, Error> {
12 if key.size_bits() != key_bit_len {
13 return Err(Error::CellUnderflow);
14 }
15
16 let mut data = match dict {
17 Some(data) => ok!(context
18 .load_dyn_cell(data.as_ref(), LoadMode::Full)
19 .and_then(CellSlice::new)),
20 None => return Ok(None),
21 };
22
23 let is_key_empty = loop {
25 let prefix = ok!(read_label(&mut data, key.size_bits()));
27
28 match key.strip_data_prefix(&prefix) {
30 Some(stripped_key) => {
31 if stripped_key.is_data_empty() {
32 break true;
34 } else if data.size_refs() < 2 {
35 return Ok(None);
37 } else {
38 key = stripped_key;
39 }
40 }
41 None => break key.is_data_empty(),
42 }
43
44 let child_index = ok!(key.load_bit()) as u8;
46 data = match data.cell().reference(child_index) {
47 Some(cell) => ok!(context
48 .load_dyn_cell(cell, LoadMode::Full)
49 .and_then(CellSlice::new)),
50 None => return Err(Error::CellUnderflow),
51 };
52 };
53
54 Ok(if is_key_empty { Some(data) } else { None })
56}
57
58pub fn dict_get_owned(
60 dict: Option<&Cell>,
61 key_bit_len: u16,
62 mut key: CellSlice<'_>,
63 context: &mut dyn CellContext,
64) -> Result<Option<CellSliceParts>, Error> {
65 if key.size_bits() != key_bit_len {
66 return Err(Error::CellUnderflow);
67 }
68
69 let root = match dict {
70 Some(cell) => ok!(context.load_cell(cell.clone(), LoadMode::Full)),
71 None => return Ok(None),
72 };
73 let mut data = ok!(root.as_slice());
74 let mut prev = None;
75
76 let is_key_empty = loop {
78 let prefix = ok!(read_label(&mut data, key.size_bits()));
80
81 match key.strip_data_prefix(&prefix) {
83 Some(stripped_key) => {
84 if stripped_key.is_data_empty() {
85 break true;
87 } else if data.size_refs() < 2 {
88 return Ok(None);
90 } else {
91 key = stripped_key;
92 }
93 }
94 None => break key.is_data_empty(),
95 }
96
97 let child_index = ok!(key.load_bit()) as u8;
99 prev = Some((data.cell(), child_index));
100 data = match data.cell().reference(child_index) {
101 Some(cell) => ok!(context
102 .load_dyn_cell(cell, LoadMode::Full)
103 .and_then(CellSlice::new)),
104 None => return Err(Error::CellUnderflow),
105 };
106 };
107
108 Ok(if is_key_empty {
110 Some(match prev {
111 Some((prev, child_index)) => {
112 let cell = match prev.reference_cloned(child_index) {
113 Some(cell) => ok!(context.load_cell(cell, LoadMode::Resolve)),
114 None => return Err(Error::CellUnderflow),
115 };
116 (cell, data.range())
117 }
118 None => {
119 let range = data.range();
120 (root, range)
121 }
122 })
123 } else {
124 None
125 })
126}
127
128pub fn dict_get_subdict<'a: 'b, 'b>(
131 dict: Option<&'a Cell>,
132 key_bit_len: u16,
133 prefix: &mut CellSlice<'b>,
134 context: &mut dyn CellContext,
135) -> Result<Option<Cell>, Error> {
136 match dict {
137 None => Ok(None),
138 Some(cell) => {
139 let prefix_len = prefix.size_bits();
140 if prefix_len == 0 || key_bit_len < prefix_len {
141 return Ok(Some(cell.clone()));
142 }
143
144 let mut data = match dict {
145 Some(data) => ok!(context
146 .load_dyn_cell(data.as_ref(), LoadMode::Full)
147 .and_then(CellSlice::new)),
148 None => return Ok(None),
149 };
150
151 let subtree = loop {
153 let label = &mut ok!(read_label(&mut data, prefix.size_bits()));
155 let lcp = prefix.longest_common_data_prefix(label);
156 match lcp.size_bits().cmp(&prefix.size_bits()) {
157 std::cmp::Ordering::Equal => {
158 let new_leaf = ok!(make_leaf(label, lcp.size_bits(), &data, context));
160 break new_leaf;
161 }
162 std::cmp::Ordering::Less if lcp.size_bits() < label.size_bits() => {
163 let value = ok!(CellBuilder::new().build_ext(context));
165 let split_edge =
166 ok!(split_edge(&data, label, &lcp, prefix, &value, context));
167 break split_edge;
168 }
169 std::cmp::Ordering::Less => {
170 if data.cell().reference_count() != 2 {
171 return Err(Error::CellUnderflow);
172 }
173 prefix.skip_first(lcp.size_bits(), 0).ok();
174 let next_branch = match prefix.load_bit() {
175 Ok(bit) => Branch::from(bit),
176 Err(e) => return Err(e),
177 };
178
179 let child = match data.cell().reference(next_branch as u8) {
180 Some(cell) => ok!(context
182 .load_dyn_cell(cell, LoadMode::Full)
183 .and_then(CellSlice::new)),
184 None => return Err(Error::CellUnderflow),
185 };
186 data = child;
187 }
188 std::cmp::Ordering::Greater => {
189 debug_assert!(false, "LCP of prefix and key can't be greater than key");
190 unsafe { std::hint::unreachable_unchecked() };
191 }
192 }
193 };
194
195 Ok(Some(subtree))
196 }
197 }
198}