1use alloc::vec::Vec;
2use axio::{Result, SeekFrom, default_read_to_end, prelude::*};
3use core::fmt;
4
5use crate::fops;
6
7pub type FileType = fops::FileType;
10
11pub type Permissions = fops::FilePerm;
13
14pub struct File {
16 inner: fops::File,
17}
18
19pub struct Metadata(pub(super) fops::FileAttr);
21
22#[derive(Default, Clone, Debug)]
24pub struct OpenOptions(fops::OpenOptions);
25
26impl OpenOptions {
27 pub const fn new() -> Self {
29 OpenOptions(fops::OpenOptions::new())
30 }
31
32 pub fn read(&mut self, read: bool) -> &mut Self {
34 self.0.read(read);
35 self
36 }
37
38 pub fn write(&mut self, write: bool) -> &mut Self {
40 self.0.write(write);
41 self
42 }
43
44 pub fn append(&mut self, append: bool) -> &mut Self {
46 self.0.append(append);
47 self
48 }
49
50 pub fn truncate(&mut self, truncate: bool) -> &mut Self {
52 self.0.truncate(truncate);
53 self
54 }
55
56 pub fn create(&mut self, create: bool) -> &mut Self {
58 self.0.create(create);
59 self
60 }
61
62 pub fn create_new(&mut self, create_new: bool) -> &mut Self {
64 self.0.create_new(create_new);
65 self
66 }
67
68 pub fn open(&self, path: &str) -> Result<File> {
70 fops::File::open(path, &self.0).map(|inner| File { inner })
71 }
72}
73
74impl Metadata {
75 pub const fn file_type(&self) -> FileType {
77 self.0.file_type()
78 }
79
80 pub const fn is_dir(&self) -> bool {
84 self.0.is_dir()
85 }
86
87 pub const fn is_file(&self) -> bool {
91 self.0.is_file()
92 }
93
94 #[allow(clippy::len_without_is_empty)]
96 pub const fn len(&self) -> u64 {
97 self.0.size()
98 }
99
100 pub const fn permissions(&self) -> Permissions {
102 self.0.perm()
103 }
104
105 pub const fn size(&self) -> u64 {
107 self.0.size()
108 }
109
110 pub const fn blocks(&self) -> u64 {
112 self.0.blocks()
113 }
114}
115
116impl fmt::Debug for Metadata {
117 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118 f.debug_struct("Metadata")
119 .field("file_type", &self.file_type())
120 .field("is_dir", &self.is_dir())
121 .field("is_file", &self.is_file())
122 .field("permissions", &self.permissions())
123 .finish_non_exhaustive()
124 }
125}
126
127impl File {
128 pub fn open(path: &str) -> Result<Self> {
130 OpenOptions::new().read(true).open(path)
131 }
132
133 pub fn create(path: &str) -> Result<Self> {
135 OpenOptions::new()
136 .write(true)
137 .create(true)
138 .truncate(true)
139 .open(path)
140 }
141
142 pub fn create_new(path: &str) -> Result<Self> {
144 OpenOptions::new()
145 .read(true)
146 .write(true)
147 .create_new(true)
148 .open(path)
149 }
150
151 pub fn options() -> OpenOptions {
153 OpenOptions::new()
154 }
155
156 pub fn set_len(&self, size: u64) -> Result<()> {
159 self.inner.truncate(size)
160 }
161
162 pub fn metadata(&self) -> Result<Metadata> {
164 self.inner.get_attr().map(Metadata)
165 }
166}
167
168impl Read for File {
169 fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
170 self.inner.read(buf)
171 }
172
173 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
174 default_read_to_end(
175 self,
176 buf,
177 self.metadata().ok().map(|metadata| metadata.size() as _),
178 )
179 }
180}
181
182impl Write for File {
183 fn write(&mut self, buf: &[u8]) -> Result<usize> {
184 self.inner.write(buf)
185 }
186
187 fn flush(&mut self) -> Result<()> {
188 self.inner.flush()
189 }
190}
191
192impl Seek for File {
193 fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
194 self.inner.seek(pos)
195 }
196}