Skip to content

Instantly share code, notes, and snippets.

@barthap
Last active November 25, 2022 17:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save barthap/1b6e717f8c659d269530415e7771f556 to your computer and use it in GitHub Desktop.
Save barthap/1b6e717f8c659d269530415e7771f556 to your computer and use it in GitHub Desktop.
Rust: Vec<T> extension to move data out of it without copying.
pub trait MemOps {
fn move_and_clear(&mut self) -> Self;
}
impl<T> MemOps for Vec<T> {
/// Moves all the elememst of `self` into a new [`Vec`] instance,
/// leaving `self` empty. **No copying is performed.**
/// The memory capacity of `self` stays unchanged.
///
/// # Example
/// ```
/// let mut a = vec![1,2,3,4];
/// let b = a.move_and_clear();
/// assert_eq!(b.len(), 4);
/// assert!(a.is_empty());
/// assert_eq!(a.capacity(), b.capacity());
/// ```
fn move_and_clear(&mut self) -> Self {
let mut new_vec = Vec::with_capacity(self.capacity());
std::mem::swap(self, &mut new_vec);
return new_vec;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_memops_move_and_clear() {
let mut a = vec![1,2,3,4];
let a_ptr_before = a.as_ptr();
let b = a.move_and_clear();
let a_ptr_after = a.as_ptr();
let b_ptr_after = b.as_ptr();
assert_ne!(a_ptr_before, a_ptr_after, "Old ptr didn't change");
assert_eq!(a_ptr_before, b_ptr_after, "Ptr addresses don't match");
assert_eq!(a.capacity(), b.capacity(), "Capacities don't match");
assert!(a.is_empty(), "Original vec isn't empty after move");
assert_eq!(b.len(), 4, "Moved length don't match");
}
}
let mut temp_buffer: Vec<u8> = Vec::new();
// some data is periodically saved to the buffer
// e.g. read from I/O
if temp_buffer.len() >= MINIMAL_DATA_SIZE {
let data_to_save = temp_buffer.move_and_clear();
do_some_save(data_to_save)?;
}
// temp_buffer is now empty and ready for next data
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment