//! I/O-related definitions

pub mod options;

pub mod device;
mod file;
pub mod filesystem;
mod input;
mod terminal;

pub use crate::generated::{
    AccessMode, DirectoryEntry, FileAttr, FileMode, FileSync, FileType, GroupId, MountOptions,
    OpenOptions, PollControl, RawFd, RemoveFlags, TimerOptions, UnmountOptions, UserId,
};
pub use file::{FileMetadataUpdate, FileMetadataUpdateMode, FileTimesUpdate, SeekFrom};
pub use input::{KeyboardKey, KeyboardKeyCode, KeyboardKeyEvent};
pub use terminal::{
    TerminalControlCharacters, TerminalInputOptions, TerminalLineOptions, TerminalOptions,
    TerminalOutputOptions, TerminalSize,
};

/// Describes a rename/move operation
#[derive(Clone, Debug)]
pub struct Rename<'a> {
    /// Where to look the source path at
    pub source_at: Option<RawFd>,
    /// Source path
    pub source: &'a str,
    /// Where to look the destination path at
    pub destination_at: Option<RawFd>,
    /// Destination path
    pub destination: &'a str,
}

impl UserId {
    /// Returns the `root` user ID
    pub const fn root() -> Self {
        Self(0)
    }

    /// Returns `true` if the user ID represents a root user
    pub const fn is_root(&self) -> bool {
        self.0 == 0
    }
}

impl GroupId {
    /// Returns the `root` group ID
    pub const fn root() -> Self {
        Self(0)
    }

    /// Returns `true` if the group ID represents a root user
    pub const fn is_root(&self) -> bool {
        self.0 == 0
    }
}

impl FileMode {
    /// Constructs a file mode from a raw [u32]
    pub const fn new(value: u32) -> Self {
        Self(value)
    }

    /// Default mode for a regular file
    pub const fn default_file() -> Self {
        Self(0o666)
    }

    /// Default mode for a directory
    pub const fn default_dir() -> Self {
        Self(0o777)
    }
}

impl RawFd {
    /// Default stdin file descriptor
    pub const STDIN: Self = Self(0);
    /// Default stdout file descriptor
    pub const STDOUT: Self = Self(1);
    /// Default stderr file descriptor
    pub const STDERR: Self = Self(2);
}

impl OpenOptions {
    /// Empty set of open options
    pub const fn default() -> Self {
        Self(0)
    }
}

impl From<u32> for RawFd {
    fn from(value: u32) -> Self {
        Self(value)
    }
}

abi_serde::impl_newtype_serde!(RawFd);
