/// Linux syscall number
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Syscall(i64);

impl Syscall {
    /// Create a syscall value from a raw Linux syscall number
    pub const fn from_number(number: i64) -> Self {
        Self(number)
    }

    /// Raw Linux syscall number
    pub const fn number(self) -> i64 {
        self.0
    }
}

impl From<Syscall> for i64 {
    fn from(syscall: Syscall) -> Self {
        syscall.number()
    }
}

#[cfg(target_os = "linux")]
#[allow(non_upper_case_globals)]
impl Syscall {
    /// sigaltstack
    pub const sigaltstack: Self = Self(libc::SYS_sigaltstack);
    /// getrandom
    pub const getrandom: Self = Self(libc::SYS_getrandom);
    /// clone
    pub const clone: Self = Self(libc::SYS_clone);
    /// clone3
    pub const clone3: Self = Self(libc::SYS_clone3);
    /// futex
    pub const futex: Self = Self(libc::SYS_futex);
    /// sched_yield
    pub const sched_yield: Self = Self(libc::SYS_sched_yield);
    /// set_robust_list
    pub const set_robust_list: Self = Self(libc::SYS_set_robust_list);
    /// sched_getaffinity
    pub const sched_getaffinity: Self = Self(libc::SYS_sched_getaffinity);
    /// madvise
    pub const madvise: Self = Self(libc::SYS_madvise);
    /// mprotect
    pub const mprotect: Self = Self(libc::SYS_mprotect);
    /// fcntl
    pub const fcntl: Self = Self(libc::SYS_fcntl);
    /// prctl
    pub const prctl: Self = Self(libc::SYS_prctl);
    /// exit
    pub const exit: Self = Self(libc::SYS_exit);
    /// exit_group
    pub const exit_group: Self = Self(libc::SYS_exit_group);
    /// kill
    pub const kill: Self = Self(libc::SYS_kill);
    /// tgkill
    pub const tgkill: Self = Self(libc::SYS_tgkill);
    /// getpid
    pub const getpid: Self = Self(libc::SYS_getpid);
    /// gettid
    pub const gettid: Self = Self(libc::SYS_gettid);
    /// rt_sigprocmask
    pub const rt_sigprocmask: Self = Self(libc::SYS_rt_sigprocmask);
    /// read
    pub const read: Self = Self(libc::SYS_read);
    /// write
    pub const write: Self = Self(libc::SYS_write);
    /// close
    pub const close: Self = Self(libc::SYS_close);
    /// brk
    pub const brk: Self = Self(libc::SYS_brk);
    /// mmap
    pub const mmap: Self = Self(libc::SYS_mmap);
    /// munmap
    pub const munmap: Self = Self(libc::SYS_munmap);
    /// mremap
    pub const mremap: Self = Self(libc::SYS_mremap);
    /// fstat
    pub const fstat: Self = Self(libc::SYS_fstat);
    /// statx
    pub const statx: Self = Self(libc::SYS_statx);
    /// newfstatat
    pub const newfstatat: Self = Self(libc::SYS_newfstatat);
    /// lseek
    pub const lseek: Self = Self(libc::SYS_lseek);
    /// rseq
    pub const rseq: Self = Self(libc::SYS_rseq);
    /// epoll_pwait
    pub const epoll_pwait: Self = Self(libc::SYS_epoll_pwait);
    /// epoll_ctl
    pub const epoll_ctl: Self = Self(libc::SYS_epoll_ctl);
    /// epoll_create1
    pub const epoll_create1: Self = Self(libc::SYS_epoll_create1);
    /// socket
    pub const socket: Self = Self(libc::SYS_socket);
    /// connect
    pub const connect: Self = Self(libc::SYS_connect);
    /// shutdown
    pub const shutdown: Self = Self(libc::SYS_shutdown);
    /// accept
    pub const accept: Self = Self(libc::SYS_accept);
    /// accept4
    pub const accept4: Self = Self(libc::SYS_accept4);
    /// sendto
    pub const sendto: Self = Self(libc::SYS_sendto);
    /// sendmsg
    pub const sendmsg: Self = Self(libc::SYS_sendmsg);
    /// sendmmsg
    pub const sendmmsg: Self = Self(libc::SYS_sendmmsg);
    /// recvfrom
    pub const recvfrom: Self = Self(libc::SYS_recvfrom);
    /// recvmsg
    pub const recvmsg: Self = Self(libc::SYS_recvmsg);
    /// recvmmsg
    pub const recvmmsg: Self = Self(libc::SYS_recvmmsg);
    /// socketpair
    pub const socketpair: Self = Self(libc::SYS_socketpair);
    /// setsockopt
    pub const setsockopt: Self = Self(libc::SYS_setsockopt);
    /// getsockopt
    pub const getsockopt: Self = Self(libc::SYS_getsockopt);
    /// getsockname
    pub const getsockname: Self = Self(libc::SYS_getsockname);
    /// bind
    pub const bind: Self = Self(libc::SYS_bind);
    /// listen
    pub const listen: Self = Self(libc::SYS_listen);
    /// ioctl
    pub const ioctl: Self = Self(libc::SYS_ioctl);
    /// inotify_init1
    pub const inotify_init1: Self = Self(libc::SYS_inotify_init1);
    /// inotify_add_watch
    pub const inotify_add_watch: Self = Self(libc::SYS_inotify_add_watch);
    /// inotify_rm_watch
    pub const inotify_rm_watch: Self = Self(libc::SYS_inotify_rm_watch);
    /// getdents64
    pub const getdents64: Self = Self(libc::SYS_getdents64);
    /// readv
    pub const readv: Self = Self(libc::SYS_readv);
    /// writev
    pub const writev: Self = Self(libc::SYS_writev);
    /// preadv
    pub const preadv: Self = Self(libc::SYS_preadv);
    /// pwritev
    pub const pwritev: Self = Self(libc::SYS_pwritev);
    /// uname
    pub const uname: Self = Self(libc::SYS_uname);
    /// seccomp
    pub const seccomp: Self = Self(libc::SYS_seccomp);
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[allow(non_upper_case_globals)]
impl Syscall {
    /// stat
    pub const stat: Self = Self(libc::SYS_stat);
    /// lstat
    pub const lstat: Self = Self(libc::SYS_lstat);
    /// epoll_wait
    pub const epoll_wait: Self = Self(libc::SYS_epoll_wait);
    /// epoll_create
    pub const epoll_create: Self = Self(libc::SYS_epoll_create);
    /// inotify_init
    pub const inotify_init: Self = Self(libc::SYS_inotify_init);
    /// readlink
    pub const readlink: Self = Self(libc::SYS_readlink);
}
