Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/environ/src/scopevec.rs
1691 views
1
use crate::prelude::*;
2
use core::cell::RefCell;
3
4
/// Small data structure to help extend the lifetime of a slice to a higher
5
/// scope.
6
///
7
/// This is currently used during component translation where translation in
8
/// general works on a borrowed slice which contains all input modules, but
9
/// generated adapter modules for components don't live within the original
10
/// slice but the data structures are much easier if the dynamically generated
11
/// adapter modules live for the same lifetime as the original input slice. To
12
/// solve this problem this `ScopeVec` helper is used to move ownership of a
13
/// `Vec<T>` to a higher scope in the program, then borrowing the slice from
14
/// that scope.
15
pub struct ScopeVec<T> {
16
data: RefCell<Vec<Box<[T]>>>,
17
}
18
19
impl<T> ScopeVec<T> {
20
/// Creates a new blank scope.
21
pub fn new() -> ScopeVec<T> {
22
ScopeVec {
23
data: Default::default(),
24
}
25
}
26
27
/// Transfers ownership of `data` into this scope and then yields the slice
28
/// back to the caller.
29
///
30
/// The original data will be deallocated when `self` is dropped.
31
pub fn push(&self, data: Vec<T>) -> &mut [T] {
32
let data: Box<[T]> = data.into();
33
let len = data.len();
34
35
let mut storage = self.data.borrow_mut();
36
storage.push(data);
37
let ptr = storage.last_mut().unwrap().as_mut_ptr();
38
39
// This should be safe for a few reasons:
40
//
41
// * The returned pointer on the heap that `data` owns. Despite moving
42
// `data` around it doesn't actually move the slice itself around, so
43
// the pointer returned should be valid (and length).
44
//
45
// * The lifetime of the returned pointer is connected to the lifetime
46
// of `self`. This reflects how when `self` is destroyed the `data` is
47
// destroyed as well, or otherwise the returned slice will be valid
48
// for as long as `self` is valid since `self` owns the original data
49
// at that point.
50
//
51
// * This function was given ownership of `data` so it should be safe to
52
// hand back a mutable reference. Once placed within a `ScopeVec` the
53
// data is never mutated so the caller will enjoy exclusive access to
54
// the slice of the original vec.
55
//
56
// This all means that it should be safe to return a mutable slice of
57
// all of `data` after the data has been pushed onto our internal list.
58
unsafe { core::slice::from_raw_parts_mut(ptr, len) }
59
}
60
61
/// Iterate over items in this `ScopeVec`, consuming ownership.
62
pub fn into_iter(self) -> impl ExactSizeIterator<Item = Box<[T]>> {
63
self.data.into_inner().into_iter()
64
}
65
}
66
67
#[cfg(test)]
68
mod tests {
69
use super::ScopeVec;
70
use crate::prelude::*;
71
72
#[test]
73
fn smoke() {
74
let scope = ScopeVec::new();
75
let a = scope.push(Vec::new());
76
let b = scope.push(vec![1, 2, 3]);
77
let c = scope.push(vec![4, 5, 6]);
78
assert_eq!(a.len(), 0);
79
b[0] = 4;
80
c[2] = 5;
81
assert_eq!(a, []);
82
assert_eq!(b, [4, 2, 3]);
83
assert_eq!(c, [4, 5, 5]);
84
}
85
}
86
87