Skip to content

Instantly share code, notes, and snippets.

@algon-320
Created August 19, 2020 07:53
Show Gist options
  • Save algon-320/f34691d4429745901375a66b75b233ab to your computer and use it in GitHub Desktop.
Save algon-320/f34691d4429745901375a66b75b233ab to your computer and use it in GitHub Desktop.
#![allow(unused_macros)]
#![allow(clippy::inconsistent_digit_grouping)]
macro_rules! bitpack_internal {
($type:ty; []; ) => {
(0 as $type, 0)
};
($type:ty; [$num:literal]; $arg:expr) => {{
let (mut val, mut width) = bitpack_internal!($type; []; );
val |= $arg & (1 as $type).checked_shl($num).unwrap_or(0).wrapping_sub(1);
width += $num;
(val, width)
}};
($type:ty; [$num:literal, $($nums:literal),+]; $arg:expr, $($args:expr),+) => {{
let (mut val, mut width) = bitpack_internal!($type; [$($nums),+]; $($args),+);
val |= ($arg & ((1 << $num) - 1)) << width;
width += $num;
(val, width)
}};
}
macro_rules! bitpack {
($type:ty; [$($nums:literal),*]; $($args:expr),*) => {
bitpack_internal!($type; [$($nums),*]; $($args),*).0
};
}
#[cfg(test)]
mod tests {
#[test]
fn test_u8_pack() {
let x = 4;
let y = 2;
let v = bitpack!(u8; [3, 3, 2]; x, 0, y);
assert_eq!(v, 0b100_000_10);
// 本当はこんな感じに書きたい
// bitpack!(u8; "{3}000{2}", 4, 2);
assert_eq!(bitpack!(u8; []; ), 0b00000000);
assert_eq!(bitpack!(u8; [2]; 3), 0b00000011);
assert_eq!(bitpack!(u8; [2]; 4), 0b00000000);
assert_eq!(bitpack!(u8; [2]; 5), 0b00000001);
assert_eq!(bitpack!(u8; [1, 2]; 1, 2), 0b00000110);
assert_eq!(bitpack!(u8; [2, 2]; 3, 0), 0b00001100);
assert_eq!(bitpack!(u8; [3, 2]; 7, 0), 0b00011100);
assert_eq!(bitpack!(u8; [3, 3, 2]; 4, 7, 0), 0b10011100);
assert_eq!(bitpack!(u8; [2, 4, 2]; 3, 0, 3), 0b11000011);
assert_eq!(bitpack!(u8; [1,1,1,1,1,1,1,1]; 1,1,1,1,1,1,1,1), 0b11111111);
assert_eq!(bitpack!(u8; [1,1,1,1,1,1,1,1]; 1,1,1,0,1,1,0,1), 0b11101101);
assert_eq!(bitpack!(u8; [8]; 0xFF), 0xFF);
let v: u32 = bitpack!(u32; [10, 10, 2]; 0b1000000000, 0b1000000000, 0b10);
assert_eq!(v, 0b1000000000100000000010);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment