rpk_firmware/
ring_fs.rs

1#[derive(Debug, PartialEq)]
2#[cfg_attr(feature = "defmt", derive(defmt::Format))]
3pub enum RingFsError {
4    OutOfSpace,
5    FileOverrun,
6    MissingFileLength,
7    InUse,
8    UnrecoverableDisk,
9    FileTooLarge,
10    FileNotFound,
11    FileClosed,
12    NotAligned,
13    OutOfBounds,
14    Unknown,
15}
16
17#[derive(Debug, Clone, Copy)]
18pub enum FileState {
19    Closed,
20    Reader,
21    Writer,
22}
23
24#[derive(Debug, Clone, Copy)]
25pub struct FileDescriptor {
26    pub state: FileState,
27    /// Address of file contents on disk.
28    pub location: u32,
29    /// Length of file.
30    pub len: u32,
31    /// Offset from location to the current read/write location.
32    pub offset: u32,
33}
34
35pub trait RingFs<'f> {
36    fn create_file(&'f self) -> Result<RingFsWriter<'f>, RingFsError>;
37    fn file_reader_by_index(&'f self, index: u32) -> Result<RingFsReader<'f>, RingFsError>;
38    fn file_reader_by_location(&'f self, location: u32) -> Result<RingFsReader<'f>, RingFsError>;
39    fn close_file(&self, desc: &mut FileDescriptor);
40    fn write_file(&self, desc: &mut FileDescriptor, data: &[u8]) -> Result<(), RingFsError>;
41    fn read_file(&self, desc: &mut FileDescriptor, data: &mut [u8]) -> Result<u32, RingFsError>;
42}
43
44pub struct RingFsWriter<'f> {
45    fs: &'f dyn RingFs<'f>,
46    desc: FileDescriptor,
47}
48impl Drop for RingFsWriter<'_> {
49    fn drop(&mut self) {
50        self.close();
51    }
52}
53impl<'f> RingFsWriter<'f> {
54    pub fn new(fs: &'f dyn RingFs<'f>, desc: FileDescriptor) -> Self {
55        Self { fs, desc }
56    }
57
58    pub fn close(&mut self) {
59        self.fs.close_file(&mut self.desc);
60    }
61
62    pub fn is_closed(&self) -> bool {
63        self.desc.is_closed()
64    }
65
66    pub fn write(&mut self, data: &[u8]) -> Result<(), RingFsError> {
67        self.fs.write_file(&mut self.desc, data)
68    }
69
70    pub fn location(&self) -> u32 {
71        self.desc.location
72    }
73}
74
75pub struct RingFsReader<'f> {
76    fs: &'f dyn RingFs<'f>,
77    desc: FileDescriptor,
78}
79impl Drop for RingFsReader<'_> {
80    fn drop(&mut self) {
81        self.close();
82    }
83}
84impl<'f> RingFsReader<'f> {
85    pub fn new(fs: &'f dyn RingFs<'f>, desc: FileDescriptor) -> Self {
86        Self { fs, desc }
87    }
88
89    pub fn close(&mut self) {
90        self.fs.close_file(&mut self.desc);
91    }
92
93    pub fn is_closed(&self) -> bool {
94        self.desc.is_closed()
95    }
96
97    pub fn read(&mut self, data: &mut [u8]) -> Result<u32, RingFsError> {
98        self.fs.read_file(&mut self.desc, data)
99    }
100}
101
102impl FileDescriptor {
103    pub fn new_writer() -> Self {
104        Self {
105            state: FileState::Writer,
106            location: 0,
107            len: 0,
108            offset: 0,
109        }
110    }
111
112    pub fn new_reader(location: u32, len: u32) -> Self {
113        Self {
114            state: FileState::Reader,
115            location,
116            len,
117            offset: 0,
118        }
119    }
120
121    pub fn is_closed(&self) -> bool {
122        matches!(self.state, FileState::Closed)
123    }
124
125    pub(crate) fn close(&mut self) {
126        if !self.is_closed() {
127            self.state = FileState::Closed;
128        }
129    }
130}