xref: /aosp_15_r20/external/crosvm/ext2/src/arena.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2024 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker //! Defines an arena allocator backed by `base::MemoryMapping`.
6*bb4ee6a4SAndroid Build Coastguard Worker 
7*bb4ee6a4SAndroid Build Coastguard Worker use std::cell::RefCell;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeSet;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::File;
10*bb4ee6a4SAndroid Build Coastguard Worker 
11*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::anyhow;
12*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::bail;
13*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Context;
14*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Result;
15*bb4ee6a4SAndroid Build Coastguard Worker use base::MappedRegion;
16*bb4ee6a4SAndroid Build Coastguard Worker use base::MemoryMapping;
17*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::AsBytes;
18*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::FromBytes;
19*bb4ee6a4SAndroid Build Coastguard Worker 
20*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
21*bb4ee6a4SAndroid Build Coastguard Worker struct Region {
22*bb4ee6a4SAndroid Build Coastguard Worker     start: usize,
23*bb4ee6a4SAndroid Build Coastguard Worker     len: usize,
24*bb4ee6a4SAndroid Build Coastguard Worker }
25*bb4ee6a4SAndroid Build Coastguard Worker 
26*bb4ee6a4SAndroid Build Coastguard Worker /// Manages a set of regions that are not overlapping each other.
27*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Default)]
28*bb4ee6a4SAndroid Build Coastguard Worker struct RegionManager(BTreeSet<Region>);
29*bb4ee6a4SAndroid Build Coastguard Worker 
30*bb4ee6a4SAndroid Build Coastguard Worker impl RegionManager {
allocate(&mut self, start: usize, len: usize) -> Result<()>31*bb4ee6a4SAndroid Build Coastguard Worker     fn allocate(&mut self, start: usize, len: usize) -> Result<()> {
32*bb4ee6a4SAndroid Build Coastguard Worker         // Allocation needs to fail if there exists a region that overlaps with [start, start+len).
33*bb4ee6a4SAndroid Build Coastguard Worker         // A region r is overlapping with [start, start+len) if and only if:
34*bb4ee6a4SAndroid Build Coastguard Worker         // r.start <= (start+len) && start <= (r.start+r.len)
35*bb4ee6a4SAndroid Build Coastguard Worker         //
36*bb4ee6a4SAndroid Build Coastguard Worker         // So, we first find the last region where r.start <= (start+len) holds.
37*bb4ee6a4SAndroid Build Coastguard Worker         let left = self
38*bb4ee6a4SAndroid Build Coastguard Worker             .0
39*bb4ee6a4SAndroid Build Coastguard Worker             .range(
40*bb4ee6a4SAndroid Build Coastguard Worker                 ..Region {
41*bb4ee6a4SAndroid Build Coastguard Worker                     start: start + len,
42*bb4ee6a4SAndroid Build Coastguard Worker                     len: 0,
43*bb4ee6a4SAndroid Build Coastguard Worker                 },
44*bb4ee6a4SAndroid Build Coastguard Worker             )
45*bb4ee6a4SAndroid Build Coastguard Worker             .next_back()
46*bb4ee6a4SAndroid Build Coastguard Worker             .copied();
47*bb4ee6a4SAndroid Build Coastguard Worker 
48*bb4ee6a4SAndroid Build Coastguard Worker         // New region to be added.
49*bb4ee6a4SAndroid Build Coastguard Worker         let new = match left {
50*bb4ee6a4SAndroid Build Coastguard Worker             None => Region { start, len },
51*bb4ee6a4SAndroid Build Coastguard Worker             Some(r) => {
52*bb4ee6a4SAndroid Build Coastguard Worker                 if start < r.start + r.len {
53*bb4ee6a4SAndroid Build Coastguard Worker                     bail!(
54*bb4ee6a4SAndroid Build Coastguard Worker                         "range overlaps: existing: {:?}, new: {:?}",
55*bb4ee6a4SAndroid Build Coastguard Worker                         left,
56*bb4ee6a4SAndroid Build Coastguard Worker                         Region { start, len }
57*bb4ee6a4SAndroid Build Coastguard Worker                     );
58*bb4ee6a4SAndroid Build Coastguard Worker                 }
59*bb4ee6a4SAndroid Build Coastguard Worker 
60*bb4ee6a4SAndroid Build Coastguard Worker                 // if `r` and the new region is adjacent, merge them.
61*bb4ee6a4SAndroid Build Coastguard Worker                 // otherwise, just return the new region.
62*bb4ee6a4SAndroid Build Coastguard Worker                 if start == r.start + r.len {
63*bb4ee6a4SAndroid Build Coastguard Worker                     let new = Region {
64*bb4ee6a4SAndroid Build Coastguard Worker                         start: r.start,
65*bb4ee6a4SAndroid Build Coastguard Worker                         len: r.len + len,
66*bb4ee6a4SAndroid Build Coastguard Worker                     };
67*bb4ee6a4SAndroid Build Coastguard Worker                     self.0.remove(&r);
68*bb4ee6a4SAndroid Build Coastguard Worker                     new
69*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
70*bb4ee6a4SAndroid Build Coastguard Worker                     Region { start, len }
71*bb4ee6a4SAndroid Build Coastguard Worker                 }
72*bb4ee6a4SAndroid Build Coastguard Worker             }
73*bb4ee6a4SAndroid Build Coastguard Worker         };
74*bb4ee6a4SAndroid Build Coastguard Worker 
75*bb4ee6a4SAndroid Build Coastguard Worker         // If there exists a region that starts from `new.start + new.len`,
76*bb4ee6a4SAndroid Build Coastguard Worker         // it should be merged with `new`.
77*bb4ee6a4SAndroid Build Coastguard Worker         let right = self
78*bb4ee6a4SAndroid Build Coastguard Worker             .0
79*bb4ee6a4SAndroid Build Coastguard Worker             .range(
80*bb4ee6a4SAndroid Build Coastguard Worker                 Region {
81*bb4ee6a4SAndroid Build Coastguard Worker                     start: new.start + new.len,
82*bb4ee6a4SAndroid Build Coastguard Worker                     len: 0,
83*bb4ee6a4SAndroid Build Coastguard Worker                 }..,
84*bb4ee6a4SAndroid Build Coastguard Worker             )
85*bb4ee6a4SAndroid Build Coastguard Worker             .next()
86*bb4ee6a4SAndroid Build Coastguard Worker             .copied();
87*bb4ee6a4SAndroid Build Coastguard Worker         match right {
88*bb4ee6a4SAndroid Build Coastguard Worker             Some(r) if r.start == new.start + new.len => {
89*bb4ee6a4SAndroid Build Coastguard Worker                 // merge and insert
90*bb4ee6a4SAndroid Build Coastguard Worker                 let merged = Region {
91*bb4ee6a4SAndroid Build Coastguard Worker                     start: new.start,
92*bb4ee6a4SAndroid Build Coastguard Worker                     len: new.len + r.len,
93*bb4ee6a4SAndroid Build Coastguard Worker                 };
94*bb4ee6a4SAndroid Build Coastguard Worker                 self.0.remove(&r);
95*bb4ee6a4SAndroid Build Coastguard Worker                 self.0.insert(merged);
96*bb4ee6a4SAndroid Build Coastguard Worker             }
97*bb4ee6a4SAndroid Build Coastguard Worker             Some(_) | None => {
98*bb4ee6a4SAndroid Build Coastguard Worker                 // just insert
99*bb4ee6a4SAndroid Build Coastguard Worker                 self.0.insert(new);
100*bb4ee6a4SAndroid Build Coastguard Worker             }
101*bb4ee6a4SAndroid Build Coastguard Worker         }
102*bb4ee6a4SAndroid Build Coastguard Worker 
103*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
104*bb4ee6a4SAndroid Build Coastguard Worker     }
105*bb4ee6a4SAndroid Build Coastguard Worker 
106*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(test)]
to_vec(&self) -> Vec<&Region>107*bb4ee6a4SAndroid Build Coastguard Worker     fn to_vec(&self) -> Vec<&Region> {
108*bb4ee6a4SAndroid Build Coastguard Worker         self.0.iter().collect()
109*bb4ee6a4SAndroid Build Coastguard Worker     }
110*bb4ee6a4SAndroid Build Coastguard Worker }
111*bb4ee6a4SAndroid Build Coastguard Worker 
112*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_region_manager()113*bb4ee6a4SAndroid Build Coastguard Worker fn test_region_manager() {
114*bb4ee6a4SAndroid Build Coastguard Worker     let mut rm: RegionManager = Default::default();
115*bb4ee6a4SAndroid Build Coastguard Worker 
116*bb4ee6a4SAndroid Build Coastguard Worker     rm.allocate(0, 5).unwrap();
117*bb4ee6a4SAndroid Build Coastguard Worker     assert_eq!(rm.to_vec(), vec![&Region { start: 0, len: 5 }]);
118*bb4ee6a4SAndroid Build Coastguard Worker     rm.allocate(10, 5).unwrap();
119*bb4ee6a4SAndroid Build Coastguard Worker     rm.allocate(15, 5).unwrap(); // will be merged into the previous one
120*bb4ee6a4SAndroid Build Coastguard Worker     assert_eq!(
121*bb4ee6a4SAndroid Build Coastguard Worker         rm.to_vec(),
122*bb4ee6a4SAndroid Build Coastguard Worker         vec![&Region { start: 0, len: 5 }, &Region { start: 10, len: 10 }]
123*bb4ee6a4SAndroid Build Coastguard Worker     );
124*bb4ee6a4SAndroid Build Coastguard Worker     rm.allocate(3, 5).unwrap_err(); // fail
125*bb4ee6a4SAndroid Build Coastguard Worker     rm.allocate(8, 5).unwrap_err(); // fail
126*bb4ee6a4SAndroid Build Coastguard Worker 
127*bb4ee6a4SAndroid Build Coastguard Worker     rm.allocate(25, 5).unwrap();
128*bb4ee6a4SAndroid Build Coastguard Worker     assert_eq!(
129*bb4ee6a4SAndroid Build Coastguard Worker         rm.to_vec(),
130*bb4ee6a4SAndroid Build Coastguard Worker         vec![
131*bb4ee6a4SAndroid Build Coastguard Worker             &Region { start: 0, len: 5 },
132*bb4ee6a4SAndroid Build Coastguard Worker             &Region { start: 10, len: 10 },
133*bb4ee6a4SAndroid Build Coastguard Worker             &Region { start: 25, len: 5 }
134*bb4ee6a4SAndroid Build Coastguard Worker         ]
135*bb4ee6a4SAndroid Build Coastguard Worker     );
136*bb4ee6a4SAndroid Build Coastguard Worker 
137*bb4ee6a4SAndroid Build Coastguard Worker     rm.allocate(5, 5).unwrap(); // will be merged to the existing two regions
138*bb4ee6a4SAndroid Build Coastguard Worker     assert_eq!(
139*bb4ee6a4SAndroid Build Coastguard Worker         rm.to_vec(),
140*bb4ee6a4SAndroid Build Coastguard Worker         vec![&Region { start: 0, len: 20 }, &Region { start: 25, len: 5 }]
141*bb4ee6a4SAndroid Build Coastguard Worker     );
142*bb4ee6a4SAndroid Build Coastguard Worker     rm.allocate(20, 5).unwrap();
143*bb4ee6a4SAndroid Build Coastguard Worker     assert_eq!(rm.to_vec(), vec![&Region { start: 0, len: 30 },]);
144*bb4ee6a4SAndroid Build Coastguard Worker }
145*bb4ee6a4SAndroid Build Coastguard Worker 
146*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, Clone, Copy, AsBytes)]
147*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
148*bb4ee6a4SAndroid Build Coastguard Worker /// Represents a ID of a disk block.
149*bb4ee6a4SAndroid Build Coastguard Worker pub struct BlockId(u32);
150*bb4ee6a4SAndroid Build Coastguard Worker 
151*bb4ee6a4SAndroid Build Coastguard Worker impl From<u32> for BlockId {
from(value: u32) -> Self152*bb4ee6a4SAndroid Build Coastguard Worker     fn from(value: u32) -> Self {
153*bb4ee6a4SAndroid Build Coastguard Worker         BlockId(value)
154*bb4ee6a4SAndroid Build Coastguard Worker     }
155*bb4ee6a4SAndroid Build Coastguard Worker }
156*bb4ee6a4SAndroid Build Coastguard Worker 
157*bb4ee6a4SAndroid Build Coastguard Worker impl From<BlockId> for u32 {
from(value: BlockId) -> Self158*bb4ee6a4SAndroid Build Coastguard Worker     fn from(value: BlockId) -> Self {
159*bb4ee6a4SAndroid Build Coastguard Worker         value.0
160*bb4ee6a4SAndroid Build Coastguard Worker     }
161*bb4ee6a4SAndroid Build Coastguard Worker }
162*bb4ee6a4SAndroid Build Coastguard Worker 
163*bb4ee6a4SAndroid Build Coastguard Worker impl BlockId {
as_bytes(&self) -> &[u8]164*bb4ee6a4SAndroid Build Coastguard Worker     pub fn as_bytes(&self) -> &[u8] {
165*bb4ee6a4SAndroid Build Coastguard Worker         self.0.as_bytes()
166*bb4ee6a4SAndroid Build Coastguard Worker     }
167*bb4ee6a4SAndroid Build Coastguard Worker }
168*bb4ee6a4SAndroid Build Coastguard Worker 
169*bb4ee6a4SAndroid Build Coastguard Worker /// Information on how to mmap a host file to ext2 blocks.
170*bb4ee6a4SAndroid Build Coastguard Worker pub struct FileMappingInfo {
171*bb4ee6a4SAndroid Build Coastguard Worker     /// Offset in the memory that a file is mapped to.
172*bb4ee6a4SAndroid Build Coastguard Worker     pub mem_offset: usize,
173*bb4ee6a4SAndroid Build Coastguard Worker     /// The file to be mmap'd.
174*bb4ee6a4SAndroid Build Coastguard Worker     pub file: File,
175*bb4ee6a4SAndroid Build Coastguard Worker     /// The length of the mapping.
176*bb4ee6a4SAndroid Build Coastguard Worker     pub length: usize,
177*bb4ee6a4SAndroid Build Coastguard Worker     /// Offset in the file to start the mapping.
178*bb4ee6a4SAndroid Build Coastguard Worker     pub file_offset: usize,
179*bb4ee6a4SAndroid Build Coastguard Worker }
180*bb4ee6a4SAndroid Build Coastguard Worker 
181*bb4ee6a4SAndroid Build Coastguard Worker /// Memory arena backed by `base::MemoryMapping`.
182*bb4ee6a4SAndroid Build Coastguard Worker ///
183*bb4ee6a4SAndroid Build Coastguard Worker /// This struct takes a mutable referencet to the memory mapping so this arena won't arena the
184*bb4ee6a4SAndroid Build Coastguard Worker /// region.
185*bb4ee6a4SAndroid Build Coastguard Worker pub struct Arena<'a> {
186*bb4ee6a4SAndroid Build Coastguard Worker     mem: &'a mut MemoryMapping,
187*bb4ee6a4SAndroid Build Coastguard Worker     block_size: usize,
188*bb4ee6a4SAndroid Build Coastguard Worker     /// A set of regions that are not overlapping each other.
189*bb4ee6a4SAndroid Build Coastguard Worker     /// Use `RefCell` for interior mutability because the mutablity of `RegionManager` should be
190*bb4ee6a4SAndroid Build Coastguard Worker     /// independent from the mutability of the memory mapping.
191*bb4ee6a4SAndroid Build Coastguard Worker     regions: RefCell<RegionManager>,
192*bb4ee6a4SAndroid Build Coastguard Worker 
193*bb4ee6a4SAndroid Build Coastguard Worker     mappings: RefCell<Vec<FileMappingInfo>>,
194*bb4ee6a4SAndroid Build Coastguard Worker }
195*bb4ee6a4SAndroid Build Coastguard Worker 
196*bb4ee6a4SAndroid Build Coastguard Worker impl<'a> Arena<'a> {
197*bb4ee6a4SAndroid Build Coastguard Worker     /// Create a new arena backed by `len` bytes of `base::MemoryMapping`.
new(block_size: usize, mem: &'a mut MemoryMapping) -> Result<Self>198*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(block_size: usize, mem: &'a mut MemoryMapping) -> Result<Self> {
199*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Self {
200*bb4ee6a4SAndroid Build Coastguard Worker             mem,
201*bb4ee6a4SAndroid Build Coastguard Worker             block_size,
202*bb4ee6a4SAndroid Build Coastguard Worker             regions: Default::default(),
203*bb4ee6a4SAndroid Build Coastguard Worker             mappings: Default::default(),
204*bb4ee6a4SAndroid Build Coastguard Worker         })
205*bb4ee6a4SAndroid Build Coastguard Worker     }
206*bb4ee6a4SAndroid Build Coastguard Worker 
207*bb4ee6a4SAndroid Build Coastguard Worker     /// A helper function to mark a region as reserved.
reserve(&self, mem_offset: usize, len: usize) -> Result<()>208*bb4ee6a4SAndroid Build Coastguard Worker     fn reserve(&self, mem_offset: usize, len: usize) -> Result<()> {
209*bb4ee6a4SAndroid Build Coastguard Worker         let mem_end = mem_offset.checked_add(len).context("mem_end overflow")?;
210*bb4ee6a4SAndroid Build Coastguard Worker 
211*bb4ee6a4SAndroid Build Coastguard Worker         if mem_end > self.mem.size() {
212*bb4ee6a4SAndroid Build Coastguard Worker             bail!(
213*bb4ee6a4SAndroid Build Coastguard Worker                 "out of memory region: {mem_offset} + {len} > {}",
214*bb4ee6a4SAndroid Build Coastguard Worker                 self.mem.size()
215*bb4ee6a4SAndroid Build Coastguard Worker             );
216*bb4ee6a4SAndroid Build Coastguard Worker         }
217*bb4ee6a4SAndroid Build Coastguard Worker 
218*bb4ee6a4SAndroid Build Coastguard Worker         self.regions.borrow_mut().allocate(mem_offset, len)?;
219*bb4ee6a4SAndroid Build Coastguard Worker 
220*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
221*bb4ee6a4SAndroid Build Coastguard Worker     }
222*bb4ee6a4SAndroid Build Coastguard Worker 
223*bb4ee6a4SAndroid Build Coastguard Worker     /// Reserves a region for mmap and stores the mmap information.
224*bb4ee6a4SAndroid Build Coastguard Worker     /// Note that `Arena` will not call  mmap(). Instead, the owner of `Arena` instance must call
225*bb4ee6a4SAndroid Build Coastguard Worker     /// `into_mapping_info()` to retrieve the mapping information and call mmap later instead.
reserve_for_mmap( &self, mem_offset: usize, length: usize, file: File, file_offset: usize, ) -> Result<()>226*bb4ee6a4SAndroid Build Coastguard Worker     pub fn reserve_for_mmap(
227*bb4ee6a4SAndroid Build Coastguard Worker         &self,
228*bb4ee6a4SAndroid Build Coastguard Worker         mem_offset: usize,
229*bb4ee6a4SAndroid Build Coastguard Worker         length: usize,
230*bb4ee6a4SAndroid Build Coastguard Worker         file: File,
231*bb4ee6a4SAndroid Build Coastguard Worker         file_offset: usize,
232*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<()> {
233*bb4ee6a4SAndroid Build Coastguard Worker         self.reserve(mem_offset, length)?;
234*bb4ee6a4SAndroid Build Coastguard Worker         self.mappings.borrow_mut().push(FileMappingInfo {
235*bb4ee6a4SAndroid Build Coastguard Worker             mem_offset,
236*bb4ee6a4SAndroid Build Coastguard Worker             length,
237*bb4ee6a4SAndroid Build Coastguard Worker             file: file.try_clone()?,
238*bb4ee6a4SAndroid Build Coastguard Worker             file_offset,
239*bb4ee6a4SAndroid Build Coastguard Worker         });
240*bb4ee6a4SAndroid Build Coastguard Worker 
241*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
242*bb4ee6a4SAndroid Build Coastguard Worker     }
243*bb4ee6a4SAndroid Build Coastguard Worker 
244*bb4ee6a4SAndroid Build Coastguard Worker     /// Allocate a new slice on an anonymous memory.
245*bb4ee6a4SAndroid Build Coastguard Worker     /// `Arena` structs guarantees that this area is not overlapping with other regions.
allocate_slice( &self, block: BlockId, block_offset: usize, len: usize, ) -> Result<&'a mut [u8]>246*bb4ee6a4SAndroid Build Coastguard Worker     pub fn allocate_slice(
247*bb4ee6a4SAndroid Build Coastguard Worker         &self,
248*bb4ee6a4SAndroid Build Coastguard Worker         block: BlockId,
249*bb4ee6a4SAndroid Build Coastguard Worker         block_offset: usize,
250*bb4ee6a4SAndroid Build Coastguard Worker         len: usize,
251*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<&'a mut [u8]> {
252*bb4ee6a4SAndroid Build Coastguard Worker         let offset = u32::from(block) as usize * self.block_size + block_offset;
253*bb4ee6a4SAndroid Build Coastguard Worker         self.reserve(offset, len)?;
254*bb4ee6a4SAndroid Build Coastguard Worker 
255*bb4ee6a4SAndroid Build Coastguard Worker         let new_addr = (self.mem.as_ptr() as usize)
256*bb4ee6a4SAndroid Build Coastguard Worker             .checked_add(offset)
257*bb4ee6a4SAndroid Build Coastguard Worker             .context("address overflow")?;
258*bb4ee6a4SAndroid Build Coastguard Worker 
259*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: the memory region [new_addr, new_addr+len) is guaranteed to be valid.
260*bb4ee6a4SAndroid Build Coastguard Worker         let slice = unsafe { std::slice::from_raw_parts_mut(new_addr as *mut u8, len) };
261*bb4ee6a4SAndroid Build Coastguard Worker         Ok(slice)
262*bb4ee6a4SAndroid Build Coastguard Worker     }
263*bb4ee6a4SAndroid Build Coastguard Worker 
264*bb4ee6a4SAndroid Build Coastguard Worker     /// Allocate a new region for a value with type `T`.
allocate<T: AsBytes + FromBytes + Sized>( &self, block: BlockId, block_offset: usize, ) -> Result<&'a mut T>265*bb4ee6a4SAndroid Build Coastguard Worker     pub fn allocate<T: AsBytes + FromBytes + Sized>(
266*bb4ee6a4SAndroid Build Coastguard Worker         &self,
267*bb4ee6a4SAndroid Build Coastguard Worker         block: BlockId,
268*bb4ee6a4SAndroid Build Coastguard Worker         block_offset: usize,
269*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<&'a mut T> {
270*bb4ee6a4SAndroid Build Coastguard Worker         let slice = self.allocate_slice(block, block_offset, std::mem::size_of::<T>())?;
271*bb4ee6a4SAndroid Build Coastguard Worker         T::mut_from(slice).ok_or_else(|| anyhow!("failed to interpret"))
272*bb4ee6a4SAndroid Build Coastguard Worker     }
273*bb4ee6a4SAndroid Build Coastguard Worker 
write_to_mem<T: AsBytes + FromBytes + Sized>( &self, block_id: BlockId, block_offset: usize, value: &T, ) -> Result<()>274*bb4ee6a4SAndroid Build Coastguard Worker     pub fn write_to_mem<T: AsBytes + FromBytes + Sized>(
275*bb4ee6a4SAndroid Build Coastguard Worker         &self,
276*bb4ee6a4SAndroid Build Coastguard Worker         block_id: BlockId,
277*bb4ee6a4SAndroid Build Coastguard Worker         block_offset: usize,
278*bb4ee6a4SAndroid Build Coastguard Worker         value: &T,
279*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<()> {
280*bb4ee6a4SAndroid Build Coastguard Worker         let slice = self.allocate_slice(block_id, block_offset, std::mem::size_of::<T>())?;
281*bb4ee6a4SAndroid Build Coastguard Worker         slice.copy_from_slice(value.as_bytes());
282*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
283*bb4ee6a4SAndroid Build Coastguard Worker     }
284*bb4ee6a4SAndroid Build Coastguard Worker 
285*bb4ee6a4SAndroid Build Coastguard Worker     /// Consumes `Arena` and retrieve mmap information.
into_mapping_info(self) -> Vec<FileMappingInfo>286*bb4ee6a4SAndroid Build Coastguard Worker     pub fn into_mapping_info(self) -> Vec<FileMappingInfo> {
287*bb4ee6a4SAndroid Build Coastguard Worker         self.mappings.take()
288*bb4ee6a4SAndroid Build Coastguard Worker     }
289*bb4ee6a4SAndroid Build Coastguard Worker }
290