submilli_wasm/store/
limits.rs1#[cfg(test)]
4#[path = "limits_tests.rs"]
5mod tests;
6
7use crate::{Error, Result};
8
9const DEFAULT_LIMIT: usize = 10_000;
10
11pub(crate) const DEFAULT_MEMORY_CEILING_BYTES: usize = host_ceiling(1u64 << 32);
19
20pub(crate) const DEFAULT_TABLE_CEILING_ELEMS: usize = host_ceiling(u32::MAX as u64);
25
26const fn host_ceiling(limit: u64) -> usize {
27 if limit > isize::MAX as u64 {
28 isize::MAX as usize
29 } else {
30 limit as usize
31 }
32}
33
34pub trait ResourceLimiter {
36 fn memory_growing(
37 &mut self,
38 current: usize,
39 desired: usize,
40 maximum: Option<usize>,
41 ) -> Result<bool>;
42
43 fn table_growing(
44 &mut self,
45 current: usize,
46 desired: usize,
47 maximum: Option<usize>,
48 ) -> Result<bool>;
49
50 fn memory_grow_failed(&mut self, error: Error) -> Result<()> {
51 Ok(())
52 }
53
54 fn table_grow_failed(&mut self, error: Error) -> Result<()> {
55 Ok(())
56 }
57
58 fn instances(&self) -> usize {
59 DEFAULT_LIMIT
60 }
61
62 fn tables(&self) -> usize {
63 DEFAULT_LIMIT
64 }
65
66 fn memories(&self) -> usize {
67 DEFAULT_LIMIT
68 }
69}
70
71#[cfg(feature = "async")]
74#[async_trait::async_trait]
75pub trait ResourceLimiterAsync: Send {
76 async fn memory_growing(
77 &mut self,
78 current: usize,
79 desired: usize,
80 maximum: Option<usize>,
81 ) -> Result<bool>;
82
83 async fn table_growing(
84 &mut self,
85 current: usize,
86 desired: usize,
87 maximum: Option<usize>,
88 ) -> Result<bool>;
89
90 fn memory_grow_failed(&mut self, error: Error) -> Result<()> {
91 Ok(())
92 }
93
94 fn table_grow_failed(&mut self, error: Error) -> Result<()> {
95 Ok(())
96 }
97
98 fn instances(&self) -> usize {
99 DEFAULT_LIMIT
100 }
101
102 fn tables(&self) -> usize {
103 DEFAULT_LIMIT
104 }
105
106 fn memories(&self) -> usize {
107 DEFAULT_LIMIT
108 }
109}
110
111#[derive(Clone, Debug)]
113pub struct StoreLimits {
114 memory_size: Option<usize>,
115 table_elements: Option<usize>,
116 instances: usize,
117 tables: usize,
118 memories: usize,
119 trap_on_grow_failure: bool,
120}
121
122impl Default for StoreLimits {
123 fn default() -> Self {
124 StoreLimits {
125 memory_size: None,
126 table_elements: None,
127 instances: DEFAULT_LIMIT,
128 tables: DEFAULT_LIMIT,
129 memories: DEFAULT_LIMIT,
130 trap_on_grow_failure: false,
131 }
132 }
133}
134
135impl ResourceLimiter for StoreLimits {
136 fn memory_growing(
137 &mut self,
138 current: usize,
139 desired: usize,
140 maximum: Option<usize>,
141 ) -> Result<bool> {
142 let within_config = self.memory_size.is_none_or(|limit| desired <= limit);
143 let within_max = maximum.is_none_or(|max| desired <= max);
144 Ok(within_config && within_max)
145 }
146
147 fn table_growing(
148 &mut self,
149 current: usize,
150 desired: usize,
151 maximum: Option<usize>,
152 ) -> Result<bool> {
153 let within_config = self.table_elements.is_none_or(|limit| desired <= limit);
154 let within_max = maximum.is_none_or(|max| desired <= max);
155 Ok(within_config && within_max)
156 }
157
158 fn memory_grow_failed(&mut self, error: Error) -> Result<()> {
159 if self.trap_on_grow_failure {
160 Err(error)
161 } else {
162 Ok(())
163 }
164 }
165
166 fn table_grow_failed(&mut self, error: Error) -> Result<()> {
167 if self.trap_on_grow_failure {
168 Err(error)
169 } else {
170 Ok(())
171 }
172 }
173
174 fn instances(&self) -> usize {
175 self.instances
176 }
177
178 fn tables(&self) -> usize {
179 self.tables
180 }
181
182 fn memories(&self) -> usize {
183 self.memories
184 }
185}
186
187#[derive(Debug)]
189pub struct StoreLimitsBuilder(StoreLimits);
190
191impl StoreLimitsBuilder {
192 pub fn new() -> Self {
193 StoreLimitsBuilder(StoreLimits::default())
194 }
195
196 pub fn memory_size(mut self, limit: usize) -> Self {
197 self.0.memory_size = Some(limit);
198 self
199 }
200
201 pub fn table_elements(mut self, limit: usize) -> Self {
202 self.0.table_elements = Some(limit);
203 self
204 }
205
206 pub fn instances(mut self, limit: usize) -> Self {
207 self.0.instances = limit;
208 self
209 }
210
211 pub fn tables(mut self, limit: usize) -> Self {
212 self.0.tables = limit;
213 self
214 }
215
216 pub fn memories(mut self, limit: usize) -> Self {
217 self.0.memories = limit;
218 self
219 }
220
221 pub fn trap_on_grow_failure(mut self, trap: bool) -> Self {
222 self.0.trap_on_grow_failure = trap;
223 self
224 }
225
226 pub fn build(self) -> StoreLimits {
227 self.0
228 }
229}
230
231impl Default for StoreLimitsBuilder {
232 fn default() -> Self {
233 StoreLimitsBuilder::new()
234 }
235}