1use crate::alloc::Allocator;
2use crate::boxed::Box;
3use crate::io::{
4self, Cursor, ErrorKind, IoSlice, WriteThroughCursor, slice_write, slice_write_all,
5 slice_write_all_vectored, slice_write_vectored,
6};
7use crate::vec::Vec;
89/// Reserves the required space, and pads the vec with 0s if necessary.
10fn reserve_and_pad<A: Allocator>(
11 pos_mut: &mut u64,
12 vec: &mut Vec<u8, A>,
13 buf_len: usize,
14) -> io::Result<usize> {
15let pos: usize = (*pos_mut).try_into().map_err(|_| {
16::core::hint::must_use(::core::io::Error::from_static_message(const {
&::core::io::SimpleMessage {
kind: ErrorKind::InvalidInput,
message: "cursor position exceeds maximum possible vector length",
}
}))io::const_error!(
17 ErrorKind::InvalidInput,
18"cursor position exceeds maximum possible vector length",
19 )20 })?;
2122// For safety reasons, we don't want these numbers to overflow
23 // otherwise our allocation won't be enough
24let desired_cap = pos.saturating_add(buf_len);
25if desired_cap > vec.capacity() {
26// We want our vec's total capacity
27 // to have room for (pos+buf_len) bytes. Reserve allocates
28 // based on additional elements from the length, so we need to
29 // reserve the difference
30cfg_select! {
31 no_global_oom_handling => {
32 vec.try_reserve(desired_cap - vec.len())?;
33 }
34_ => {
35vec.reserve(desired_cap - vec.len());
36 }
37 }
38 }
39// Pad if pos is above the current len.
40if pos > vec.len() {
41let diff = pos - vec.len();
42// Unfortunately, `resize()` would suffice but the optimiser does not
43 // realise the `reserve` it does can be eliminated. So we do it manually
44 // to eliminate that extra branch
45let spare = vec.spare_capacity_mut();
46if true {
if !(spare.len() >= diff) {
::core::panicking::panic("assertion failed: spare.len() >= diff")
};
};debug_assert!(spare.len() >= diff);
47// Safety: we have allocated enough capacity for this.
48 // And we are only writing, not reading
49unsafe {
50spare.get_unchecked_mut(..diff).fill(core::mem::MaybeUninit::new(0));
51vec.set_len(pos);
52 }
53 }
5455Ok(pos)
56}
5758/// Writes the slice to the vec without allocating.
59///
60/// # Safety
61///
62/// `vec` must have `buf.len()` spare capacity.
63unsafe fn vec_write_all_unchecked<A>(pos: usize, vec: &mut Vec<u8, A>, buf: &[u8]) -> usize64where
65A: Allocator,
66{
67if true {
if !(vec.capacity() >= pos + buf.len()) {
::core::panicking::panic("assertion failed: vec.capacity() >= pos + buf.len()")
};
};debug_assert!(vec.capacity() >= pos + buf.len());
68unsafe { vec.as_mut_ptr().add(pos).copy_from(buf.as_ptr(), buf.len()) };
69pos + buf.len()
70}
7172/// Resizing `write_all` implementation for [`Cursor`].
73///
74/// Cursor is allowed to have a pre-allocated and initialised
75/// vector body, but with a position of 0. This means the [`Write`]
76/// will overwrite the contents of the vec.
77///
78/// This also allows for the vec body to be empty, but with a position of N.
79/// This means that [`Write`] will pad the vec with 0 initially,
80/// before writing anything from that point
81///
82/// [`Write`]: crate::io::Write
83fn vec_write_all<A>(pos_mut: &mut u64, vec: &mut Vec<u8, A>, buf: &[u8]) -> io::Result<usize>
84where
85A: Allocator,
86{
87let buf_len = buf.len();
88let mut pos = reserve_and_pad(pos_mut, vec, buf_len)?;
8990// Write the buf then progress the vec forward if necessary
91 // Safety: we have ensured that the capacity is available
92 // and that all bytes get written up to pos
93unsafe {
94pos = vec_write_all_unchecked(pos, vec, buf);
95if pos > vec.len() {
96vec.set_len(pos);
97 }
98 };
99100// Bump us forward
101*pos_mut += buf_lenas u64;
102Ok(buf_len)
103}
104105/// Resizing `write_all_vectored` implementation for [`Cursor`].
106///
107/// Cursor is allowed to have a pre-allocated and initialised
108/// vector body, but with a position of 0. This means the [`Write`]
109/// will overwrite the contents of the vec.
110///
111/// This also allows for the vec body to be empty, but with a position of N.
112/// This means that [`Write`] will pad the vec with 0 initially,
113/// before writing anything from that point
114///
115/// [`Write`]: crate::io::Write
116fn vec_write_all_vectored<A>(
117 pos_mut: &mut u64,
118 vec: &mut Vec<u8, A>,
119 bufs: &[IoSlice<'_>],
120) -> io::Result<usize>
121where
122A: Allocator,
123{
124// For safety reasons, we don't want this sum to overflow ever.
125 // If this saturates, the reserve should panic to avoid any unsound writing.
126let buf_len = bufs.iter().fold(0usize, |a, b| a.saturating_add(b.len()));
127let mut pos = reserve_and_pad(pos_mut, vec, buf_len)?;
128129// Write the buf then progress the vec forward if necessary
130 // Safety: we have ensured that the capacity is available
131 // and that all bytes get written up to the last pos
132unsafe {
133for buf in bufs {
134 pos = vec_write_all_unchecked(pos, vec, buf);
135 }
136if pos > vec.len() {
137vec.set_len(pos);
138 }
139 }
140141// Bump us forward
142*pos_mut += buf_lenas u64;
143Ok(buf_len)
144}
145146#[stable(feature = "cursor_mut_vec", since = "1.25.0")]
147impl<A> WriteThroughCursor for &mut Vec<u8, A>
148where
149A: Allocator,
150{
151fn write(this: &mut Cursor<Self>, buf: &[u8]) -> io::Result<usize> {
152let (pos, inner) = this.into_parts_mut();
153vec_write_all(pos, inner, buf)
154 }
155156fn write_vectored(this: &mut Cursor<Self>, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
157let (pos, inner) = this.into_parts_mut();
158vec_write_all_vectored(pos, inner, bufs)
159 }
160161#[inline]
162fn is_write_vectored(_this: &Cursor<Self>) -> bool {
163true
164}
165166fn write_all(this: &mut Cursor<Self>, buf: &[u8]) -> io::Result<()> {
167let (pos, inner) = this.into_parts_mut();
168 vec_write_all(pos, inner, buf)?;
169Ok(())
170 }
171172fn write_all_vectored(this: &mut Cursor<Self>, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
173let (pos, inner) = this.into_parts_mut();
174 vec_write_all_vectored(pos, inner, bufs)?;
175Ok(())
176 }
177178#[inline]
179fn flush(_this: &mut Cursor<Self>) -> io::Result<()> {
180Ok(())
181 }
182}
183184#[stable(feature = "rust1", since = "1.0.0")]
185impl<A> WriteThroughCursor for Vec<u8, A>
186where
187A: Allocator,
188{
189fn write(this: &mut Cursor<Self>, buf: &[u8]) -> io::Result<usize> {
190let (pos, inner) = this.into_parts_mut();
191vec_write_all(pos, inner, buf)
192 }
193194fn write_vectored(this: &mut Cursor<Self>, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
195let (pos, inner) = this.into_parts_mut();
196vec_write_all_vectored(pos, inner, bufs)
197 }
198199#[inline]
200fn is_write_vectored(_this: &Cursor<Self>) -> bool {
201true
202}
203204fn write_all(this: &mut Cursor<Self>, buf: &[u8]) -> io::Result<()> {
205let (pos, inner) = this.into_parts_mut();
206 vec_write_all(pos, inner, buf)?;
207Ok(())
208 }
209210fn write_all_vectored(this: &mut Cursor<Self>, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
211let (pos, inner) = this.into_parts_mut();
212 vec_write_all_vectored(pos, inner, bufs)?;
213Ok(())
214 }
215216#[inline]
217fn flush(_this: &mut Cursor<Self>) -> io::Result<()> {
218Ok(())
219 }
220}
221222#[stable(feature = "cursor_box_slice", since = "1.5.0")]
223impl<A> WriteThroughCursor for Box<[u8], A>
224where
225A: Allocator,
226{
227#[inline]
228fn write(this: &mut Cursor<Self>, buf: &[u8]) -> io::Result<usize> {
229let (pos, inner) = this.into_parts_mut();
230 slice_write(pos, inner, buf)
231 }
232233#[inline]
234fn write_vectored(this: &mut Cursor<Self>, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
235let (pos, inner) = this.into_parts_mut();
236 slice_write_vectored(pos, inner, bufs)
237 }
238239#[inline]
240fn is_write_vectored(_this: &Cursor<Self>) -> bool {
241true
242}
243244#[inline]
245fn write_all(this: &mut Cursor<Self>, buf: &[u8]) -> io::Result<()> {
246let (pos, inner) = this.into_parts_mut();
247 slice_write_all(pos, inner, buf)
248 }
249250#[inline]
251fn write_all_vectored(this: &mut Cursor<Self>, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
252let (pos, inner) = this.into_parts_mut();
253 slice_write_all_vectored(pos, inner, bufs)
254 }
255256#[inline]
257fn flush(_this: &mut Cursor<Self>) -> io::Result<()> {
258Ok(())
259 }
260}