1use super::sdb_error::SdbError;
2use nix::fcntl::OFlag;
3use nix::unistd::pipe2;
4use nix::unistd::read;
5use nix::unistd::write;
6use std::os::fd::{AsRawFd, OwnedFd};
7
8#[derive(Debug)]
9pub struct Pipe {
10 fds: [Option<OwnedFd>; 2],
11}
12
13impl Pipe {
14 pub const READ_FD: usize = 0;
15 pub const WRITE_FD: usize = 1;
16
17 pub fn new(close_on_exec: bool) -> Result<Self, SdbError> {
18 match pipe2(if close_on_exec {
19 OFlag::O_CLOEXEC
20 } else {
21 OFlag::from_bits(0).unwrap()
22 }) {
23 Ok((read, write)) => Ok(Pipe {
24 fds: [Some(read), Some(write)],
25 }),
26 Err(errno) => SdbError::errno("Pipe creation failed", errno),
27 }
28 }
29
30 pub fn get_read_fd(&self) -> i32 {
31 self.fds[Pipe::READ_FD].as_ref().unwrap().as_raw_fd()
32 }
33
34 pub fn get_write_fd(&self) -> i32 {
35 self.fds[Pipe::WRITE_FD].as_ref().unwrap().as_raw_fd()
36 }
37
38 pub fn release_read(&mut self) -> OwnedFd {
39 let fd = self.fds[Pipe::READ_FD].take();
40 return fd.unwrap();
41 }
42 pub fn release_write(&mut self) -> OwnedFd {
43 let fd = self.fds[Pipe::WRITE_FD].take();
44 return fd.unwrap();
45 }
46
47 pub fn close_read(&mut self) {
48 self.release_read();
49 }
50 pub fn close_write(&mut self) {
51 self.release_write();
52 }
53
54 pub fn read(&self) -> Result<Vec<u8>, SdbError> {
55 let buf: &mut [u8] = &mut [0u8; 1024];
56 match read(self.fds[Pipe::READ_FD].as_ref().unwrap().as_raw_fd(), buf) {
57 Ok(size) => Ok(buf[..size].to_vec()),
58 Err(errno) => SdbError::errno("Could not read from pipe", errno),
59 }
60 }
61
62 pub fn write(&self, bytes: &[u8]) -> Result<(), SdbError> {
63 match write(self.fds[Pipe::WRITE_FD].as_ref().unwrap(), bytes) {
64 Ok(_) => Ok(()),
65 Err(errno) => SdbError::errno("Could not read from pipe", errno),
66 }
67 }
68}