1use std::{
7 any::Any,
8 io::{self, Cursor, Write},
9 sync::{Arc, RwLock},
10};
11
12use wasi_common::{
13 file::{FdFlags, FileType},
14 Error, ErrorExt, WasiFile,
15};
16
17pub struct ReadableWritePipe<W: Write> {
20 buf: Arc<RwLock<W>>,
21}
22
23#[wiggle::async_trait]
24impl<W: Write + Any + Send + Sync> WasiFile for ReadableWritePipe<W> {
25 fn as_any(&self) -> &dyn std::any::Any {
26 self
27 }
28 async fn get_filetype(&mut self) -> Result<FileType, Error> {
29 Ok(FileType::Pipe)
30 }
31 async fn get_fdflags(&mut self) -> Result<FdFlags, Error> {
32 Ok(FdFlags::APPEND)
33 }
34 async fn write_vectored<'a>(&mut self, bufs: &[std::io::IoSlice<'a>]) -> Result<u64, Error> {
35 let n = self.borrow().write_vectored(bufs)?;
36 Ok(n.try_into()?)
37 }
38 async fn writable(&self) -> Result<(), Error> {
39 Ok(())
40 }
41 async fn write_vectored_at<'a>(
42 &mut self,
43 _bufs: &[io::IoSlice<'a>],
44 _offset: u64,
45 ) -> Result<u64, Error> {
46 Err(Error::seek_pipe())
47 }
48 async fn seek(&mut self, _pos: std::io::SeekFrom) -> Result<u64, Error> {
49 Err(Error::seek_pipe())
50 }
51 fn isatty(&mut self) -> bool {
52 false
53 }
54}
55
56impl<W: Write> ReadableWritePipe<W> {
57 pub fn borrow(&self) -> std::sync::RwLockWriteGuard<W> {
58 RwLock::write(&self.buf).unwrap()
59 }
60 pub fn get_read_lock(&self) -> std::sync::RwLockReadGuard<W> {
61 self.buf.read().unwrap()
62 }
63 pub fn new(inner: W) -> Self {
64 Self {
65 buf: Arc::new(RwLock::new(inner)),
66 }
67 }
68}
69
70impl ReadableWritePipe<Cursor<Vec<u8>>> {
71 pub fn new_vec_buf() -> Self {
72 Self::new(Cursor::new(vec![]))
73 }
74}
75
76impl<W: Write> Clone for ReadableWritePipe<W> {
77 fn clone(&self) -> Self {
78 Self {
79 buf: self.buf.clone(),
80 }
81 }
82}