blob: 4d0aba9db6c15383ded433a03bce936bfd7b3aba [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use {
crate::device::{
buffer::{Buffer, BufferRef, MutableBufferRef},
buffer_allocator::{BufferAllocator, MemBufferSource},
Device,
},
anyhow::{ensure, Error},
async_trait::async_trait,
std::sync::{
atomic::{AtomicBool, Ordering},
Mutex,
},
};
pub struct FakeDevice {
allocator: BufferAllocator,
data: Mutex<Vec<u8>>,
closed: AtomicBool,
}
const TRANSFER_HEAP_SIZE: usize = 16 * 1024 * 1024;
impl FakeDevice {
pub fn new(block_count: u64, block_size: u32) -> Self {
let allocator = BufferAllocator::new(
block_size as usize,
Box::new(MemBufferSource::new(TRANSFER_HEAP_SIZE)),
);
Self {
allocator,
data: Mutex::new(vec![0 as u8; block_count as usize * block_size as usize]),
closed: AtomicBool::new(false),
}
}
}
#[async_trait]
impl Device for FakeDevice {
fn allocate_buffer(&self, size: usize) -> Buffer<'_> {
assert!(!self.closed.load(Ordering::Relaxed));
self.allocator.allocate_buffer(size)
}
fn block_size(&self) -> u32 {
self.allocator.block_size() as u32
}
fn block_count(&self) -> u64 {
self.data.lock().unwrap().len() as u64 / self.block_size() as u64
}
async fn read(&self, offset: u64, mut buffer: MutableBufferRef<'_>) -> Result<(), Error> {
ensure!(!self.closed.load(Ordering::Relaxed));
let offset = offset as usize;
assert_eq!(offset % self.allocator.block_size(), 0);
let data = self.data.lock().unwrap();
let size = buffer.len();
assert!(offset + size <= data.len());
buffer.as_mut_slice().copy_from_slice(&data[offset..offset + size]);
Ok(())
}
async fn write(&self, offset: u64, buffer: BufferRef<'_>) -> Result<(), Error> {
ensure!(!self.closed.load(Ordering::Relaxed));
let offset = offset as usize;
assert_eq!(offset % self.allocator.block_size(), 0);
let mut data = self.data.lock().unwrap();
assert!(offset + buffer.len() <= data.len());
data[offset..offset + buffer.len()].copy_from_slice(buffer.as_slice());
Ok(())
}
async fn close(&self) -> Result<(), Error> {
self.closed.store(true, Ordering::Relaxed);
Ok(())
}
}