sui_package_resolver/
limits.rs1use crate::{Error, Result};
5
6pub const DEFAULT_MAX_LAYOUT_WORK: usize = 2_048;
8
9#[derive(Debug, Clone)]
12pub struct Limits {
13 pub max_type_argument_depth: usize,
15 pub max_type_argument_width: usize,
17 pub max_type_nodes: usize,
19 pub max_move_value_depth: usize,
21 pub max_layout_work: usize,
23}
24
25pub(crate) struct LayoutBudget {
26 max_nodes: Option<usize>,
27 remaining_nodes: usize,
28}
29
30pub(crate) struct LayoutMeter<'b> {
31 max_depth: Option<usize>,
32 remaining_depth: usize,
33 budget: &'b mut LayoutBudget,
34}
35
36impl Limits {
37 pub(crate) fn layout_budget(&self) -> LayoutBudget {
38 LayoutBudget {
39 max_nodes: Some(self.max_layout_work),
40 remaining_nodes: self.max_layout_work,
41 }
42 }
43}
44
45impl LayoutBudget {
46 pub(crate) fn unlimited() -> Self {
47 Self {
48 max_nodes: None,
49 remaining_nodes: usize::MAX,
50 }
51 }
52
53 fn charge_node(&mut self) -> Result<()> {
54 self.charge_nodes(1)
55 }
56
57 fn charge_nodes(&mut self, nodes: usize) -> Result<()> {
58 let Some(max_nodes) = self.max_nodes else {
59 return Ok(());
60 };
61 if nodes > self.remaining_nodes {
62 return Err(Error::TooManyTypeNodes(
63 max_nodes,
64 max_nodes
65 .saturating_sub(self.remaining_nodes)
66 .saturating_add(nodes),
67 ));
68 }
69
70 self.remaining_nodes = self.remaining_nodes.saturating_sub(nodes);
71 Ok(())
72 }
73}
74
75impl<'b> LayoutMeter<'b> {
76 pub(crate) fn new(max_depth: Option<usize>, budget: &'b mut LayoutBudget) -> Self {
77 Self {
78 max_depth,
79 remaining_depth: max_depth.unwrap_or(usize::MAX),
80 budget,
81 }
82 }
83
84 pub(crate) fn check_depth(&self) -> Result<()> {
85 if self.remaining_depth == 0 {
86 return Err(Error::ValueNesting(self.max_depth.unwrap_or(0)));
87 }
88 Ok(())
89 }
90
91 pub(crate) fn ensure_depth(&self, depth: usize) -> Result<()> {
92 if depth > self.remaining_depth {
93 return Err(Error::ValueNesting(self.max_depth.unwrap_or(0)));
94 }
95 Ok(())
96 }
97
98 pub(crate) fn nest(&mut self) -> Result<LayoutMeter<'_>> {
99 self.check_depth()?;
100 Ok(LayoutMeter {
101 max_depth: self.max_depth,
102 remaining_depth: self.remaining_depth.saturating_sub(1),
103 budget: self.budget,
104 })
105 }
106
107 pub(crate) fn charge_node(&mut self) -> Result<()> {
108 self.budget.charge_node()
109 }
110
111 pub(crate) fn charge_nodes(&mut self, nodes: usize) -> Result<()> {
112 self.budget.charge_nodes(nodes)
113 }
114}