Created
February 2, 2023 03:36
-
-
Save FuuuOverclocking/a8fa886948ed421de6652cda8ec6ff99 to your computer and use it in GitHub Desktop.
[Rust] Traverse and consume the vector in the given order
This file contains hidden or 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
use std::mem::{self, ManuallyDrop}; | |
use std::ptr; | |
/// Traverse the vector in the given order. The vector will be consumed, and its | |
/// elements will be moved in when calling the closure. `order` must contain all | |
/// values in the range `0..vec.len()` without repetition or omission, but the | |
/// order of elements can be arbitrary. | |
/// | |
/// # Example | |
/// ``` | |
/// use {YOUR CRATE NAME}::consume_vec_in_order; | |
/// | |
/// let src = vec![ | |
/// "0".to_string(), | |
/// "1".to_string(), | |
/// "2".to_string(), | |
/// "3".to_string(), | |
/// "4".to_string(), | |
/// ]; | |
/// let mut dst = vec![]; | |
/// | |
/// consume_vec_in_order( | |
/// src, | |
/// &[2, 1, 3, 0, 4], | |
/// |elem| dst.push(elem), | |
/// ); | |
/// assert_eq!(dst, vec!["2", "1", "3", "0", "4"]); | |
/// ``` | |
pub fn consume_vec_in_order<T>(vec: Vec<T>, order: &[usize], mut cb: impl FnMut(T)) { | |
// Check whether `order` contains all numbers in 0..len without repetition | |
// or omission. | |
if cfg!(debug_assertions) { | |
use std::collections::HashSet; | |
let n = order.len(); | |
if n != vec.len() { | |
panic!("The length of `order` is not equal to that of `vec`."); | |
} | |
let mut set = HashSet::<usize>::new(); | |
for &idx in order { | |
if idx >= n { | |
panic!("`{idx}` in the `order` is out of range (0..{n})."); | |
} else if set.contains(&idx) { | |
panic!("`order` contains the repeated element `{idx}`"); | |
} else { | |
set.insert(idx); | |
} | |
} | |
} | |
unsafe { | |
for &idx in order { | |
let s = ptr::read(vec.get_unchecked(idx)); | |
cb(s); | |
} | |
let vec: Vec<ManuallyDrop<T>> = mem::transmute(vec); | |
drop(vec); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment