use core::ops::{BitOr, Not, BitAnd};
use core::fmt::{Debug, Formatter};
use crate::kty::{
c_int,
O_APPEND, O_NONBLOCK, O_DIRECT, O_NOATIME, O_ASYNC, O_SYNC, O_DSYNC, O_PATH, O_RDWR,
O_RDONLY, O_WRONLY,
};
#[derive(PartialEq, Eq)]
pub struct DescriptionFlags(pub c_int);
impl BitOr for DescriptionFlags {
type Output = DescriptionFlags;
fn bitor(self, other: DescriptionFlags) -> DescriptionFlags {
DescriptionFlags(self.0 | other.0)
}
}
impl BitAnd for DescriptionFlags {
type Output = DescriptionFlags;
fn bitand(self, other: DescriptionFlags) -> DescriptionFlags {
DescriptionFlags(self.0 & other.0)
}
}
impl Not for DescriptionFlags {
type Output = DescriptionFlags;
fn not(self) -> DescriptionFlags {
DescriptionFlags(!self.0)
}
}
pub const FD_NONE: DescriptionFlags = DescriptionFlags(0);
pub const FD_ACCESS_MASK: DescriptionFlags = DescriptionFlags(3);
macro_rules! create_flags {
($($(#[$meta:meta])* flag $name:ident = $val:expr;)*) => {
$($(#[$meta])* pub const $name: DescriptionFlags = DescriptionFlags($val);)*
impl Debug for DescriptionFlags {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let rm = match self.0 & 3 {
O_RDONLY => "FD_READ_ONLY",
O_WRONLY => "FD_WRITE_ONLY",
_ => "FD_READ_WRITE",
};
core::write!(f, "{}", rm)?;
let flags = self.0 & !3;
$(
if flags & $val != 0 {
core::write!(f, "|")?;
core::write!(f, stringify!($name))?;
}
)*
Ok(())
}
}
}
}
create_flags! {
#[doc = "The file description is in read-only mode.\n"]
#[doc = "= See also"]
#[doc = "* link:man:open(2) and O_RDONLY therein"]
flag FD_READ_ONLY = O_RDONLY;
#[doc = "The file description is in write-only mode.\n"]
#[doc = "= See also"]
#[doc = "* link:man:open(2) and O_WRONLY therein"]
flag FD_WRITE_ONLY = O_WRONLY;
#[doc = "The file description is open for reading and writing.\n"]
#[doc = "= See also"]
#[doc = "* link:man:open(2) and O_RDWR therein"]
flag FD_READ_WRITE = O_RDWR;
#[doc = "Bypass kernel buffers and write directly to the disk.\n"]
#[doc = "= See also"]
#[doc = "* link:man:open(2) and O_DIRECT therein"]
flag FD_BYPASS_BUFFER = O_DIRECT;
#[doc = "Don't update the access time of the file.\n"]
#[doc = "= See also"]
#[doc = "* link:man:open(2) and O_NOATIME therein"]
flag FD_NO_ACCESS_TIME_UPDATE = O_NOATIME;
#[doc = "Perform all writes to the file at the end of the file.\n"]
#[doc = "= See also"]
#[doc = "* link:man:open(2) and O_APPEND therein"]
flag FD_APPEND = O_APPEND;
#[doc = "Send a signal to the process when the file becomes ready for reading or \
writing.\n"]
#[doc = "= See also"]
#[doc = "* link:man:open(2) and O_ASYNC therein"]
flag FD_SIGNAL_IO = O_ASYNC;
#[doc = "Ensure that all data has been passed to the hardware after a write.\n"]
#[doc = "= See also"]
#[doc = "* link:man:open(2) and O_SYNC therein"]
flag FD_SYNC = O_SYNC;
#[doc = "Ensure that enough data has been passed to the hardware after a write so \
that the data can be read back.\n"]
#[doc = "= See also"]
#[doc = "* link:man:open(2) and O_DSYNC therein"]
flag FD_DATA_SYNC = O_DSYNC;
#[doc = "Return an error instead of blocking.\n"]
#[doc = "= See also"]
#[doc = "* link:man:open(2) and O_NONBLOCK therein"]
flag FD_DONT_BLOCK = O_NONBLOCK;
#[doc = "The file description identifies a path in a filesystem.\n"]
#[doc = "= See also"]
#[doc = "* link:man:open(2) and O_PATH therein"]
flag FD_PATH = O_PATH;
}
impl DescriptionFlags {
pub fn set(&mut self, flag: DescriptionFlags) {
self.0 |= flag.0
}
pub fn unset(&mut self, flag: DescriptionFlags) {
self.0 &= !flag.0
}
pub fn is_set(&self, flag: DescriptionFlags) -> bool {
self.0 & flag.0 != 0
}
}