nstd_sys/fs/file.rs
1//! A handle to an opened file.
2use crate::{
3 alloc::CBox,
4 core::{
5 result::NSTDResult,
6 slice::{NSTDSlice, NSTDSliceMut},
7 str::NSTDStr,
8 },
9 io::{NSTDIOError, NSTDIOResult},
10 string::NSTDString,
11 vec::NSTDVec,
12 NSTDUInt8,
13};
14use nstdapi::nstdapi;
15use std::fs::File;
16#[cfg(unix)]
17use std::os::unix::io::AsRawFd;
18
19/// Creates the file upon opening if it does not already exist.
20///
21/// Either of the `NSTD_FILE_WRITE` or `NSTD_FILE_APPEND` options must also be toggled for the file
22/// to be created.
23pub const NSTD_FILE_CREATE: NSTDUInt8 = 1;
24
25/// Open a file in read mode.
26pub const NSTD_FILE_READ: NSTDUInt8 = 1 << 1;
27
28/// Open a file in write mode.
29pub const NSTD_FILE_WRITE: NSTDUInt8 = 1 << 2;
30
31/// Open a file in writing mode without overwriting saved data.
32pub const NSTD_FILE_APPEND: NSTDUInt8 = 1 << 3;
33
34/// Open a file in truncate mode, this will set the file's length to 0 upon opening.
35pub const NSTD_FILE_TRUNC: NSTDUInt8 = 1 << 4;
36
37/// A handle to an opened file.
38#[nstdapi]
39pub struct NSTDFile {
40 /// The inner [File].
41 f: CBox<File>,
42}
43
44/// A result type yielding an `NSTDFile` on success.
45pub type NSTDFileResult = NSTDResult<NSTDFile, NSTDIOError>;
46
47/// Opens file on the filesystem and returns a handle to it.
48///
49/// # Parameters:
50///
51/// - `const NSTDStr *name` - The name of the file to create.
52///
53/// - `NSTDUInt8 mask` - A bit mask for toggling the file's different open options.
54///
55/// # Returns
56///
57/// `NSTDFileResult file` - A handle to the opened file, or the IO error on failure.
58///
59/// # Safety
60///
61/// This operation can cause undefined behavior if `name`'s data is invalid.
62#[nstdapi]
63pub unsafe fn nstd_fs_file_open(name: &NSTDStr, mask: NSTDUInt8) -> NSTDFileResult {
64 // Attempt to create/open the file in write mode.
65 match File::options()
66 .create((mask & NSTD_FILE_CREATE) != 0)
67 .read((mask & NSTD_FILE_READ) != 0)
68 .write((mask & NSTD_FILE_WRITE) != 0)
69 .append((mask & NSTD_FILE_APPEND) != 0)
70 .truncate((mask & NSTD_FILE_TRUNC) != 0)
71 .open(name.as_str())
72 {
73 Ok(f) => CBox::new(f).map_or(
74 NSTDResult::Err(NSTDIOError::NSTD_IO_ERROR_OUT_OF_MEMORY),
75 |f| NSTDResult::Ok(NSTDFile { f }),
76 ),
77 Err(err) => NSTDResult::Err(NSTDIOError::from_err(err.kind())),
78 }
79}
80
81/// Writes some data to a file & returns how many bytes were written.
82///
83/// # Parameters:
84///
85/// - `NSTDFile *file` - A handle to an open file.
86///
87/// - `const NSTDSlice *bytes` - The data to write to the file.
88///
89/// # Returns
90///
91/// `NSTDIOResult written` - The number of bytes written to `handle` on success, or the I/O
92/// operation error code on failure.
93///
94/// # Safety
95///
96/// This function's caller must guarantee validity of `bytes`.
97#[inline]
98#[nstdapi]
99pub unsafe fn nstd_fs_file_write(file: &mut NSTDFile, bytes: &NSTDSlice) -> NSTDIOResult {
100 #[cfg(not(unix))]
101 return crate::io::stdio::write(&mut *file.f, bytes);
102 #[cfg(unix)]
103 return crate::os::unix::io::stdio::write(file.f.as_raw_fd(), bytes).into();
104}
105
106/// Writes a whole buffer to a file.
107///
108/// # Parameters:
109///
110/// - `NSTDFile *file` - A handle to an open file.
111///
112/// - `const NSTDSlice *bytes` - The data to write to the file.
113///
114/// # Returns
115///
116/// `NSTDIOError errc` - The I/O operation error code.
117///
118/// # Safety
119///
120/// This function's caller must guarantee validity of `bytes`.
121#[inline]
122#[nstdapi]
123pub unsafe fn nstd_fs_file_write_all(file: &mut NSTDFile, bytes: &NSTDSlice) -> NSTDIOError {
124 #[cfg(not(unix))]
125 return crate::io::stdio::write_all(&mut *file.f, bytes);
126 #[cfg(unix)]
127 return crate::os::unix::io::stdio::write_all(file.f.as_raw_fd(), bytes).into();
128}
129
130/// Flushes a file stream.
131///
132/// # Parameters:
133///
134/// - `NSTDFile *file` - The file stream.
135///
136/// # Returns
137///
138/// `NSTDIOError errc` - The I/O operation error code.
139#[inline]
140#[nstdapi]
141pub fn nstd_fs_file_flush(file: &mut NSTDFile) -> NSTDIOError {
142 crate::io::stdio::flush(&mut *file.f)
143}
144
145/// Reads some data from an open file into a buffer.
146///
147/// # Parameters:
148///
149/// - `NSTDFile *file` - A handle to the opened file.
150///
151/// - `NSTDSliceMut *buffer` - The buffer to start filling with data from the file.
152///
153/// # Returns
154///
155/// `NSTDIOResult read` - The number of bytes read from `handle` on success, or the I/O operation
156/// error code on failure.
157///
158/// # Safety
159///
160/// `buffer`'s data must be valid for writes.
161#[inline]
162#[nstdapi]
163pub unsafe fn nstd_fs_file_read(file: &mut NSTDFile, buffer: &mut NSTDSliceMut) -> NSTDIOResult {
164 #[cfg(not(unix))]
165 return crate::io::stdio::read(&mut *file.f, buffer);
166 #[cfg(unix)]
167 return crate::os::unix::io::stdio::read(file.f.as_raw_fd(), buffer).into();
168}
169
170/// Continuously reads data from `file` into a buffer until EOF is reached.
171///
172/// # Note
173///
174/// If extending the buffer fails, an error code of `NSTD_IO_ERROR_OUT_OF_MEMORY` will be returned.
175/// This does not mean there were no bytes read from `file` in this case.
176///
177/// # Parameters:
178///
179/// - `NSTDFile *file` - A handle to the file.
180///
181/// - `NSTDVec *buffer` - The buffer to be extended with data from the file.
182///
183/// # Returns
184///
185/// `NSTDIOResult read` - The number of bytes read from `handle` on success, or the I/O operation
186/// error code on failure.
187#[inline]
188#[nstdapi]
189pub fn nstd_fs_file_read_all(file: &mut NSTDFile, buffer: &mut NSTDVec<'_>) -> NSTDIOResult {
190 #[cfg(not(unix))]
191 return crate::io::stdio::read_all(&mut *file.f, buffer);
192 #[cfg(unix)]
193 // SAFETY: `file` owns the file descriptor.
194 return unsafe { crate::os::unix::io::stdio::read_all(file.f.as_raw_fd(), buffer).into() };
195}
196
197/// Continuously reads UTF-8 data from `file` into a string buffer until EOF is reached.
198///
199/// # Note
200///
201/// If extending the buffer fails, an error code of `NSTD_IO_ERROR_OUT_OF_MEMORY` will be returned.
202/// This does not mean there were no bytes read from `file` in this case.
203///
204/// # Parameters:
205///
206/// - `NSTDFile *file` - A handle to the file.
207///
208/// - `NSTDString *buffer` - The buffer to be extended with data from the file.
209///
210/// # Returns
211///
212/// `NSTDIOResult read` - The number of bytes read from `handle` on success, or the I/O operation
213/// error code on failure.
214#[inline]
215#[nstdapi]
216pub fn nstd_fs_file_read_to_string(
217 file: &mut NSTDFile,
218 buffer: &mut NSTDString<'_>,
219) -> NSTDIOResult {
220 #[cfg(not(unix))]
221 return crate::io::stdio::read_to_string(&mut *file.f, buffer);
222 #[cfg(unix)]
223 // SAFETY: `file` owns the file descriptor.
224 return unsafe {
225 crate::os::unix::io::stdio::read_to_string(file.f.as_raw_fd(), buffer).into()
226 };
227}
228
229/// Reads enough data from `file` to fill the entirety of `buffer`.
230///
231/// # Note
232///
233/// This function will return an error code of `NSTD_IO_ERROR_INVALID_INPUT` if the buffer's
234/// element size is not 1.
235///
236/// # Parameters:
237///
238/// - `NSTDFile *file` - A handle to the file.
239///
240/// - `NSTDSliceMut *buffer` - The buffer to fill with data from the file.
241///
242/// # Returns
243///
244/// `NSTDIOError errc` - The I/O operation error code.
245///
246/// # Safety
247///
248/// `buffer` must be valid for writes.
249#[inline]
250#[nstdapi]
251pub unsafe fn nstd_fs_file_read_exact(
252 file: &mut NSTDFile,
253 buffer: &mut NSTDSliceMut,
254) -> NSTDIOError {
255 #[cfg(not(unix))]
256 return crate::io::stdio::read_exact(&mut *file.f, buffer);
257 #[cfg(unix)]
258 return crate::os::unix::io::stdio::read_exact(file.f.as_raw_fd(), buffer).into();
259}
260
261/// Closes a file handle.
262///
263/// # Parameters:
264///
265/// - `NSTDFile file` - The file handle to close.
266#[inline]
267#[nstdapi]
268#[allow(
269 unused_variables,
270 clippy::missing_const_for_fn,
271 clippy::needless_pass_by_value
272)]
273pub fn nstd_fs_file_close(file: NSTDFile) {}