Last active
November 25, 2022 17:35
-
-
Save barthap/1b6e717f8c659d269530415e7771f556 to your computer and use it in GitHub Desktop.
Rust: Vec<T> extension to move data out of it without copying.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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