vasi/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#![no_std]
// https://github.com/rust-lang/rfcs/blob/master/text/2585-unsafe-block-in-unsafe-fn.md
#![deny(unsafe_op_in_unsafe_fn)]

// For use by code generated by vasi_macro::VirtualAddressSpaceIndependent;
#[doc(hidden)]
pub use static_assertions::assert_impl_all;
pub use vasi_macro::VirtualAddressSpaceIndependent;
/// A type implementing this trait guarantees that accessing instances
/// of that type outside of their original virtual address space does not
/// violate Rust's safety requirements.
///
/// This is mostly equivalent to them being *self-contained*: not referring to
/// memory outside of the range `[&self, &self + std::mem::sizeof<T>()]`.
/// However, they *may* reference memory outside of that range if they somehow
/// ensure that they only do so from inside the virtual address space where it
/// is valid to do so.
///
/// Types implementing this trait can definitely not contain references.  If
/// they contain pointers, the type is responsible for ensuring those pointers
/// aren't dereferenced outside a virtual address space where they are valid.
///
/// *Relative* pointers, e.g. as implemented in
/// [rkyv](https://crates.io/crates/rkyv), are acceptable as long as they point
/// within the boundaries of the enclosing type.
///
/// The type must also be FFI-safe; e.g. have a stable layout (e.g. `[repr(C)]`),
/// to help ensure that different processes accessing data of a given type
/// actually agree on its layout.  Note though that is necessary, but not
/// sufficient, to ensure they agree on the layout; e.g. things can still go
/// wrong if processes use different versions of the type.  (TODO: maybe split
/// this property into a separate trait).
///
/// # Safety
///
/// The type must actually be self-contained, as above.
pub unsafe trait VirtualAddressSpaceIndependent {
    /// Used by the derive macro to validate that fields are Vasi.
    const IGNORE: () = ();
}

// Types not containing any pointers are trivially VirtualAddressSpaceIndependent.
unsafe impl VirtualAddressSpaceIndependent for i64 {}
unsafe impl VirtualAddressSpaceIndependent for u64 {}
unsafe impl VirtualAddressSpaceIndependent for i32 {}
unsafe impl VirtualAddressSpaceIndependent for u32 {}
unsafe impl VirtualAddressSpaceIndependent for i16 {}
unsafe impl VirtualAddressSpaceIndependent for u16 {}
unsafe impl VirtualAddressSpaceIndependent for i8 {}
unsafe impl VirtualAddressSpaceIndependent for u8 {}
unsafe impl VirtualAddressSpaceIndependent for usize {}
unsafe impl VirtualAddressSpaceIndependent for isize {}
unsafe impl VirtualAddressSpaceIndependent for bool {}

// e.g. "This type has the same in-memory representation as the underlying integer type, u64"
unsafe impl VirtualAddressSpaceIndependent for core::sync::atomic::AtomicU64 {}
unsafe impl VirtualAddressSpaceIndependent for core::sync::atomic::AtomicI64 {}
unsafe impl VirtualAddressSpaceIndependent for core::sync::atomic::AtomicU32 {}
unsafe impl VirtualAddressSpaceIndependent for core::sync::atomic::AtomicI32 {}
unsafe impl VirtualAddressSpaceIndependent for core::sync::atomic::AtomicU16 {}
unsafe impl VirtualAddressSpaceIndependent for core::sync::atomic::AtomicI16 {}
unsafe impl VirtualAddressSpaceIndependent for core::sync::atomic::AtomicU8 {}
unsafe impl VirtualAddressSpaceIndependent for core::sync::atomic::AtomicI8 {}
unsafe impl VirtualAddressSpaceIndependent for core::sync::atomic::AtomicBool {}

// An array of T is [VirtualAddressSpaceIndependent] if its elements are.
unsafe impl<T, const N: usize> VirtualAddressSpaceIndependent for [T; N] where
    T: VirtualAddressSpaceIndependent
{
}

// PhantomData is intrinsically VirtualAddressSpaceIndependent.
//
// Conservatively only implement when T is VirtualAddressSpaceIndependent,
// but unclear whether this restriction is necessary.
unsafe impl<T> VirtualAddressSpaceIndependent for core::marker::PhantomData<T> where
    T: VirtualAddressSpaceIndependent
{
}

// Cell is `repr(transparent)` around an `UnsafeCell<T>`.
unsafe impl<T> VirtualAddressSpaceIndependent for core::cell::Cell<T> where
    T: VirtualAddressSpaceIndependent
{
}

// UnsafeCell is `repr(transparent)` around a `T`.
unsafe impl<T> VirtualAddressSpaceIndependent for core::cell::UnsafeCell<T> where
    T: VirtualAddressSpaceIndependent
{
}

// ManuallyDrop is `repr(transparent)` around a `<T>`.
unsafe impl<T> VirtualAddressSpaceIndependent for core::mem::ManuallyDrop<T> where
    T: VirtualAddressSpaceIndependent
{
}

// MaybeUninit is `repr(transparent)` around a union of `()` and `ManuallyDrop<T>`.
unsafe impl<T> VirtualAddressSpaceIndependent for core::mem::MaybeUninit<T> where
    T: VirtualAddressSpaceIndependent
{
}

unsafe impl VirtualAddressSpaceIndependent for () {}