Coverage Report

Created: 2026-07-03 16:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/build/source/crates/checked/src/store.rs
Line
Count
Source
1
use alloc::{string::String, vec::Vec};
2
use wasm::{
3
    Config, FuncAddr, FuncType, GlobalAddr, GlobalType, HostResumable, Hostcode, MemAddr, MemType,
4
    Module, ModuleAddr, RuntimeError, TableAddr, TableType, WasmResumable,
5
};
6
7
use crate::{
8
    stored_types::{Stored, StoredExternVal, StoredInstantiationOutcome, StoredRunState},
9
    AbstractStored, StoreId, StoredRef, StoredResumable, StoredValue,
10
};
11
12
pub struct Store<'b, T: Config> {
13
    pub(crate) inner: wasm::Store<'b, T>,
14
15
    /// A unique identifier for this store. This is used to verify that stored
16
    /// objects belong to the current [`Store`](wasm::Store).
17
    pub(crate) id: StoreId,
18
}
19
20
impl<'b, T: Config> Store<'b, T> {
21
    /// Returns an immutable reference to the raw store.
22
27
    pub fn inner(&self) -> &wasm::Store<'b, T> {
23
27
        &self.inner
24
27
    }
25
26
    /// Deconstructs this checked store and returns its inner representation.
27
0
    pub fn into_inner(self) -> wasm::Store<'b, T> {
28
0
        self.inner
29
0
    }
30
31
    /// Returns the id of this store.
32
0
    pub fn id(&self) -> StoreId {
33
0
        self.id
34
0
    }
35
}
36
37
// All functions in this impl block must occur in the same order as they are
38
// defined in for the unchecked `Store` methods. Also all functions must follow
39
// the same implementation scheme to make sure they are only light wrappers:
40
//
41
// 1. try unwrap [stored parameter objects]
42
// 2. call [unchecked method]
43
// 3. rewrap [results into stored objects]
44
// 4. return [stored result objects]
45
impl<'b, T: Config> Store<'b, T> {
46
442
    pub fn new(user_data: T) -> Self {
47
442
        Self {
48
442
            inner: wasm::Store::new(user_data),
49
442
            id: StoreId::new(),
50
442
        }
51
442
    }
52
53
    /// This is a safe variant of
54
    /// [`Store::module_instantiate`](wasm::Store::module_instantiate).
55
294
    pub fn module_instantiate(
56
294
        &mut self,
57
294
        validation_info: &Module<'b>,
58
294
        extern_vals: Vec<StoredExternVal>,
59
294
        maybe_fuel: Option<u64>,
60
294
    ) -> Result<StoredInstantiationOutcome, RuntimeError> {
61
        // 1. try unwrap
62
294
        let extern_vals = extern_vals.try_unwrap_into_bare(self.id);
63
        // 2. call
64
        // SAFETY: It was just checked that the `ExternVal`s came from the
65
        // current store through their store ids.
66
292
        let instantiation_outcome = unsafe {
67
294
            self.inner
68
294
                .module_instantiate(validation_info, extern_vals, maybe_fuel)
69
2
        }?;
70
        // 3. rewrap
71
        // SAFETY: The `InstantiationOutcome` just came from the current store.
72
292
        let stored_instantiation_outcome =
73
292
            unsafe { StoredInstantiationOutcome::from_bare(instantiation_outcome, self.id) };
74
        // 4. return
75
292
        Ok(stored_instantiation_outcome)
76
294
    }
77
78
    /// This is a safe variant of
79
    /// [`Store::instance_export`](wasm::Store::instance_export).
80
48.1k
    pub fn instance_export(
81
48.1k
        &self,
82
48.1k
        module_addr: Stored<ModuleAddr>,
83
48.1k
        name: &str,
84
48.1k
    ) -> Result<StoredExternVal, RuntimeError> {
85
        // 1. try unwrap
86
48.1k
        let module_addr = module_addr.try_unwrap_into_bare(self.id);
87
        // 2. call
88
        // SAFETY: It was just checked that the `ModuleAddr` came from the
89
        // current store through its store id.
90
48.1k
        let extern_val = unsafe { self.inner.instance_export(module_addr, name) }
?0
;
91
        // 3. rewrap
92
        // SAFETY: The `ExternVal` just came from the current store.
93
48.1k
        let stored_extern_val = unsafe { StoredExternVal::from_bare(extern_val, self.id) };
94
        // 4. return
95
48.1k
        Ok(stored_extern_val)
96
48.1k
    }
97
98
    /// This is a variant of [`Store::func_alloc`](wasm::Store::func_alloc). It
99
    /// is functionally equal, with the only difference being that this function
100
    /// returns a [`Stored<FuncAddr>`].
101
    #[allow(clippy::let_and_return)] // reason = "to follow the 1234 structure"
102
1.02k
    pub fn func_alloc(&mut self, func_type: FuncType, hostcode: Hostcode) -> Stored<FuncAddr> {
103
        // 1. try unwrap
104
        // no stored parameters
105
        // 2. call
106
1.02k
        let func_addr = self.inner.func_alloc(func_type, hostcode);
107
        // 3. rewrap
108
        // 4. return
109
        // SAFETY: The function address just came from the current store.
110
1.02k
        unsafe { Stored::from_bare(func_addr, self.id) }
111
1.02k
    }
112
113
    /// This is a safe variant of [`Store::func_type`](wasm::Store::func_type).
114
0
    pub fn func_type(&self, func_addr: Stored<FuncAddr>) -> FuncType {
115
        // 1. try unwrap
116
0
        let func_addr = func_addr.try_unwrap_into_bare(self.id);
117
        // 2. call
118
        // 3. rewrap
119
        // `FuncType` does not have a stored variant.
120
        // 4. return
121
        // SAFETY: It was just checked that the `FuncAddr` came from the current
122
        // store through its store id.
123
0
        unsafe { self.inner.func_type(func_addr) }
124
0
    }
125
126
    /// This is a safe variant of [`Store::invoke`](wasm::Store::invoke).
127
1
    pub fn invoke(
128
1
        &mut self,
129
1
        func_addr: Stored<FuncAddr>,
130
1
        params: Vec<StoredValue>,
131
1
        maybe_fuel: Option<u64>,
132
1
    ) -> Result<StoredRunState, RuntimeError> {
133
        // 1. try unwrap
134
1
        let func_addr = func_addr.try_unwrap_into_bare(self.id);
135
1
        let params = params.try_unwrap_into_bare(self.id);
136
        // 2. call
137
        // SAFETY: It was just checked that the `FuncAddr` and any addresses in
138
        // the parameters came from the current store through their store ids.
139
1
        let run_state = unsafe { self.inner.invoke(func_addr, params, maybe_fuel) }
?0
;
140
        // 3. rewrap
141
        // SAFETY: The `RunState` just came from the current store.
142
1
        let stored_run_state = unsafe { StoredRunState::from_bare(run_state, self.id) };
143
        // 4. return
144
1
        Ok(stored_run_state)
145
1
    }
146
147
    /// This is a safe variant of
148
    /// [`Store::table_alloc`](wasm::Store::table_alloc).
149
145
    pub fn table_alloc(
150
145
        &mut self,
151
145
        table_type: TableType,
152
145
        r#ref: StoredRef,
153
145
    ) -> Result<Stored<TableAddr>, RuntimeError> {
154
        // 1. try unwrap
155
145
        let r#ref = r#ref.try_unwrap_into_bare(self.id);
156
        // 2. call
157
        // SAFETY: It was just checked that any address in the reference came
158
        // from the current store through its store id.
159
145
        let table_addr = unsafe { self.inner.table_alloc(table_type, r#ref) }
?0
;
160
        // 3. rewrap
161
        // SAFETY: The `TableAddr` just came from the current store.
162
145
        let stored_table_addr = unsafe { Stored::from_bare(table_addr, self.id) };
163
        // 4. return
164
145
        Ok(stored_table_addr)
165
145
    }
166
167
    /// This is a safe variant of
168
    /// [`Store::table_type`](wasm::Store::table_type).
169
0
    pub fn table_type(&self, table_addr: Stored<TableAddr>) -> TableType {
170
        // 1. try unwrap
171
0
        let table_addr = table_addr.try_unwrap_into_bare(self.id);
172
        // 2. call
173
        // 3. rewrap
174
        // `TableType` has no stored variant.
175
        // 4. return
176
        // SAFETY: It was just checked that the `TableAddr` came from the
177
        // current store through its store id.
178
0
        unsafe { self.inner.table_type(table_addr) }
179
0
    }
180
181
    /// This is a safe variant of
182
    /// [`Store::table_read`](wasm::Store::table_read).
183
2
    pub fn table_read(
184
2
        &self,
185
2
        table_addr: Stored<TableAddr>,
186
2
        i: u32,
187
2
    ) -> Result<StoredRef, RuntimeError> {
188
        // 1. try unwrap
189
2
        let table_addr = table_addr.try_unwrap_into_bare(self.id);
190
        // 2. call
191
        // SAFETY: It was just checked that the `TableAddr` came from the
192
        // current store through its store id.
193
2
        let r#ref = unsafe { self.inner.table_read(table_addr, i) }
?0
;
194
        // 3. rewrap
195
        // SAFETY: The `Ref` ust came from the current store.
196
2
        let stored_ref = unsafe { StoredRef::from_bare(r#ref, self.id) };
197
        // 4. return
198
2
        Ok(stored_ref)
199
2
    }
200
201
    /// This is a safe variant of
202
    /// [`Store::table_write`](wasm::Store::table_write).
203
0
    pub fn table_write(
204
0
        &mut self,
205
0
        table_addr: Stored<TableAddr>,
206
0
        i: u32,
207
0
        r#ref: StoredRef,
208
0
    ) -> Result<(), RuntimeError> {
209
        // 1. try unwrap
210
0
        let table_addr = table_addr.try_unwrap_into_bare(self.id);
211
0
        let r#ref = r#ref.try_unwrap_into_bare(self.id);
212
        // 2. call
213
        // SAFETY: It was just checked that the `TableAddr` and any address in
214
        // the reference came from the current store through their store ids.
215
0
        unsafe { self.inner.table_write(table_addr, i, r#ref) }?;
216
        // 3. rewrap
217
        // result is the unit type.
218
        // 4. return
219
0
        Ok(())
220
0
    }
221
222
    /// This is a safe variant of
223
    /// [`Store::table_size`](wasm::Store::table_size).
224
0
    pub fn table_size(&self, table_addr: Stored<TableAddr>) -> u32 {
225
        // 1. try unwrap
226
0
        let table_addr = table_addr.try_unwrap_into_bare(self.id);
227
        // 2. call
228
        // 3. rewrap
229
        // table size has no stored variant.
230
        // 4. return
231
        // SAFETY: It was just checked that the `TableAddr` came from the
232
        // current store through its store id.
233
0
        unsafe { self.inner.table_size(table_addr) }
234
0
    }
235
236
    /// This is a variant of [`Store::mem_alloc`](wasm::Store::mem_alloc) that
237
    /// returns a stored object.
238
    #[allow(clippy::let_and_return)] // reason = "to follow the 1234 structure"
239
147
    pub fn mem_alloc(&mut self, mem_type: MemType) -> Stored<MemAddr> {
240
        // 1. try unwrap
241
        // no stored parameters
242
        // 2. call
243
147
        let mem_addr = self.inner.mem_alloc(mem_type);
244
        // 3. rewrap
245
        // 4. return
246
        // SAFETY: The `MemAddr` just came from the current store.
247
147
        unsafe { Stored::from_bare(mem_addr, self.id) }
248
147
    }
249
250
    /// This is a safe variant of [`Store::mem_type`](wasm::Store::mem_type).
251
0
    pub fn mem_type(&self, mem_addr: Stored<MemAddr>) -> MemType {
252
        // 1. try unwrap
253
0
        let mem_addr = mem_addr.try_unwrap_into_bare(self.id);
254
        // 2. call
255
        // 3. rewrap
256
        // `MemType` does not have a stored variant.
257
        // 4. return
258
        // SAFETY: It was just checked that the `MemAddr` came from the current
259
        // store through its store id.
260
0
        unsafe { self.inner.mem_type(mem_addr) }
261
0
    }
262
263
    /// This is a safe variant of [`Store::mem_read`](wasm::Store::mem_read).
264
210
    pub fn mem_read(&self, mem_addr: Stored<MemAddr>, i: u32) -> Result<u8, RuntimeError> {
265
        // 1. try unwrap
266
210
        let mem_addr = mem_addr.try_unwrap_into_bare(self.id);
267
        // 2. call
268
        // SAFETY: It was just checked that the `MemAddr` came from the current
269
        // store through its store id.
270
210
        let byte = unsafe { self.inner.mem_read(mem_addr, i) }
?0
;
271
        // 3. rewrap
272
        // a single byte does not have a stored variant.
273
        // 4. return
274
210
        Ok(byte)
275
210
    }
276
277
    /// This is a safe variant of [`Store::mem_write`](wasm::Store::mem_write).
278
0
    pub fn mem_write(
279
0
        &mut self,
280
0
        mem_addr: Stored<MemAddr>,
281
0
        i: u32,
282
0
        byte: u8,
283
0
    ) -> Result<(), RuntimeError> {
284
        // 1. try unwrap
285
0
        let mem_addr = mem_addr.try_unwrap_into_bare(self.id);
286
        // 2. call
287
        // SAFETY: It was just checked that the `MemAddr` came from the current
288
        // store through its store id.
289
0
        unsafe { self.inner.mem_write(mem_addr, i, byte) }?;
290
        // 3. rewrap
291
        // result is the unit type.
292
        // 4. return
293
0
        Ok(())
294
0
    }
295
296
    /// This is a safe variant of [`Store::mem_size`](wasm::Store::mem_size).
297
0
    pub fn mem_size(&self, mem_addr: Stored<MemAddr>) -> u32 {
298
        // 1. try unwrap
299
0
        let mem_addr = mem_addr.try_unwrap_into_bare(self.id);
300
        // 2. call
301
        // 3. rewrap
302
        // mem size does not have a stored variant.
303
        // 4. return
304
        // SAFETY: It was just checked that the `MemAddr` came from the current
305
        // store through its store id.
306
0
        unsafe { self.inner.mem_size(mem_addr) }
307
0
    }
308
309
    /// This is a safe variant of [`Store::mem_grow`](wasm::Store::mem_grow).
310
0
    pub fn mem_grow(&mut self, mem_addr: Stored<MemAddr>, n: u32) -> Result<(), RuntimeError> {
311
        // 1. try unwrap
312
0
        let mem_addr = mem_addr.try_unwrap_into_bare(self.id);
313
        // 2. call
314
        // SAFETY: It was just checked that the `MemAddr` came from the current
315
        // store through its store id.
316
0
        unsafe { self.inner.mem_grow(mem_addr, n) }?;
317
        // 3. rewrap
318
        // result is the unit type.
319
        // 4. return
320
0
        Ok(())
321
0
    }
322
323
    /// This is a safe variant of
324
    /// [`Store::global_alloc`](wasm::Store::global_alloc).
325
580
    pub fn global_alloc(
326
580
        &mut self,
327
580
        global_type: GlobalType,
328
580
        val: StoredValue,
329
580
    ) -> Result<Stored<GlobalAddr>, RuntimeError> {
330
        // 1. try unwrap
331
580
        let val = val.try_unwrap_into_bare(self.id);
332
        // 2. call
333
        // SAFETY: It was just checked that any address the value came from the
334
        // current store through its store id.
335
580
        let global_addr = unsafe { self.inner.global_alloc(global_type, val) }
?0
;
336
        // 3. rewrap
337
        // SAFETY: The `GlobalAddr` just came from the current store.
338
580
        let stored_global_addr = unsafe { Stored::from_bare(global_addr, self.id) };
339
        // 4. return
340
580
        Ok(stored_global_addr)
341
580
    }
342
343
    /// This is a safe variant of
344
    /// [`Store::global_type`](wasm::Store::global_type).
345
2
    pub fn global_type(&self, global_addr: Stored<GlobalAddr>) -> Result<GlobalType, RuntimeError> {
346
        // 1. try unwrap
347
2
        let global_addr = global_addr.try_unwrap_into_bare(self.id);
348
        // 2. call
349
        // SAFETY: It was just checked that the `GlobalAddr` came from the
350
        // current store through its store id.
351
2
        let global_type = unsafe { self.inner.global_type(global_addr) };
352
        // 3. rewrap
353
        // `GlobalType` does not have a stored variant.
354
        // 4. return
355
2
        Ok(global_type)
356
2
    }
357
358
    /// This is a safe variant of
359
    /// [`Store::global_read`](wasm::Store::global_read).
360
99
    pub fn global_read(&self, global_addr: Stored<GlobalAddr>) -> StoredValue {
361
        // 1. try unwrap
362
99
        let global_addr = global_addr.try_unwrap_into_bare(self.id);
363
        // 2. call
364
        // SAFETY: It was just checked that the `GlobalAddr` came from the
365
        // current store through its store id.
366
99
        let value = unsafe { self.inner.global_read(global_addr) };
367
        // 3. rewrap
368
        // 4. return
369
        // SAFETY: The `Value` just came from the current store.
370
99
        unsafe { StoredValue::from_bare(value, self.id) }
371
99
    }
372
373
    /// This is a safe variant of
374
    /// [`Store::global_write`](wasm::Store::global_write).
375
1
    pub fn global_write(
376
1
        &mut self,
377
1
        global_addr: Stored<GlobalAddr>,
378
1
        val: StoredValue,
379
1
    ) -> Result<(), RuntimeError> {
380
        // 1. try unwrap
381
1
        let global_addr = global_addr.try_unwrap_into_bare(self.id);
382
1
        let val = val.try_unwrap_into_bare(self.id);
383
        // 2. call
384
        // SAFETY: It was just checked that the `GlobalAddr` any any address
385
        // contained in the value came from the current store through their
386
        // store ids.
387
1
        unsafe { self.inner.global_write(global_addr, val) }
?0
;
388
        // 3. rewrap
389
        // result is the unit type.
390
        // 4. return
391
1
        Ok(())
392
1
    }
393
394
    /// This is a safe variant of
395
    /// [`Store::create_resumable`](wasm::Store::create_resumable).
396
47.8k
    pub fn create_resumable(
397
47.8k
        &self,
398
47.8k
        func_addr: Stored<FuncAddr>,
399
47.8k
        params: Vec<StoredValue>,
400
47.8k
        maybe_fuel: Option<u64>,
401
47.8k
    ) -> Result<StoredResumable, RuntimeError> {
402
        // 1. try unwrap
403
47.8k
        let func_addr = func_addr.try_unwrap_into_bare(self.id);
404
47.8k
        let params = params.try_unwrap_into_bare(self.id);
405
        // 2. call
406
        // SAFETY: It was just checked that the `FuncAddr` any any addresses
407
        // contained in the parameters came from the current store through their
408
        // store ids.
409
47.8k
        let resumable = unsafe { self.inner.create_resumable(func_addr, params, maybe_fuel) }
?0
;
410
        // 3. rewrap
411
        // SAFETY: The `Resumable` just came from the current store.
412
47.8k
        let stored_resumable = unsafe { StoredResumable::from_bare(resumable, self.id) };
413
        // 4. return
414
47.8k
        Ok(stored_resumable)
415
47.8k
    }
416
417
    /// This is a safe variant of [`Store::resume`](wasm::Store::resume).
418
47.8k
    pub fn resume(&mut self, resumable: StoredResumable) -> Result<StoredRunState, RuntimeError> {
419
        // 1. try unwrap
420
47.8k
        let resumable = resumable.try_unwrap_into_bare(self.id);
421
        // 2. call
422
        // SAFETY: It was just checked that the `Resumable` came from the
423
        // current store through its store id.
424
47.8k
        let 
run_state45.3k
= unsafe { self.inner.resume(resumable) }
?2.42k
;
425
        // 3. rewrap
426
        // SAFETY: The `RunState` just came from the current store.
427
45.3k
        let stored_run_state = unsafe { StoredRunState::from_bare(run_state, self.id) };
428
        // 4. return
429
45.3k
        Ok(stored_run_state)
430
47.8k
    }
431
432
    /// This is a safe variant of [`Store::resume_wasm`](wasm::Store::resume_wasm).
433
72
    pub fn resume_wasm(
434
72
        &mut self,
435
72
        resumable: Stored<WasmResumable>,
436
72
    ) -> Result<StoredRunState, RuntimeError> {
437
        // 1. try unwrap
438
72
        let resumable = resumable.try_unwrap_into_bare(self.id);
439
        // 2. call
440
        // SAFETY: It was just checked that the `WasmResumable` came from the
441
        // current store through its store id.
442
72
        let run_state = unsafe { self.inner.resume_wasm(resumable) }
?0
;
443
        // 3. rewrap
444
        // SAFETY: The `RunState` just came from the current store.
445
72
        let stored_run_state = unsafe { StoredRunState::from_bare(run_state, self.id) };
446
        // 4. return
447
72
        Ok(stored_run_state)
448
72
    }
449
450
    /// This is a safe variant of [`wasm::Store::finish_host_call`].
451
28
    pub fn finish_host_call(
452
28
        &mut self,
453
28
        host_resumable: Stored<HostResumable>,
454
28
        host_call_return_values: Vec<StoredValue>,
455
28
    ) -> Result<StoredRunState, RuntimeError> {
456
        // 1. try unwrap
457
28
        let host_resumable = host_resumable.try_unwrap_into_bare(self.id);
458
28
        let host_call_return_values = host_call_return_values.try_unwrap_into_bare(self.id);
459
        // 2. call
460
        // SAFETY: It was just checked that the `HostResumable` and all `Value`s
461
        // came from the current store through their store ids.
462
27
        let run_state = unsafe {
463
28
            self.inner
464
28
                .finish_host_call(host_resumable, host_call_return_values)
465
1
        }?;
466
        // 3. rewrap
467
        // SAFETY: The `RunState`s just came from the current store.
468
27
        let stored_run_state = unsafe { StoredRunState::from_bare(run_state, self.id) };
469
        // 4. return
470
27
        Ok(stored_run_state)
471
28
    }
472
473
    /// This is a safe variant of
474
    /// [`Store::invoke_simple`](wasm::Store::invoke_simple)
475
6.84k
    pub fn invoke_simple(
476
6.84k
        &mut self,
477
6.84k
        function: Stored<FuncAddr>,
478
6.84k
        params: Vec<StoredValue>,
479
6.84k
    ) -> Result<Vec<StoredValue>, RuntimeError> {
480
        // 1. try unwrap
481
6.84k
        let function = function.try_unwrap_into_bare(self.id);
482
6.84k
        let params = params.try_unwrap_into_bare(self.id);
483
        // 2. call
484
        // SAFETY: It was just checked that the `FuncAddr` and all `Value`s came
485
        // from the current store through their store ids.
486
6.84k
        let 
return_values6.17k
= unsafe { self.inner.invoke_simple(function, params) }
?667
;
487
        // 3. rewrap
488
        // SAFETY: The `Value`s just came from the current store.
489
6.17k
        let stored_return_values = unsafe { Vec::from_bare(return_values, self.id) };
490
        // 4. return
491
6.17k
        Ok(stored_return_values)
492
6.84k
    }
493
494
    /// This is a safe variant of
495
    /// [`Store::mem_access_mut_slice`](crate::Store::mem_access_mut_slice).
496
3
    pub fn mem_access_mut_slice<R>(
497
3
        &self,
498
3
        memory: Stored<MemAddr>,
499
3
        accessor: impl FnOnce(&mut [u8]) -> R,
500
3
    ) -> R {
501
        // 1. try unwrap
502
3
        let memory = memory.try_unwrap_into_bare(self.id);
503
        // 2. call
504
        // 3. rewrap
505
        // result is generic
506
        // 4. return
507
        // SAFETY: It was just checked that the `MemAddr` came from the current
508
        // store through its store id.
509
3
        unsafe { self.inner.mem_access_mut_slice(memory, accessor) }
510
3
    }
511
512
    /// This is a safe variant of
513
    /// [`Store::instance_exports`](wasm::Store::instance_exports)
514
0
    pub fn instance_exports(
515
0
        &self,
516
0
        module_addr: Stored<ModuleAddr>,
517
0
    ) -> Vec<(String, StoredExternVal)> {
518
        // 1. try unwrap
519
0
        let module_addr = module_addr.try_unwrap_into_bare(self.id);
520
        // 2. call
521
        // SAFETY: We just checked that this module address is valid in the
522
        // current store through its store id.
523
0
        let exports = unsafe { self.inner.instance_exports(module_addr) };
524
        // 3. rewrap
525
        // 4. return
526
0
        exports
527
0
            .into_iter()
528
0
            .map(|(name, externval)| {
529
                // SAFETY: The `ExternVal`s just came from the current store.
530
0
                let stored_externval = unsafe { StoredExternVal::from_bare(externval, self.id) };
531
0
                (name, stored_externval)
532
0
            })
533
0
            .collect()
534
0
    }
535
}