1#![deny(missing_docs)]
30
31pub mod context;
35pub mod error;
37pub mod storage_cost;
39
40use std::ops::{Add, AddAssign};
41
42pub use context::{CostContext, CostResult, CostsExt};
43use integer_encoding::VarInt;
44
45use crate::{
46 error::Error,
47 storage_cost::{
48 key_value_cost::KeyValueStorageCost, removal::StorageRemovedBytes, StorageCost,
49 },
50 StorageRemovedBytes::BasicStorageRemoval,
51};
52
53pub type ChildKeyLength = u32;
55
56pub type FeatureSumLength = u32;
58
59pub type ChildSumLength = u32;
61
62pub type ChildrenSizes = Option<(
64 Option<(ChildKeyLength, ChildSumLength)>,
65 Option<(ChildKeyLength, ChildSumLength)>,
66)>;
67
68pub type ChildrenSizesWithValue = Option<(
70 Vec<u8>,
71 Option<(ChildKeyLength, ChildSumLength)>,
72 Option<(ChildKeyLength, ChildSumLength)>,
73)>;
74
75pub enum TreeCostType {
77 TreeFeatureUsesVarIntCostAs8Bytes,
79 TreeFeatureUsesTwoVarIntsCostAs16Bytes,
81 TreeFeatureUses16Bytes,
83}
84
85impl TreeCostType {
86 fn cost_size(&self) -> u32 {
87 match self {
88 TreeCostType::TreeFeatureUsesVarIntCostAs8Bytes => 8,
89 TreeCostType::TreeFeatureUsesTwoVarIntsCostAs16Bytes => 16,
90 TreeCostType::TreeFeatureUses16Bytes => 16,
91 }
92 }
93}
94
95pub type ChildrenSizesWithIsSumTree = Option<(
97 Option<(TreeCostType, FeatureSumLength)>,
98 Option<(ChildKeyLength, ChildSumLength)>,
99 Option<(ChildKeyLength, ChildSumLength)>,
100)>;
101
102#[derive(Debug, Default, Eq, PartialEq, Clone)]
104pub struct OperationCost {
105 pub seek_count: u32,
107 pub storage_cost: StorageCost,
109 pub storage_loaded_bytes: u64,
111 pub hash_node_calls: u32,
113}
114
115impl OperationCost {
116 pub fn is_nothing(&self) -> bool {
118 self == &Self::default()
119 }
120
121 pub fn with_seek_count(seek_count: u32) -> Self {
124 OperationCost {
125 seek_count,
126 ..Default::default()
127 }
128 }
129
130 pub fn with_storage_written_bytes(storage_written_bytes: u32) -> Self {
133 OperationCost {
134 storage_cost: StorageCost {
135 added_bytes: storage_written_bytes,
136 ..Default::default()
137 },
138 ..Default::default()
139 }
140 }
141
142 pub fn with_storage_loaded_bytes(storage_loaded_bytes: u64) -> Self {
145 OperationCost {
146 storage_loaded_bytes,
147 ..Default::default()
148 }
149 }
150
151 pub fn with_storage_freed_bytes(storage_freed_bytes: u32) -> Self {
154 OperationCost {
155 storage_cost: StorageCost {
156 removed_bytes: BasicStorageRemoval(storage_freed_bytes),
157 ..Default::default()
158 },
159 ..Default::default()
160 }
161 }
162
163 pub fn with_hash_node_calls(hash_node_calls: u32) -> Self {
166 OperationCost {
167 hash_node_calls,
168 ..Default::default()
169 }
170 }
171
172 pub fn worse_or_eq_than(&self, other: &Self) -> bool {
175 self.seek_count >= other.seek_count
176 && self.storage_cost.worse_or_eq_than(&other.storage_cost)
177 && self.storage_loaded_bytes >= other.storage_loaded_bytes
178 && self.hash_node_calls >= other.hash_node_calls
179 }
180
181 pub fn add_key_value_storage_costs(
183 &mut self,
184 key_len: u32,
185 value_len: u32,
186 children_sizes: ChildrenSizesWithIsSumTree,
187 storage_cost_info: Option<KeyValueStorageCost>,
188 ) -> Result<(), Error> {
189 let paid_key_len = key_len + key_len.required_space() as u32;
190
191 let doesnt_need_verification = storage_cost_info
192 .as_ref()
193 .map(|key_value_storage_cost| {
194 if !key_value_storage_cost.needs_value_verification {
195 Some(
196 key_value_storage_cost.value_storage_cost.added_bytes
197 + key_value_storage_cost.value_storage_cost.replaced_bytes,
198 )
199 } else {
200 None
201 }
202 })
203 .unwrap_or(None);
204 let final_paid_value_len = if let Some(value_cost_len) = doesnt_need_verification {
205 value_cost_len
206 } else {
207 let mut paid_value_len = value_len;
208 if let Some((in_sum_tree, left_child, right_child)) = children_sizes {
210 paid_value_len -= 2; if let Some((left_child_len, left_child_sum_len)) = left_child {
214 paid_value_len -= left_child_len;
215 paid_value_len -= left_child_sum_len;
216 }
217 if let Some((right_child_len, right_child_sum_len)) = right_child {
218 paid_value_len -= right_child_len;
219 paid_value_len -= right_child_sum_len;
220 }
221
222 let sum_tree_node_size = if let Some((tree_cost_type, sum_tree_len)) = in_sum_tree {
223 let cost_size = tree_cost_type.cost_size();
224 paid_value_len -= sum_tree_len;
225 paid_value_len += cost_size;
226 cost_size
227 } else {
228 0
229 };
230
231 paid_value_len += paid_value_len.required_space() as u32;
234
235 paid_value_len += key_len + 4 + sum_tree_node_size;
243 } else {
244 paid_value_len += paid_value_len.required_space() as u32;
245 }
246 paid_value_len
247 };
248
249 let (key_storage_cost, value_storage_costs) = match storage_cost_info {
250 None => (None, None),
251 Some(s) => {
252 s.key_storage_cost
253 .verify_key_storage_cost(paid_key_len, s.new_node)?;
254 s.value_storage_cost.verify(final_paid_value_len)?;
255 (Some(s.key_storage_cost), Some(s.value_storage_cost))
256 }
257 };
258
259 self.add_storage_costs(paid_key_len, key_storage_cost);
260 self.add_storage_costs(final_paid_value_len, value_storage_costs);
261 Ok(())
262 }
263
264 fn add_storage_costs(
266 &mut self,
267 len_with_required_space: u32,
268 storage_cost_info: Option<StorageCost>,
269 ) {
270 match storage_cost_info {
271 None => {
273 self.storage_cost += StorageCost {
274 added_bytes: len_with_required_space,
275 ..Default::default()
276 }
277 }
278 Some(storage_cost) => {
279 self.storage_cost += storage_cost;
280 }
281 }
282 }
283}
284
285impl Add for OperationCost {
286 type Output = Self;
287
288 fn add(self, rhs: Self) -> Self::Output {
289 OperationCost {
290 seek_count: self.seek_count + rhs.seek_count,
291 storage_cost: self.storage_cost + rhs.storage_cost,
292 storage_loaded_bytes: self.storage_loaded_bytes + rhs.storage_loaded_bytes,
293 hash_node_calls: self.hash_node_calls + rhs.hash_node_calls,
294 }
295 }
296}
297
298impl AddAssign for OperationCost {
299 fn add_assign(&mut self, rhs: Self) {
300 self.seek_count += rhs.seek_count;
301 self.storage_cost += rhs.storage_cost;
302 self.storage_loaded_bytes += rhs.storage_loaded_bytes;
303 self.hash_node_calls += rhs.hash_node_calls;
304 }
305}
306
307#[cfg(test)]
308mod tests {
309 use super::*;
310 use crate::context::{CostContext, CostResult, CostsExt};
311
312 #[test]
313 fn test_map() {
314 let initial = CostContext {
315 value: 75,
316 cost: OperationCost {
317 storage_loaded_bytes: 3,
318 ..Default::default()
319 },
320 };
321
322 let mapped = initial.map(|x| x + 25);
323 assert_eq!(
324 mapped,
325 CostContext {
326 value: 100,
327 cost: OperationCost {
328 storage_loaded_bytes: 3,
329 ..Default::default()
330 },
331 }
332 );
333 }
334
335 #[test]
336 fn test_flat_map() {
337 let initial = CostContext {
338 value: 75,
339 cost: OperationCost {
340 storage_loaded_bytes: 3,
341 ..Default::default()
342 },
343 };
344
345 let mapped = initial.flat_map(|x| CostContext {
346 value: x + 25,
347 cost: OperationCost {
348 storage_loaded_bytes: 7,
349 ..Default::default()
350 },
351 });
352 assert_eq!(
353 mapped,
354 CostContext {
355 value: 100,
356 cost: OperationCost {
357 storage_loaded_bytes: 10,
358 ..Default::default()
359 },
360 }
361 );
362 }
363
364 #[test]
365 fn test_map_ok() {
366 let initial: CostResult<usize, ()> = CostContext {
367 value: Ok(75),
368 cost: OperationCost {
369 storage_loaded_bytes: 3,
370 ..Default::default()
371 },
372 };
373
374 let mapped = initial.map_ok(|x| x + 25);
375 assert_eq!(
376 mapped,
377 CostContext {
378 value: Ok(100),
379 cost: OperationCost {
380 storage_loaded_bytes: 3,
381 ..Default::default()
382 },
383 }
384 );
385 }
386
387 #[test]
388 fn test_map_ok_err() {
389 let initial: CostResult<usize, ()> = CostContext {
390 value: Err(()),
391 cost: OperationCost {
392 storage_loaded_bytes: 3,
393 ..Default::default()
394 },
395 };
396
397 let mapped = initial.map_ok(|x| x + 25);
398 assert_eq!(
399 mapped,
400 CostContext {
401 value: Err(()),
402 cost: OperationCost {
403 storage_loaded_bytes: 3,
404 ..Default::default()
405 },
406 }
407 );
408 }
409
410 #[test]
411 fn test_flat_map_ok() {
412 let initial: CostResult<usize, ()> = CostContext {
413 value: Ok(75),
414 cost: OperationCost {
415 storage_loaded_bytes: 3,
416 ..Default::default()
417 },
418 };
419
420 let mapped = initial.flat_map_ok(|x| CostContext {
421 value: Ok(x + 25),
422 cost: OperationCost {
423 storage_loaded_bytes: 7,
424 ..Default::default()
425 },
426 });
427 assert_eq!(
428 mapped,
429 CostContext {
430 value: Ok(100),
431 cost: OperationCost {
432 storage_loaded_bytes: 10,
433 ..Default::default()
434 },
435 }
436 );
437 }
438
439 #[test]
440 fn test_flat_map_err_first() {
441 let initial: CostResult<usize, ()> = CostContext {
442 value: Err(()),
443 cost: OperationCost {
444 storage_loaded_bytes: 3,
445 ..Default::default()
446 },
447 };
448 let mut executed = false;
449 let mapped = initial.flat_map_ok(|x| {
450 executed = true;
451 CostContext {
452 value: Ok(x + 25),
453 cost: OperationCost {
454 storage_loaded_bytes: 7,
455 ..Default::default()
456 },
457 }
458 });
459
460 assert!(!executed);
462 assert_eq!(
463 mapped,
464 CostContext {
465 value: Err(()),
466 cost: OperationCost {
467 storage_loaded_bytes: 3,
468 ..Default::default()
469 },
470 }
471 );
472 }
473
474 #[test]
475 fn test_flat_map_err_second() {
476 let initial: CostResult<usize, ()> = CostContext {
477 value: Ok(75),
478 cost: OperationCost {
479 storage_loaded_bytes: 3,
480 ..Default::default()
481 },
482 };
483 let mut executed = false;
484 let mapped: CostResult<usize, ()> = initial.flat_map_ok(|_| {
485 executed = true;
486 CostContext {
487 value: Err(()),
488 cost: OperationCost {
489 storage_loaded_bytes: 7,
490 ..Default::default()
491 },
492 }
493 });
494
495 assert!(executed);
498 assert_eq!(
499 mapped,
500 CostContext {
501 value: Err(()),
502 cost: OperationCost {
503 storage_loaded_bytes: 10,
504 ..Default::default()
505 },
506 }
507 );
508 }
509
510 #[test]
511 fn test_flatten_nested_errors() {
512 let initial: CostResult<usize, &str> = CostContext {
513 value: Ok(75),
514 cost: OperationCost {
515 storage_loaded_bytes: 3,
516 ..Default::default()
517 },
518 };
519 let ok = initial.map_ok(|x| Ok(x + 25));
522 assert_eq!(ok.flatten().unwrap(), Ok(100));
523
524 let initial: CostResult<usize, &str> = CostContext {
525 value: Ok(75),
526 cost: OperationCost {
527 storage_loaded_bytes: 3,
528 ..Default::default()
529 },
530 };
531 let error_inner: CostResult<Result<usize, &str>, &str> = initial.map_ok(|_| Err("latter"));
532 assert_eq!(error_inner.flatten().unwrap(), Err("latter"));
533
534 let initial: CostResult<usize, &str> = CostContext {
535 value: Err("inner"),
536 cost: OperationCost {
537 storage_loaded_bytes: 3,
538 ..Default::default()
539 },
540 };
541 let error_inner: CostResult<Result<usize, &str>, &str> = initial.map_ok(|x| Ok(x + 25));
542 assert_eq!(error_inner.flatten().unwrap(), Err("inner"));
543 }
544
545 #[test]
546 fn test_wrap_fn_cost() {
547 let loaded_value = b"ayylmao";
549 let costs_ctx = loaded_value.wrap_fn_cost(|x| OperationCost {
550 seek_count: 1,
551 storage_loaded_bytes: x.len() as u64,
552 ..Default::default()
553 });
554 assert_eq!(
555 costs_ctx,
556 CostContext {
557 value: loaded_value,
558 cost: OperationCost {
559 seek_count: 1,
560 storage_loaded_bytes: 7,
561 ..Default::default()
562 }
563 }
564 )
565 }
566
567 #[test]
568 fn test_map_err() {
569 let initial: CostResult<usize, ()> = CostContext {
570 value: Err(()),
571 cost: OperationCost {
572 storage_loaded_bytes: 3,
573 ..Default::default()
574 },
575 };
576
577 let mapped = initial.map_err(|_| "ayyerror");
578 assert_eq!(
579 mapped,
580 CostContext {
581 value: Err("ayyerror"),
582 cost: OperationCost {
583 storage_loaded_bytes: 3,
584 ..Default::default()
585 },
586 }
587 );
588 }
589}