#![doc = include_str!("../README.md")]
fn do_copy<T: Copy>(src: &[T], dst: &mut [T], pattern: &[usize]) {
let pattern_len = pattern.len();
assert_eq!(src.len(), dst.len(), "src and dst need to be the same size");
assert!(
src.len().is_multiple_of(pattern_len),
"length must be divisable by {}, but is {}",
pattern_len,
src.len()
);
for i in 0..src.len() / pattern_len {
for j in 0..pattern_len {
dst[i * pattern_len + j] = src[i * pattern_len + pattern[j]];
}
}
}
macro_rules! define_copy {
($t: ident, [$i0: literal, $i1: literal, $i2: literal, $i3: literal]) => {
paste::paste! {
#[doc = concat!(
"Copy from `src` to `dst`, reordering 4 ",
stringify!($t),
" at a time in the pattern (",
$i0, ", ",
$i1, ", ",
$i2, ", ",
$i3, ").\n\n",
"\n",
"```\n",
"let mut swizzled = [0; 8];\n",
"swizzler::",
stringify!($t), "::", stringify!([<"copy_" $i0 $i1 $i2 $i3>]),
"(&[0, 1, 2, 3, 10, 11, 12, 13], &mut swizzled);\n",
"assert_eq!(swizzled, [",
concat!($i0, ", ", $i1, ", ", $i2, ", ", $i3), ", ",
concat!("1", $i0, ", 1", $i1, ", 1", $i2, ", 1", $i3),
"]);\n",
"```\n"
)]
pub fn [<"copy_" $i0 $i1 $i2 $i3>](src: &[$t], dst: &mut [$t]) {
super::do_copy(src, dst, &[$i0, $i1, $i2, $i3]);
}
}
};
}
macro_rules! define_type {
($t:ident) => {
#[doc = concat!("Functions for swizzling slices of `", stringify!($t), "`.")]
pub mod $t {
define_copy!($t, [0, 1, 2, 3]);
define_copy!($t, [0, 1, 3, 2]);
define_copy!($t, [0, 2, 1, 3]);
define_copy!($t, [0, 2, 3, 1]);
define_copy!($t, [0, 3, 1, 2]);
define_copy!($t, [0, 3, 2, 1]);
define_copy!($t, [1, 0, 2, 3]);
define_copy!($t, [1, 0, 3, 2]);
define_copy!($t, [1, 2, 0, 3]);
define_copy!($t, [1, 2, 3, 0]);
define_copy!($t, [1, 3, 0, 2]);
define_copy!($t, [1, 3, 2, 0]);
define_copy!($t, [2, 0, 1, 3]);
define_copy!($t, [2, 0, 3, 1]);
define_copy!($t, [2, 1, 0, 3]);
define_copy!($t, [2, 1, 3, 0]);
define_copy!($t, [2, 3, 0, 1]);
define_copy!($t, [2, 3, 1, 0]);
define_copy!($t, [3, 0, 1, 2]);
define_copy!($t, [3, 0, 2, 1]);
define_copy!($t, [3, 1, 0, 2]);
define_copy!($t, [3, 1, 2, 0]);
define_copy!($t, [3, 2, 0, 1]);
define_copy!($t, [3, 2, 1, 0]);
}
};
}
#[cfg(feature = "u8")]
define_type!(u8);
#[cfg(feature = "u16")]
define_type!(u16);
#[cfg(feature = "u32")]
define_type!(u32);
pub fn bgra_to_rgba(src: &[u8], dst: &mut [u8]) {
u8::copy_2103(src, dst);
}
pub fn rgba_to_bgra(src: &[u8], dst: &mut [u8]) {
u8::copy_2103(src, dst);
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(feature = "u8")]
#[test]
fn u8_copy_2103_test() {
let source = [10, 11, 12, 13, 20, 21, 22, 23];
let mut target = [0; 8];
u8::copy_2103(&source, &mut target);
assert_eq!(target, [12, 11, 10, 13, 22, 21, 20, 23]);
}
}