use std::{io, path::Path};
use crate::{
api::{
io::Io,
resource::{FromResource, Resource},
},
fs::ops::OpenatFile,
};
#[derive(Debug, Clone)]
pub struct OpenOptions {
read: bool,
write: bool,
append: bool,
truncate: bool,
create: bool,
create_new: bool,
#[cfg(unix)]
mode: Option<u32>,
}
impl OpenOptions {
#[must_use]
pub const fn new() -> Self {
Self {
read: false,
write: false,
append: false,
truncate: false,
create: false,
create_new: false,
#[cfg(unix)]
mode: None,
}
}
#[must_use]
pub const fn read(mut self, read: bool) -> Self {
self.read = read;
self
}
#[must_use]
pub const fn write(mut self, write: bool) -> Self {
self.write = write;
self
}
#[must_use]
pub const fn append(mut self, append: bool) -> Self {
self.append = append;
self
}
#[must_use]
pub const fn truncate(mut self, truncate: bool) -> Self {
self.truncate = truncate;
self
}
#[must_use]
pub const fn create(mut self, create: bool) -> Self {
self.create = create;
self
}
#[must_use]
pub const fn create_new(mut self, create_new: bool) -> Self {
self.create_new = create_new;
self
}
#[cfg(unix)]
#[must_use]
pub const fn mode(mut self, mode: u32) -> Self {
self.mode = Some(mode);
self
}
pub fn open<P: AsRef<Path>>(&self, path: P) -> Io<OpenatFile> {
let flags = self.make_flags()?;
self.open_inner(flags, path.as_ref())
}
#[cfg(unix)]
fn make_flags(&self) -> io::Result<libc::c_int> {
let mut flags = 0;
match (self.read, self.write, self.append) {
(true, false, false) => flags |= libc::O_RDONLY,
(false, true, false) => flags |= libc::O_WRONLY,
(true, true, false) => flags |= libc::O_RDWR,
(false, false, true) => flags |= libc::O_WRONLY | libc::O_APPEND,
(true, false, true) => flags |= libc::O_RDWR | libc::O_APPEND,
(false, true, true) => flags |= libc::O_WRONLY | libc::O_APPEND,
(true, true, true) => flags |= libc::O_RDWR | libc::O_APPEND,
(false, false, false) => {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"at least one of read, write, or append must be set",
));
}
}
if self.create_new {
flags |= libc::O_CREAT | libc::O_EXCL;
} else if self.create {
flags |= libc::O_CREAT;
}
if self.truncate {
flags |= libc::O_TRUNC;
}
Ok(flags)
}
fn open_inner(&self, flags: libc::c_int, path: &Path) -> Io<OpenatFile> {
todo!();
}
}
pub struct File(Resource);
impl File {
pub fn open<P: AsRef<Path>>(path: P) -> io::Result<Self> {
OpenOptions::new().read(true).open(path.as_ref())
}
pub fn create<P: AsRef<Path>>(path: P) -> io::Result<Self> {
OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(path.as_ref())
}
pub fn create_new<P: AsRef<Path>>(path: P) -> io::Result<File> {
OpenOptions::new()
.read(true)
.write(true)
.create_new(true)
.open(path.as_ref())
}
}
impl FromResource for File {
fn from_resource(resource: Resource) -> Self {
File(resource)
}
}
impl Default for OpenOptions {
fn default() -> Self {
Self::new()
}
}