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