1#![deny(missing_docs)]
8
9use fuchsia_runtime::vmar_root_self;
10use shared_buffer::SharedBuffer;
11use std::ops::{Deref, DerefMut};
12
13mod immutable;
14pub use immutable::{Error as ImmutableMappingError, ImmutableMapping};
15
16#[derive(Debug)]
23pub struct Mapping {
24 buffer: SharedBuffer,
25}
26
27impl Deref for Mapping {
28 type Target = SharedBuffer;
29 fn deref(&self) -> &Self::Target {
30 &self.buffer
31 }
32}
33
34impl DerefMut for Mapping {
35 fn deref_mut(&mut self) -> &mut Self::Target {
36 &mut self.buffer
37 }
38}
39
40impl Mapping {
41 pub fn allocate(size: usize) -> Result<(Self, zx::Vmo), zx::Status> {
46 let vmo = zx::Vmo::create(size as u64)?;
47 let flags = zx::VmarFlags::PERM_READ
48 | zx::VmarFlags::PERM_WRITE
49 | zx::VmarFlags::MAP_RANGE
50 | zx::VmarFlags::REQUIRE_NON_RESIZABLE;
51 let mapping = Self::create_from_vmo(&vmo, size, flags)?;
52 Ok((mapping, vmo))
53 }
54
55 pub fn allocate_with_name(size: usize, name: &str) -> Result<(Self, zx::Vmo), zx::Status> {
60 let name = zx::Name::new(name)?;
61 let vmo = zx::Vmo::create(size as u64)?;
62 vmo.set_name(&name)?;
63 let flags = zx::VmarFlags::PERM_READ
64 | zx::VmarFlags::PERM_WRITE
65 | zx::VmarFlags::MAP_RANGE
66 | zx::VmarFlags::REQUIRE_NON_RESIZABLE;
67 let mapping = Self::create_from_vmo(&vmo, size, flags)?;
68 Ok((mapping, vmo))
69 }
70
71 pub fn create_from_vmo(
76 vmo: &zx::Vmo,
77 size: usize,
78 flags: zx::VmarFlags,
79 ) -> Result<Self, zx::Status> {
80 let flags = flags | zx::VmarFlags::REQUIRE_NON_RESIZABLE;
81 let addr = vmar_root_self().map(0, &vmo, 0, size, flags)?;
82
83 let buffer = unsafe { SharedBuffer::new(addr as *mut u8, size) };
94 Ok(Mapping { buffer })
95 }
96
97 pub fn len(&self) -> usize {
99 self.buffer.len()
100 }
101}
102
103impl Drop for Mapping {
104 fn drop(&mut self) {
105 let (addr, size): (*mut u8, usize) = self.buffer.as_ptr_len();
106 let addr = addr as usize;
107
108 unsafe {
115 let _ = vmar_root_self().unmap(addr, size);
116 }
117 }
118}
119
120#[cfg(test)]
121mod tests {
122 use super::*;
123
124 const PAGE_SIZE: usize = 4096;
125
126 #[test]
127 fn test_create() {
128 let size = PAGE_SIZE;
129 let (mapping, _vmo) = Mapping::allocate(size).unwrap();
130 assert_eq!(size, mapping.len());
131 }
132
133 #[test]
134 fn test_create_from_vmo() {
135 let size = PAGE_SIZE;
136 let flags = zx::VmarFlags::PERM_READ | zx::VmarFlags::PERM_WRITE;
137 {
138 let vmo = zx::Vmo::create_with_opts(zx::VmoOptions::RESIZABLE, size as u64).unwrap();
140 let status = Mapping::create_from_vmo(&vmo, size, flags).unwrap_err();
141 assert_eq!(status, zx::Status::NOT_SUPPORTED);
142 }
143 {
144 let vmo = zx::Vmo::create(size as u64).unwrap();
145 let mapping = Mapping::create_from_vmo(&vmo, size, flags).unwrap();
146 assert_eq!(size, mapping.len());
147 }
148 }
149
150 #[test]
151 fn test_create_with_name() {
152 let size = PAGE_SIZE;
153 let (mapping, vmo) = Mapping::allocate_with_name(size, "TestName").unwrap();
154 assert_eq!(size, mapping.len());
155 assert_eq!("TestName", vmo.get_name().expect("Has name"));
156 let res = Mapping::allocate_with_name(size, "Invalid\0TestName");
157 assert_eq!(zx::Status::INVALID_ARGS, res.unwrap_err());
158 }
159
160 #[test]
161 fn test_mapping_read_write() {
162 let size = PAGE_SIZE;
163 let (mapping, vmo) = Mapping::allocate(size).unwrap();
164
165 let mut buf = [0; 128];
166
167 let s = b"Hello world";
169 vmo.write(s, 0).unwrap();
170 let slice = &mut buf[0..s.len()];
171 mapping.read(slice);
172 assert_eq!(s, slice);
173
174 let s = b"Goodbye world";
176 mapping.write(s);
177 let slice = &mut buf[0..s.len()];
178 vmo.read(slice, 0).unwrap();
179 assert_eq!(s, slice);
180 }
181}