Skip to main content

unittest/
user_memory.rs

1// Copyright 2026 The Fuchsia Authors
2//
3// Use of this source code is governed by a MIT-style
4// license that can be found in the LICENSE file or at
5// https://opensource.org/licenses/MIT
6
7use core::ffi::c_void;
8use core::ptr::NonNull;
9use zx_status::Status;
10
11// Opaque type for C++ UserMemory
12#[repr(C)]
13struct RawUserMemory {
14    _facade: zr::OpaqueFacade,
15}
16
17unsafe extern "C" {
18    fn unittest_user_memory_create(size: usize) -> *mut RawUserMemory;
19    fn unittest_user_memory_destroy(mem: *mut RawUserMemory);
20    fn unittest_user_memory_get_base(mem: *const RawUserMemory) -> usize;
21    fn unittest_user_memory_commit_and_map(mem: *mut RawUserMemory, size: usize) -> i32;
22    fn unittest_user_memory_vmo_write(
23        mem: *mut RawUserMemory,
24        ptr: *const c_void,
25        offset: u64,
26        len: u64,
27    ) -> i32;
28    fn unittest_user_memory_vmo_read(
29        mem: *mut RawUserMemory,
30        ptr: *mut c_void,
31        offset: u64,
32        len: u64,
33    ) -> i32;
34}
35
36/// UserMemory facilitates testing code that requires user memory.
37///
38/// Example:
39///    let mut mem = UserMemory::create(size).unwrap();
40///    mem.commit_and_map(size).unwrap();
41///    let out_ptr = UserOutPtr::<u32>::new(mem.base() as *mut u32);
42///    out_ptr.write(value).unwrap();
43pub struct UserMemory {
44    raw: NonNull<RawUserMemory>,
45}
46
47impl UserMemory {
48    pub fn create(size: usize) -> Option<Self> {
49        let raw = unsafe { unittest_user_memory_create(size) };
50        NonNull::new(raw).map(|raw| Self { raw })
51    }
52
53    pub fn base(&self) -> usize {
54        unsafe { unittest_user_memory_get_base(self.raw.as_ptr()) }
55    }
56
57    /// Ensures the mapping is committed and mapped such that usages will cause no faults.
58    pub fn commit_and_map(&mut self, size: usize) -> Result<(), Status> {
59        let status = unsafe { unittest_user_memory_commit_and_map(self.raw.as_ptr(), size) };
60        Status::ok(status)
61    }
62
63    /// Write to the underlying VMO directly, bypassing the mapping.
64    pub fn vmo_write(&mut self, data: &[u8], offset: u64) -> Result<(), Status> {
65        let status = unsafe {
66            unittest_user_memory_vmo_write(
67                self.raw.as_ptr(),
68                data.as_ptr() as *const c_void,
69                offset,
70                data.len() as u64,
71            )
72        };
73        Status::ok(status)
74    }
75
76    /// Read from the underlying VMO directly, bypassing the mapping.
77    pub fn vmo_read(&mut self, data: &mut [u8], offset: u64) -> Result<(), Status> {
78        let status = unsafe {
79            unittest_user_memory_vmo_read(
80                self.raw.as_ptr(),
81                data.as_mut_ptr() as *mut c_void,
82                offset,
83                data.len() as u64,
84            )
85        };
86        Status::ok(status)
87    }
88}
89
90impl Drop for UserMemory {
91    fn drop(&mut self) {
92        unsafe { unittest_user_memory_destroy(self.raw.as_ptr()) };
93    }
94}