Created
August 23, 2022 18:10
-
-
Save victor-iyi/2d4d6f407c17fa698abd5efea43898b0 to your computer and use it in GitHub Desktop.
Rust's vec![...] macro re-implementation
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
#[macro_export] | |
macro_rules! avec { | |
($($element:expr),*) => {{ | |
const COUNT: usize = crate::count![@COUNT; $($element),*]; | |
#[allow(unused_mut)] | |
let mut vs = Vec::with_capacity(COUNT); | |
$(vs.push($element);)* | |
vs | |
}}; | |
// Handle trailing comma. | |
($($element:expr,)*) => {{ | |
$crate::avec![$($element),*] | |
}}; | |
// avec![0; 5] => creates a vector of [0, 0, 0, 0, 0] | |
($element:expr; $count:expr) => {{ | |
// let count = $count; | |
// let mut vs = Vec::with_capacity(count); | |
// vs.extend(::std::iter::repeat($element).take(count)); | |
let mut vs = Vec::new(); | |
vs.resize($count, $element); | |
vs | |
}}; | |
} | |
#[macro_export] | |
#[doc(hidden)] | |
macro_rules! count { | |
// Count the number of elements by creating list of unit type. | |
(@COUNT; $($element:expr),*) => { | |
<[()]>::len(&[$(crate::count![@UNIT; $element]),*]) | |
}; | |
// Returns a unit in the substituting vector. | |
(@UNIT; $_element:expr) => { () }; | |
} | |
#[cfg(test)] | |
mod tests { | |
use super::*; | |
#[test] | |
fn empty_vec() { | |
let x: Vec<u32> = avec![]; | |
assert!(x.is_empty()); | |
} | |
#[test] | |
fn single() { | |
let x = avec![42]; | |
assert!(!x.is_empty()); | |
assert_eq!(x.len(), 1); | |
assert_eq!(x[0], 42); | |
} | |
#[test] | |
fn double() { | |
let x = avec![42, 43]; | |
assert!(!x.is_empty()); | |
assert_eq!(x.len(), 2); | |
assert_eq!(x[0], 42); | |
assert_eq!(x[1], 43); | |
} | |
#[test] | |
fn trailing() { | |
let every_letter = avec![ | |
"The quick brown fox jumps over the lazy dog", | |
"Pack my box with fivedozen liquor jugs", | |
]; | |
assert!(!every_letter.is_empty()); | |
assert_eq!(every_letter.len(), 2); | |
} | |
#[test] | |
fn count() { | |
let x = avec![42; 3]; | |
assert!(!x.is_empty()); | |
assert_eq!(x.len(), 3); | |
assert_eq!(x[0], 42); | |
assert_eq!(x[1], 42); | |
assert_eq!(x[2], 42); | |
} | |
#[test] | |
fn non_literals() { | |
let mut y = Some(42); | |
let x = avec![y.take().unwrap(); 2]; | |
assert!(!x.is_empty()); | |
assert_eq!(x.len(), 2); | |
assert_eq!(x[0], 42); | |
assert_eq!(x[1], 42); | |
} | |
/// ```compile_fail | |
/// let x: Vec<u32> = vecmac::avec![42; "foo"]; | |
/// ``` | |
#[allow(dead_code)] | |
fn invalid_count() {} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment