@@ -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) ]
728825mod 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