1use crate::io::{Result, SeekFrom, prelude::*};
2use core::fmt;
3
4use arceos_api::fs as api;
5
6pub type FileType = api::AxFileType;
9
10pub type Permissions = api::AxFilePerm;
12
13pub struct File {
15 inner: api::AxFileHandle,
16}
17
18pub struct Metadata(api::AxFileAttr);
20
21#[derive(Clone, Debug)]
23pub struct OpenOptions(api::AxOpenOptions);
24
25impl OpenOptions {
26 pub const fn new() -> Self {
28 OpenOptions(api::AxOpenOptions::new())
29 }
30
31 pub fn read(&mut self, read: bool) -> &mut Self {
33 self.0.read(read);
34 self
35 }
36
37 pub fn write(&mut self, write: bool) -> &mut Self {
39 self.0.write(write);
40 self
41 }
42
43 pub fn append(&mut self, append: bool) -> &mut Self {
45 self.0.append(append);
46 self
47 }
48
49 pub fn truncate(&mut self, truncate: bool) -> &mut Self {
51 self.0.truncate(truncate);
52 self
53 }
54
55 pub fn create(&mut self, create: bool) -> &mut Self {
57 self.0.create(create);
58 self
59 }
60
61 pub fn create_new(&mut self, create_new: bool) -> &mut Self {
63 self.0.create_new(create_new);
64 self
65 }
66
67 pub fn open(&self, path: &str) -> Result<File> {
69 api::ax_open_file(path, &self.0).map(|inner| File { inner })
70 }
71}
72
73impl Metadata {
74 pub const fn file_type(&self) -> FileType {
76 self.0.file_type()
77 }
78
79 pub const fn is_dir(&self) -> bool {
83 self.0.is_dir()
84 }
85
86 pub const fn is_file(&self) -> bool {
90 self.0.is_file()
91 }
92
93 #[allow(clippy::len_without_is_empty)]
95 pub const fn len(&self) -> u64 {
96 self.0.size()
97 }
98
99 pub const fn permissions(&self) -> Permissions {
101 self.0.perm()
102 }
103
104 pub const fn size(&self) -> u64 {
106 self.0.size()
107 }
108
109 pub const fn blocks(&self) -> u64 {
111 self.0.blocks()
112 }
113}
114
115impl fmt::Debug for Metadata {
116 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117 f.debug_struct("Metadata")
118 .field("file_type", &self.file_type())
119 .field("is_dir", &self.is_dir())
120 .field("is_file", &self.is_file())
121 .field("permissions", &self.permissions())
122 .finish_non_exhaustive()
123 }
124}
125
126impl File {
127 pub fn open(path: &str) -> Result<Self> {
129 OpenOptions::new().read(true).open(path)
130 }
131
132 pub fn create(path: &str) -> Result<Self> {
134 OpenOptions::new()
135 .write(true)
136 .create(true)
137 .truncate(true)
138 .open(path)
139 }
140
141 pub fn create_new(path: &str) -> Result<Self> {
143 OpenOptions::new()
144 .read(true)
145 .write(true)
146 .create_new(true)
147 .open(path)
148 }
149
150 pub fn options() -> OpenOptions {
152 OpenOptions::new()
153 }
154
155 pub fn set_len(&self, size: u64) -> Result<()> {
158 api::ax_truncate_file(&self.inner, size)
159 }
160
161 pub fn metadata(&self) -> Result<Metadata> {
163 api::ax_file_attr(&self.inner).map(Metadata)
164 }
165}
166
167impl Read for File {
168 fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
169 api::ax_read_file(&mut self.inner, buf)
170 }
171}
172
173impl Write for File {
174 fn write(&mut self, buf: &[u8]) -> Result<usize> {
175 api::ax_write_file(&mut self.inner, buf)
176 }
177
178 fn flush(&mut self) -> Result<()> {
179 api::ax_flush_file(&self.inner)
180 }
181}
182
183impl Seek for File {
184 fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
185 api::ax_seek_file(&mut self.inner, pos)
186 }
187}