1 // Copyright (c) 2023 Huawei Device Co., Ltd. 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 use std::fs::File; 15 use std::io; 16 use std::io::{IoSlice, Write}; 17 use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd}; 18 19 use ylong_io::sys::SourceFd; 20 use ylong_io::{Interest, Selector, Source, Token}; 21 22 #[derive(Debug)] 23 pub(crate) struct Pipe { 24 pub(crate) fd: File, 25 } 26 27 impl<T: IntoRawFd> From<T> for Pipe { from(value: T) -> Self28 fn from(value: T) -> Self { 29 let fd = unsafe { File::from_raw_fd(value.into_raw_fd()) }; 30 Self { fd } 31 } 32 } 33 34 impl<'a> io::Read for &'a Pipe { read(&mut self, buf: &mut [u8]) -> io::Result<usize>35 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { 36 (&self.fd).read(buf) 37 } 38 } 39 40 impl<'a> Write for &'a Pipe { write(&mut self, buf: &[u8]) -> io::Result<usize>41 fn write(&mut self, buf: &[u8]) -> io::Result<usize> { 42 (&self.fd).write(buf) 43 } 44 write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize>45 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { 46 (&self.fd).write_vectored(bufs) 47 } 48 flush(&mut self) -> io::Result<()>49 fn flush(&mut self) -> io::Result<()> { 50 (&self.fd).flush() 51 } 52 } 53 54 impl AsRawFd for Pipe { as_raw_fd(&self) -> RawFd55 fn as_raw_fd(&self) -> RawFd { 56 self.fd.as_raw_fd() 57 } 58 } 59 60 impl AsFd for Pipe { as_fd(&self) -> BorrowedFd<'_>61 fn as_fd(&self) -> BorrowedFd<'_> { 62 unsafe { BorrowedFd::borrow_raw(self.fd.as_raw_fd()) } 63 } 64 } 65 66 impl Source for Pipe { register( &mut self, selector: &Selector, token: Token, interests: Interest, ) -> io::Result<()>67 fn register( 68 &mut self, 69 selector: &Selector, 70 token: Token, 71 interests: Interest, 72 ) -> io::Result<()> { 73 SourceFd(&self.as_raw_fd()).register(selector, token, interests) 74 } 75 deregister(&mut self, selector: &Selector) -> io::Result<()>76 fn deregister(&mut self, selector: &Selector) -> io::Result<()> { 77 SourceFd(&self.as_raw_fd()).deregister(selector) 78 } 79 get_fd(&self) -> ylong_io::Fd80 fn get_fd(&self) -> ylong_io::Fd { 81 self.fd.as_raw_fd() 82 } 83 } 84 85 #[cfg(test)] 86 mod test { 87 use std::io::{Read, Seek, Write}; 88 use std::os::fd::{AsFd, AsRawFd}; 89 90 use ylong_io::Source; 91 92 use super::Pipe; 93 94 /// UT test cases for Pipe. 95 /// 96 /// # Brief 97 /// 1. Create a `Pipe` from `std::fs::File`. 98 /// 2. Write something into `Pipe`. 99 /// 3. Read from `Pipe` and check result. 100 #[test] ut_process_pipe_test()101 fn ut_process_pipe_test() { 102 let arg = "Hello, world!"; 103 let file_path = "pipe_file0.txt"; 104 105 let mut file = std::fs::File::options() 106 .read(true) 107 .write(true) 108 .create(true) 109 .open(file_path) 110 .unwrap(); 111 let seek = file.stream_position().unwrap(); 112 let mut pipe = Pipe::from(file); 113 114 assert!(pipe.get_fd().as_raw_fd() >= 0); 115 assert!(pipe.as_fd().as_raw_fd() >= 0); 116 assert!(pipe.as_raw_fd() >= 0); 117 118 (&pipe).write_all(arg.as_bytes()).unwrap(); 119 (&pipe).flush().unwrap(); 120 121 pipe.fd.seek(std::io::SeekFrom::Start(seek)).unwrap(); 122 123 let mut buf = [0; 13]; 124 (&pipe).read_exact(&mut buf).unwrap(); 125 assert_eq!(buf, arg.as_bytes()); 126 127 std::fs::remove_file(file_path).unwrap(); 128 } 129 } 130