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