channels_io/buf/
buf.rs

1use core::cmp::min;
2use core::pin::Pin;
3use core::task::{Context, Poll};
4
5#[cfg(feature = "alloc")]
6use alloc::vec::Vec;
7
8use crate::buf::{Chain, Take};
9use crate::error::{IoError, ReadError};
10use crate::util::copy_slice;
11use crate::{AsyncRead, Read};
12
13/// An immutable buffer that contains an internal cursor.
14pub trait Buf {
15	/// Get the number of bytes remaining in the buffer.
16	fn remaining(&self) -> usize;
17
18	/// Get the remaining bytes of the buffer as a slice.
19	///
20	/// This method is allowed to return slices smaller than what [`Buf::remaining()`]
21	/// describes. This allows non contiguous representation of the buffer in memory.
22	fn chunk(&self) -> &[u8];
23
24	/// Advance the internal cursor of the buffer by `n` bytes.
25	///
26	/// # Panics
27	///
28	/// If `n` is a value that would cause the cursor to go out of bounds.
29	fn advance(&mut self, n: usize);
30
31	/// Check whether the buffer has any data left in it.
32	fn has_remaining(&self) -> bool {
33		self.remaining() != 0
34	}
35
36	/// Copy data from the buffer into `slice` advancing the buffer accordingly.
37	fn copy_to_slice(&mut self, slice: &mut [u8]) -> usize {
38		let n = min(self.remaining(), slice.len());
39		let mut i = 0;
40
41		while i < n {
42			let x = copy_slice(self.chunk(), &mut slice[i..]);
43			self.advance(x);
44			i += x;
45		}
46
47		n
48	}
49
50	#[cfg(feature = "alloc")]
51	/// Copy the buffer into `vec`.
52	fn copy_to_vec(mut self, vec: &mut Vec<u8>)
53	where
54		Self: Sized,
55	{
56		vec.reserve(self.remaining());
57
58		while self.has_remaining() {
59			let c = self.chunk();
60			vec.extend_from_slice(c);
61			self.advance(c.len());
62		}
63	}
64
65	/// Create a "by reference" adapter that takes the current instance of [`Buf`]
66	/// by mutable reference.
67	fn by_ref(&mut self) -> &mut Self
68	where
69		Self: Sized,
70	{
71		self
72	}
73
74	/// Create an adapter that implements the [`Read`] and [`AsyncRead`] traits
75	/// on the current instance of [`Buf`].
76	fn reader(self) -> Reader<Self>
77	where
78		Self: Sized,
79	{
80		Reader::new(self)
81	}
82
83	/// Create a [`Chain`] adapter that chains this buffer with `other`.
84	///
85	/// The returned [`Buf`] will behave as a non-contiguous buffer made up of
86	/// the contents of `self` and `other`.
87	fn chain<T: Buf>(self, other: T) -> Chain<Self, T>
88	where
89		Self: Sized,
90	{
91		Chain::new(self, other)
92	}
93
94	/// Create a [`Take`] adapter that takes `n` bytes from this buffer.
95	///
96	/// The returned [`Buf`] will contain only the first `n` bytes of this buffer.
97	fn take(self, n: usize) -> Take<Self>
98	where
99		Self: Sized,
100	{
101		Take::new(self, n)
102	}
103}
104
105macro_rules! forward_impl_buf {
106	($to:ty) => {
107		fn remaining(&self) -> usize {
108			<$to>::remaining(self)
109		}
110
111		fn chunk(&self) -> &[u8] {
112			<$to>::chunk(self)
113		}
114
115		fn advance(&mut self, n: usize) {
116			<$to>::advance(self, n);
117		}
118
119		fn has_remaining(&self) -> bool {
120			<$to>::has_remaining(self)
121		}
122
123		fn copy_to_slice(&mut self, slice: &mut [u8]) -> usize {
124			<$to>::copy_to_slice(self, slice)
125		}
126	};
127}
128
129impl<T: Buf + ?Sized> Buf for &mut T {
130	forward_impl_buf!(T);
131}
132
133#[cfg(feature = "alloc")]
134impl<T: Buf + ?Sized> Buf for alloc::boxed::Box<T> {
135	forward_impl_buf!(T);
136}
137
138impl Buf for &[u8] {
139	fn remaining(&self) -> usize {
140		self.len()
141	}
142
143	fn chunk(&self) -> &[u8] {
144		self
145	}
146
147	fn advance(&mut self, n: usize) {
148		*self = &self[n..];
149	}
150}
151
152/// The error returned by IO read calls to a [`Reader`].
153#[derive(Debug, Clone, Copy)]
154pub enum ReaderError {
155	/// The reader has reached EOF.
156	Eof,
157}
158
159impl IoError for ReaderError {
160	fn should_retry(&self) -> bool {
161		false
162	}
163}
164
165impl ReadError for ReaderError {
166	fn eof() -> Self {
167		Self::Eof
168	}
169}
170
171/// An adapter for [`Buf`] that implements both [`Read`] and [`AsyncRead`].
172#[derive(Debug, Clone, Copy)]
173pub struct Reader<B> {
174	buf: B,
175}
176
177impl<B> Reader<B> {
178	fn new(buf: B) -> Self {
179		Self { buf }
180	}
181}
182
183impl<B: Buf> Read for Reader<B> {
184	type Error = ReaderError;
185
186	fn read_slice(
187		&mut self,
188		buf: &mut [u8],
189	) -> Result<usize, Self::Error> {
190		if buf.is_empty() {
191			return Ok(0);
192		}
193
194		let n = self.buf.copy_to_slice(buf);
195		if n == 0 {
196			return Err(ReaderError::Eof);
197		}
198
199		Ok(n)
200	}
201}
202
203impl<B: Buf + Unpin> AsyncRead for Reader<B> {
204	type Error = ReaderError;
205
206	fn poll_read_slice(
207		mut self: Pin<&mut Self>,
208		_: &mut Context,
209		buf: &mut [u8],
210	) -> Poll<Result<usize, Self::Error>> {
211		Poll::Ready(self.read_slice(buf))
212	}
213}