veridian_kernel/fs/
blockdev.rs1use alloc::vec::Vec;
6
7use crate::error::KernelError;
8
9pub trait BlockDevice: Send + Sync {
11 fn name(&self) -> &str;
13
14 fn block_size(&self) -> usize;
16
17 fn block_count(&self) -> u64;
19
20 fn read_blocks(&self, start_block: u64, buffer: &mut [u8]) -> Result<(), KernelError>;
22
23 fn write_blocks(&mut self, start_block: u64, buffer: &[u8]) -> Result<(), KernelError>;
25
26 fn flush(&mut self) -> Result<(), KernelError> {
28 Ok(()) }
30}
31
32pub struct RamBlockDevice {
34 name: alloc::string::String,
35 block_size: usize,
36 data: Vec<u8>,
37}
38
39impl RamBlockDevice {
40 pub fn new(name: alloc::string::String, block_size: usize, block_count: u64) -> Self {
42 let size = block_size * block_count as usize;
43 Self {
44 name,
45 block_size,
46 data: alloc::vec![0u8; size],
47 }
48 }
49
50 pub fn size(&self) -> usize {
52 self.data.len()
53 }
54}
55
56impl BlockDevice for RamBlockDevice {
57 fn name(&self) -> &str {
58 &self.name
59 }
60
61 fn block_size(&self) -> usize {
62 self.block_size
63 }
64
65 fn block_count(&self) -> u64 {
66 (self.data.len() / self.block_size) as u64
67 }
68
69 fn read_blocks(&self, start_block: u64, buffer: &mut [u8]) -> Result<(), KernelError> {
70 let start_byte = start_block as usize * self.block_size;
71 let end_byte = start_byte + buffer.len();
72
73 if end_byte > self.data.len() {
74 return Err(KernelError::InvalidArgument {
75 name: "block_range",
76 value: "out_of_bounds",
77 });
78 }
79
80 buffer.copy_from_slice(&self.data[start_byte..end_byte]);
81 Ok(())
82 }
83
84 fn write_blocks(&mut self, start_block: u64, buffer: &[u8]) -> Result<(), KernelError> {
85 let start_byte = start_block as usize * self.block_size;
86 let end_byte = start_byte + buffer.len();
87
88 if end_byte > self.data.len() {
89 return Err(KernelError::InvalidArgument {
90 name: "block_range",
91 value: "out_of_bounds",
92 });
93 }
94
95 self.data[start_byte..end_byte].copy_from_slice(buffer);
96 Ok(())
97 }
98}
99
100#[cfg(test)]
101mod tests {
102 use alloc::string::String;
103
104 use super::*;
105
106 #[test]
107 fn test_ram_block_device() {
108 let mut dev = RamBlockDevice::new(String::from("test"), 512, 100);
109
110 assert_eq!(dev.block_size(), 512);
111 assert_eq!(dev.block_count(), 100);
112
113 let write_data = [0x42u8; 512];
115 dev.write_blocks(0, &write_data).unwrap();
116
117 let mut read_data = [0u8; 512];
119 dev.read_blocks(0, &mut read_data).unwrap();
120
121 assert_eq!(read_data, write_data);
122 }
123}