fusio_core/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3
4#[cfg(feature = "alloc")]
5extern crate alloc;
6
7pub mod buf;
8#[cfg(feature = "alloc")]
9#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
10mod dynamic;
11pub mod error;
12mod maybe;
13
14use core::future::Future;
15
16pub use buf::{IoBuf, IoBufMut};
17#[cfg(feature = "alloc")]
18#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
19pub use dynamic::{DynRead, DynWrite};
20use error::Error;
21pub use maybe::{MaybeOwned, MaybeSend, MaybeSendFuture, MaybeSync};
22
23/// The core trait for writing data.
24///
25/// It is similar to [`std::io::Write`], but it takes ownership of the buffer,
26/// because completion-based IO requires the buffer to be pinned and should be safe to
27/// cancellation.
28///
29/// [`Write`] represents "sequential write all and overwrite" semantics,
30/// which means each buffer will be written to the file sequentially and overwrite the previous
31/// file when closed.
32///
33/// Contents are not guaranteed to be written to the file until the [`Write::close`] method is
34/// called. [`Write::flush`] may be used to flush the data to the file in some
35/// implementations, but not all implementations will do so.
36///
37/// Whether the operation is successful or not, the buffer will be returned.
38/// Fusio promises that the returned buffer will be the same as the input buffer.
39///
40/// # Examples
41///
42/// ```no_run
43/// use fusio_core::{IoBuf, Write};
44///
45/// async fn write_data<W: Write>(
46///     mut writer: W,
47///     data: Vec<u8>,
48/// ) -> Result<(), fusio_core::error::Error> {
49///     let (result, _buf) = writer.write_all(data).await;
50///     result?;
51///     writer.flush().await?;
52///     writer.close().await?;
53///     Ok(())
54/// }
55/// ```
56///
57/// # Dyn Compatibility
58/// This trait is not dyn compatible.
59/// If you want to use [`Write`] trait in a dynamic way, you could use [`DynWrite`] trait.
60pub trait Write: MaybeSend {
61    fn write_all<B: IoBuf>(
62        &mut self,
63        buf: B,
64    ) -> impl Future<Output = (Result<(), Error>, B)> + MaybeSend;
65
66    fn flush(&mut self) -> impl Future<Output = Result<(), Error>> + MaybeSend;
67
68    fn close(&mut self) -> impl Future<Output = Result<(), Error>> + MaybeSend;
69}
70
71/// The core trait for reading data.
72///
73/// It is similar to [`std::io::Read`], but it takes ownership of the buffer,
74/// because completion-based IO requires the buffer to be pinned and should be safe to
75/// cancellation.
76///
77/// [`Read`] represents "random exactly read" semantics,
78/// which means the read operation will start at the specified position, and the buffer will be
79/// exactly filled with the data read.
80///
81/// The buffer will be returned with the result, whether the operation is successful or not.
82/// Fusio promises that the returned buffer will be the same as the input buffer.
83///
84/// If you want sequential reading, try `SeqRead` (not yet implemented).
85///
86/// # Examples
87///
88/// ```no_run
89/// use fusio_core::{IoBufMut, Read};
90///
91/// async fn read_at_position<R: Read>(
92///     mut reader: R,
93///     pos: u64,
94///     len: usize,
95/// ) -> Result<Vec<u8>, fusio_core::error::Error> {
96///     let mut buf = vec![0u8; len];
97///     let (result, buf) = reader.read_exact_at(buf, pos).await;
98///     result?;
99///     Ok(buf)
100/// }
101/// ```
102///
103/// # Dyn Compatibility
104/// This trait is not dyn compatible.
105/// If you want to use [`Read`] trait in a dynamic way, you could use [`DynRead`] trait.
106pub trait Read: MaybeSend + MaybeSync {
107    fn read_exact_at<B: IoBufMut>(
108        &mut self,
109        buf: B,
110        pos: u64,
111    ) -> impl Future<Output = (Result<(), Error>, B)> + MaybeSend;
112
113    #[cfg(feature = "alloc")]
114    #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
115    fn read_to_end_at(
116        &mut self,
117        buf: alloc::vec::Vec<u8>,
118        pos: u64,
119    ) -> impl Future<Output = (Result<(), Error>, alloc::vec::Vec<u8>)> + MaybeSend;
120
121    fn size(&self) -> impl Future<Output = Result<u64, Error>> + MaybeSend;
122}
123
124impl<R: Read> Read for &mut R {
125    fn read_exact_at<B: IoBufMut>(
126        &mut self,
127        buf: B,
128        pos: u64,
129    ) -> impl Future<Output = (Result<(), Error>, B)> + MaybeSend {
130        R::read_exact_at(self, buf, pos)
131    }
132
133    #[cfg(feature = "alloc")]
134    fn read_to_end_at(
135        &mut self,
136        buf: alloc::vec::Vec<u8>,
137        pos: u64,
138    ) -> impl Future<Output = (Result<(), Error>, alloc::vec::Vec<u8>)> + MaybeSend {
139        R::read_to_end_at(self, buf, pos)
140    }
141
142    fn size(&self) -> impl Future<Output = Result<u64, Error>> + MaybeSend {
143        R::size(self)
144    }
145}
146
147impl<W: Write> Write for &mut W {
148    fn write_all<B: IoBuf>(
149        &mut self,
150        buf: B,
151    ) -> impl Future<Output = (Result<(), Error>, B)> + MaybeSend {
152        W::write_all(self, buf)
153    }
154
155    fn flush(&mut self) -> impl Future<Output = Result<(), Error>> + MaybeSend {
156        W::flush(self)
157    }
158
159    fn close(&mut self) -> impl Future<Output = Result<(), Error>> + MaybeSend {
160        W::close(self)
161    }
162}
163
164#[cfg(feature = "std")]
165impl Read for &mut Vec<u8> {
166    async fn read_exact_at<B: IoBufMut>(&mut self, mut buf: B, pos: u64) -> (Result<(), Error>, B) {
167        let pos = pos as usize;
168        let len = buf.bytes_init();
169        let end = pos + len;
170        if end > self.len() {
171            return (
172                Err(std::io::Error::new(std::io::ErrorKind::UnexpectedEof, "").into()),
173                buf,
174            );
175        }
176        buf.as_slice_mut().copy_from_slice(&self[pos..end]);
177        (Ok(()), buf)
178    }
179
180    async fn read_to_end_at(&mut self, mut buf: Vec<u8>, pos: u64) -> (Result<(), Error>, Vec<u8>) {
181        let pos = pos as usize;
182        buf.extend_from_slice(&self[pos..]);
183        (Ok(()), buf)
184    }
185
186    async fn size(&self) -> Result<u64, Error> {
187        Ok(self.len() as u64)
188    }
189}
190
191#[cfg(feature = "std")]
192impl Write for std::io::Cursor<&mut Vec<u8>> {
193    async fn write_all<B: IoBuf>(&mut self, buf: B) -> (Result<(), Error>, B) {
194        (
195            std::io::Write::write_all(self, buf.as_slice()).map_err(Error::Io),
196            buf,
197        )
198    }
199
200    async fn flush(&mut self) -> Result<(), Error> {
201        Ok(())
202    }
203
204    async fn close(&mut self) -> Result<(), Error> {
205        Ok(())
206    }
207}