Coverage Report

Created: 2026-04-02 14:31

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