Skip to main content

alloc/io/
cursor.rs

1use crate::alloc::Allocator;
2use crate::boxed::Box;
3use crate::io::{
4    self, Cursor, ErrorKind, IoSlice, WriteThroughCursor, slice_write, slice_write_all,
5    slice_write_all_vectored, slice_write_vectored,
6};
7use crate::vec::Vec;
8
9/// 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> {
15    let 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    })?;
21
22    // For safety reasons, we don't want these numbers to overflow
23    // otherwise our allocation won't be enough
24    let desired_cap = pos.saturating_add(buf_len);
25    if 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
30        cfg_select! {
31            no_global_oom_handling => {
32                vec.try_reserve(desired_cap - vec.len())?;
33            }
34            _ => {
35                vec.reserve(desired_cap - vec.len());
36            }
37        }
38    }
39    // Pad if pos is above the current len.
40    if pos > vec.len() {
41        let 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
45        let spare = vec.spare_capacity_mut();
46        if 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
49        unsafe {
50            spare.get_unchecked_mut(..diff).fill(core::mem::MaybeUninit::new(0));
51            vec.set_len(pos);
52        }
53    }
54
55    Ok(pos)
56}
57
58/// 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]) -> usize
64where
65    A: Allocator,
66{
67    if true {
    if !(vec.capacity() >= pos + buf.len()) {
        ::core::panicking::panic("assertion failed: vec.capacity() >= pos + buf.len()")
    };
};debug_assert!(vec.capacity() >= pos + buf.len());
68    unsafe { vec.as_mut_ptr().add(pos).copy_from(buf.as_ptr(), buf.len()) };
69    pos + buf.len()
70}
71
72/// 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
85    A: Allocator,
86{
87    let buf_len = buf.len();
88    let mut pos = reserve_and_pad(pos_mut, vec, buf_len)?;
89
90    // 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
93    unsafe {
94        pos = vec_write_all_unchecked(pos, vec, buf);
95        if pos > vec.len() {
96            vec.set_len(pos);
97        }
98    };
99
100    // Bump us forward
101    *pos_mut += buf_len as u64;
102    Ok(buf_len)
103}
104
105/// 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
122    A: 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.
126    let buf_len = bufs.iter().fold(0usize, |a, b| a.saturating_add(b.len()));
127    let mut pos = reserve_and_pad(pos_mut, vec, buf_len)?;
128
129    // 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
132    unsafe {
133        for buf in bufs {
134            pos = vec_write_all_unchecked(pos, vec, buf);
135        }
136        if pos > vec.len() {
137            vec.set_len(pos);
138        }
139    }
140
141    // Bump us forward
142    *pos_mut += buf_len as u64;
143    Ok(buf_len)
144}
145
146#[stable(feature = "cursor_mut_vec", since = "1.25.0")]
147impl<A> WriteThroughCursor for &mut Vec<u8, A>
148where
149    A: Allocator,
150{
151    fn write(this: &mut Cursor<Self>, buf: &[u8]) -> io::Result<usize> {
152        let (pos, inner) = this.into_parts_mut();
153        vec_write_all(pos, inner, buf)
154    }
155
156    fn write_vectored(this: &mut Cursor<Self>, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
157        let (pos, inner) = this.into_parts_mut();
158        vec_write_all_vectored(pos, inner, bufs)
159    }
160
161    #[inline]
162    fn is_write_vectored(_this: &Cursor<Self>) -> bool {
163        true
164    }
165
166    fn write_all(this: &mut Cursor<Self>, buf: &[u8]) -> io::Result<()> {
167        let (pos, inner) = this.into_parts_mut();
168        vec_write_all(pos, inner, buf)?;
169        Ok(())
170    }
171
172    fn write_all_vectored(this: &mut Cursor<Self>, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
173        let (pos, inner) = this.into_parts_mut();
174        vec_write_all_vectored(pos, inner, bufs)?;
175        Ok(())
176    }
177
178    #[inline]
179    fn flush(_this: &mut Cursor<Self>) -> io::Result<()> {
180        Ok(())
181    }
182}
183
184#[stable(feature = "rust1", since = "1.0.0")]
185impl<A> WriteThroughCursor for Vec<u8, A>
186where
187    A: Allocator,
188{
189    fn write(this: &mut Cursor<Self>, buf: &[u8]) -> io::Result<usize> {
190        let (pos, inner) = this.into_parts_mut();
191        vec_write_all(pos, inner, buf)
192    }
193
194    fn write_vectored(this: &mut Cursor<Self>, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
195        let (pos, inner) = this.into_parts_mut();
196        vec_write_all_vectored(pos, inner, bufs)
197    }
198
199    #[inline]
200    fn is_write_vectored(_this: &Cursor<Self>) -> bool {
201        true
202    }
203
204    fn write_all(this: &mut Cursor<Self>, buf: &[u8]) -> io::Result<()> {
205        let (pos, inner) = this.into_parts_mut();
206        vec_write_all(pos, inner, buf)?;
207        Ok(())
208    }
209
210    fn write_all_vectored(this: &mut Cursor<Self>, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
211        let (pos, inner) = this.into_parts_mut();
212        vec_write_all_vectored(pos, inner, bufs)?;
213        Ok(())
214    }
215
216    #[inline]
217    fn flush(_this: &mut Cursor<Self>) -> io::Result<()> {
218        Ok(())
219    }
220}
221
222#[stable(feature = "cursor_box_slice", since = "1.5.0")]
223impl<A> WriteThroughCursor for Box<[u8], A>
224where
225    A: Allocator,
226{
227    #[inline]
228    fn write(this: &mut Cursor<Self>, buf: &[u8]) -> io::Result<usize> {
229        let (pos, inner) = this.into_parts_mut();
230        slice_write(pos, inner, buf)
231    }
232
233    #[inline]
234    fn write_vectored(this: &mut Cursor<Self>, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
235        let (pos, inner) = this.into_parts_mut();
236        slice_write_vectored(pos, inner, bufs)
237    }
238
239    #[inline]
240    fn is_write_vectored(_this: &Cursor<Self>) -> bool {
241        true
242    }
243
244    #[inline]
245    fn write_all(this: &mut Cursor<Self>, buf: &[u8]) -> io::Result<()> {
246        let (pos, inner) = this.into_parts_mut();
247        slice_write_all(pos, inner, buf)
248    }
249
250    #[inline]
251    fn write_all_vectored(this: &mut Cursor<Self>, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
252        let (pos, inner) = this.into_parts_mut();
253        slice_write_all_vectored(pos, inner, bufs)
254    }
255
256    #[inline]
257    fn flush(_this: &mut Cursor<Self>) -> io::Result<()> {
258        Ok(())
259    }
260}