sdb_debugger 0.2.2

Book: Building a Debugger. Rust port of C++ debugger sdb
Documentation
use super::sdb_error::SdbError;
use nix::fcntl::OFlag;
use nix::unistd::pipe2;
use nix::unistd::read;
use nix::unistd::write;
use std::os::fd::{AsRawFd, OwnedFd};

#[derive(Debug)]
pub struct Pipe {
    fds: [Option<OwnedFd>; 2],
}

impl Pipe {
    pub const READ_FD: usize = 0;
    pub const WRITE_FD: usize = 1;

    pub fn new(close_on_exec: bool) -> Result<Self, SdbError> {
        match pipe2(if close_on_exec {
            OFlag::O_CLOEXEC
        } else {
            OFlag::from_bits(0).unwrap()
        }) {
            Ok((read, write)) => Ok(Pipe {
                fds: [Some(read), Some(write)],
            }),
            Err(errno) => SdbError::errno("Pipe creation failed", errno),
        }
    }

    pub fn get_read_fd(&self) -> i32 {
        self.fds[Pipe::READ_FD].as_ref().unwrap().as_raw_fd()
    }

    pub fn get_write_fd(&self) -> i32 {
        self.fds[Pipe::WRITE_FD].as_ref().unwrap().as_raw_fd()
    }

    pub fn release_read(&mut self) -> OwnedFd {
        let fd = self.fds[Pipe::READ_FD].take();
        return fd.unwrap();
    }
    pub fn release_write(&mut self) -> OwnedFd {
        let fd = self.fds[Pipe::WRITE_FD].take();
        return fd.unwrap();
    }

    pub fn close_read(&mut self) {
        self.release_read();
    }
    pub fn close_write(&mut self) {
        self.release_write();
    }

    pub fn read(&self) -> Result<Vec<u8>, SdbError> {
        let buf: &mut [u8] = &mut [0u8; 1024];
        match read(self.fds[Pipe::READ_FD].as_ref().unwrap().as_raw_fd(), buf) {
            Ok(size) => Ok(buf[..size].to_vec()),
            Err(errno) => SdbError::errno("Could not read from pipe", errno),
        }
    }

    pub fn write(&self, bytes: &[u8]) -> Result<(), SdbError> {
        match write(self.fds[Pipe::WRITE_FD].as_ref().unwrap(), bytes) {
            Ok(_) => Ok(()),
            Err(errno) => SdbError::errno("Could not read from pipe", errno),
        }
    }
}