libc_tools 0.1.3

a fork to std process
Documentation
use std::fmt::Display;

use libc::{__errno_location, c_int};

use crate::Close;

pub struct Dup {
    fd: libc::c_int,
}

impl Dup {
    pub fn dup(old_fd: libc::c_int) -> Result<libc::c_int, DupError> {
        unsafe {
            match libc::dup(old_fd) {
                -1 => Err(DupError::Errno(*__errno_location())),
                fd @ _ => Ok(fd),
            }
        }
    }
    pub fn dup2(old_fd: libc::c_int, new_fd: libc::c_int) -> Result<libc::c_int, DupError> {
        unsafe {
            match libc::dup2(old_fd, new_fd) {
                fd if fd == new_fd => Ok(fd),
                -1 => Err(DupError::Errno(*__errno_location())),
                _ => panic!("this should not reached!"),
            }
        }
    }
    pub fn transform(fd: libc::c_int) -> Dup {
        Dup { fd }
    }

    pub fn close_to(&self, fd: libc::c_int) -> Result<libc::c_int, DupError> {
        if self.fd != fd {
            let result = Dup::dup2(self.fd, fd);
            result
        } else {
            Ok(fd)
        }
    }

    pub fn dup2s<'a, 'b>(old_fds: &'a [c_int], new_fds: &'b [c_int]) -> Result<(), DupError> {
        if old_fds.len() != new_fds.len() {
            panic!("dup2s: old fd array length should equal to new fds array");
        }
        for i in 0..old_fds.len() {
            Self::transform(old_fds[i]).close_to(new_fds[i])?;
        }
        Ok(())
    }
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum DupError {
    Errno(libc::c_int),
}

impl Display for DupError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            &DupError::Errno(v) => f.write_str(std::format!("dup error, errno: {}", v).as_str()),
        }
    }
}