Skip to content

Instantly share code, notes, and snippets.

@victor-iyi
Created August 23, 2022 18:10
Show Gist options
  • Save victor-iyi/2d4d6f407c17fa698abd5efea43898b0 to your computer and use it in GitHub Desktop.
Save victor-iyi/2d4d6f407c17fa698abd5efea43898b0 to your computer and use it in GitHub Desktop.
Rust's vec![...] macro re-implementation
#[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