Skip to content

Commit 0364e05

Browse files
samlichkorken89
authored andcommitted
Vec: add set_len
1 parent 9e08514 commit 0364e05

File tree

1 file changed

+98
-1
lines changed

1 file changed

+98
-1
lines changed

src/vec.rs

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,103 @@ where
327327
self.resize(new_len, T::default())
328328
}
329329

330+
/// Forces the length of the vector to `new_len`.
331+
///
332+
/// This is a low-level operation that maintains none of the normal
333+
/// invariants of the type. Normally changing the length of a vector
334+
/// is done using one of the safe operations instead, such as
335+
/// [`truncate`], [`resize`], [`extend`], or [`clear`].
336+
///
337+
/// [`truncate`]: #method.truncate
338+
/// [`resize`]: #method.resize
339+
/// [`extend`]: https://doc.rust-lang.org/stable/core/iter/trait.Extend.html#tymethod.extend
340+
/// [`clear`]: #method.clear
341+
///
342+
/// # Safety
343+
///
344+
/// - `new_len` must be less than or equal to [`capacity()`].
345+
/// - The elements at `old_len..new_len` must be initialized.
346+
///
347+
/// [`capacity()`]: #method.capacity
348+
///
349+
/// # Examples
350+
///
351+
/// This method can be useful for situations in which the vector
352+
/// is serving as a buffer for other code, particularly over FFI:
353+
///
354+
/// ```no_run
355+
/// # #![allow(dead_code)]
356+
/// use heapless::Vec;
357+
/// use heapless::consts::*;
358+
///
359+
/// # // This is just a minimal skeleton for the doc example;
360+
/// # // don't use this as a starting point for a real library.
361+
/// # pub struct StreamWrapper { strm: *mut core::ffi::c_void }
362+
/// # const Z_OK: i32 = 0;
363+
/// # extern "C" {
364+
/// # fn deflateGetDictionary(
365+
/// # strm: *mut core::ffi::c_void,
366+
/// # dictionary: *mut u8,
367+
/// # dictLength: *mut usize,
368+
/// # ) -> i32;
369+
/// # }
370+
/// # impl StreamWrapper {
371+
/// pub fn get_dictionary(&self) -> Option<Vec<u8, U32768>> {
372+
/// // Per the FFI method's docs, "32768 bytes is always enough".
373+
/// let mut dict = Vec::new();
374+
/// let mut dict_length = 0;
375+
/// // SAFETY: When `deflateGetDictionary` returns `Z_OK`, it holds that:
376+
/// // 1. `dict_length` elements were initialized.
377+
/// // 2. `dict_length` <= the capacity (32_768)
378+
/// // which makes `set_len` safe to call.
379+
/// unsafe {
380+
/// // Make the FFI call...
381+
/// let r = deflateGetDictionary(self.strm, dict.as_mut_ptr(), &mut dict_length);
382+
/// if r == Z_OK {
383+
/// // ...and update the length to what was initialized.
384+
/// dict.set_len(dict_length);
385+
/// Some(dict)
386+
/// } else {
387+
/// None
388+
/// }
389+
/// }
390+
/// }
391+
/// # }
392+
/// ```
393+
///
394+
/// While the following example is sound, there is a memory leak since
395+
/// the inner vectors were not freed prior to the `set_len` call:
396+
///
397+
/// ```
398+
/// use core::iter::FromIterator;
399+
/// use heapless::Vec;
400+
/// use heapless::consts::*;
401+
///
402+
/// let mut vec = Vec::<Vec<u8, U3>, U3>::from_iter(
403+
/// [
404+
/// Vec::from_iter([1, 0, 0].iter().cloned()),
405+
/// Vec::from_iter([0, 1, 0].iter().cloned()),
406+
/// Vec::from_iter([0, 0, 1].iter().cloned()),
407+
/// ]
408+
/// .iter()
409+
/// .cloned()
410+
/// );
411+
/// // SAFETY:
412+
/// // 1. `old_len..0` is empty so no elements need to be initialized.
413+
/// // 2. `0 <= capacity` always holds whatever `capacity` is.
414+
/// unsafe {
415+
/// vec.set_len(0);
416+
/// }
417+
/// ```
418+
///
419+
/// Normally, here, one would use [`clear`] instead to correctly drop
420+
/// the contents and thus not leak memory.
421+
pub unsafe fn set_len(&mut self, new_len: usize) {
422+
debug_assert!(new_len <= self.capacity());
423+
424+
self.0.len = new_len
425+
}
426+
330427
/// Removes an element from the vector and returns it.
331428
///
332429
/// The removed element is replaced by the last element of the vector.
@@ -726,8 +823,8 @@ where
726823

727824
#[cfg(test)]
728825
mod tests {
729-
use as_slice::AsSlice;
730826
use crate::{consts::*, Vec};
827+
use as_slice::AsSlice;
731828
use core::fmt::Write;
732829

733830
#[test]

0 commit comments

Comments
 (0)