Refactor swapper code with traits.

Change-Id: Ia27d3a11fea86d2ac430c3455d5247cfc4891e70
diff --git a/benches/benchmarks.rs b/benches/benchmarks.rs
index 3f69369..5d5b958 100644
--- a/benches/benchmarks.rs
+++ b/benches/benchmarks.rs
@@ -5,63 +5,22 @@
 extern crate num;
 extern crate test;
 
-use rust_samples::{cswap, swap};
+use rust_samples::swapper::{CAllocaSwapper, CLoopSwapper, LoopSwapper, PtrSwapper, Swapper};
 
 use heapless::consts::{U10, U100, U1000, U10000, U100000, U1000000};
 use num::{one, zero, Num};
 use test::{black_box, Bencher};
 
-fn bench_swap_loop<T, N>(b: &mut Bencher)
+fn bench_swap<S, T, N>(b: &mut Bencher)
 where
+    S: Swapper,
     N: heapless::ArrayLength<T>,
     T: Num + Copy,
 {
     let (mut arr1, mut arr2) = bench_swap_setup::<T, N>();
 
     b.iter(|| {
-        swap::swap_loop(&mut arr1, &mut arr2);
-        black_box(&arr1);
-        black_box(&arr2);
-    });
-}
-
-fn bench_swap_ptrswap<T, N>(b: &mut Bencher)
-where
-    N: heapless::ArrayLength<T>,
-    T: Num + Copy,
-{
-    let (mut arr1, mut arr2) = bench_swap_setup::<T, N>();
-
-    b.iter(|| {
-        swap::swap_ptrswap(&mut arr1, &mut arr2);
-        black_box(&arr1);
-        black_box(&arr2);
-    });
-}
-
-fn bench_cswap_loop<T, N>(b: &mut Bencher)
-where
-    N: heapless::ArrayLength<T>,
-    T: Num + Copy,
-{
-    let (mut arr1, mut arr2) = bench_swap_setup::<T, N>();
-
-    b.iter(|| {
-        cswap::cswap_loop(&mut arr1, &mut arr2);
-        black_box(&arr1);
-        black_box(&arr2);
-    });
-}
-
-fn bench_cswap_alloca<T, N>(b: &mut Bencher)
-where
-    N: heapless::ArrayLength<T>,
-    T: Num + Copy,
-{
-    let (mut arr1, mut arr2) = bench_swap_setup::<T, N>();
-
-    b.iter(|| {
-        cswap::cswap_alloca(&mut arr1, &mut arr2);
+        S::swap(&mut arr1, &mut arr2);
         black_box(&arr1);
         black_box(&arr2);
     });
@@ -103,120 +62,120 @@
 
 #[bench]
 fn bench_swap_loop_len_10(b: &mut Bencher) {
-    bench_swap_loop::<BenchInt, U10>(b);
+    bench_swap::<LoopSwapper, BenchInt, U10>(b);
 }
 
 #[bench]
 fn bench_swap_loop_len_100(b: &mut Bencher) {
-    bench_swap_loop::<BenchInt, U100>(b);
+    bench_swap::<LoopSwapper, BenchInt, U100>(b);
 }
 
 #[bench]
 fn bench_swap_loop_len_1000(b: &mut Bencher) {
-    bench_swap_loop::<BenchInt, U1000>(b);
+    bench_swap::<LoopSwapper, BenchInt, U1000>(b);
 }
 
 #[bench]
 fn bench_swap_loop_len_10000(b: &mut Bencher) {
-    bench_swap_loop::<BenchInt, U10000>(b);
+    bench_swap::<LoopSwapper, BenchInt, U10000>(b);
 }
 
 #[bench]
 fn bench_swap_loop_len_100000(b: &mut Bencher) {
-    bench_swap_loop::<BenchInt, U100000>(b);
+    bench_swap::<LoopSwapper, BenchInt, U100000>(b);
 }
 
 #[bench]
 fn bench_swap_loop_len_1000000(b: &mut Bencher) {
-    bench_swap_loop::<BenchInt, U1000000>(b);
+    bench_swap::<LoopSwapper, BenchInt, U1000000>(b);
 }
 
 #[bench]
 fn bench_swap_ptrswap_len_10(b: &mut Bencher) {
-    bench_swap_ptrswap::<BenchInt, U10>(b);
+    bench_swap::<PtrSwapper, BenchInt, U10>(b);
 }
 
 #[bench]
 fn bench_swap_ptrswap_len_100(b: &mut Bencher) {
-    bench_swap_ptrswap::<BenchInt, U100>(b);
+    bench_swap::<PtrSwapper, BenchInt, U100>(b);
 }
 
 #[bench]
 fn bench_swap_ptrswap_len_1000(b: &mut Bencher) {
-    bench_swap_ptrswap::<BenchInt, U1000>(b);
+    bench_swap::<PtrSwapper, BenchInt, U1000>(b);
 }
 
 #[bench]
 fn bench_swap_ptrswap_len_10000(b: &mut Bencher) {
-    bench_swap_ptrswap::<BenchInt, U10000>(b);
+    bench_swap::<PtrSwapper, BenchInt, U10000>(b);
 }
 
 #[bench]
 fn bench_swap_ptrswap_len_100000(b: &mut Bencher) {
-    bench_swap_ptrswap::<BenchInt, U100000>(b);
+    bench_swap::<PtrSwapper, BenchInt, U100000>(b);
 }
 
 #[bench]
 fn bench_swap_ptrswap_len_1000000(b: &mut Bencher) {
-    bench_swap_ptrswap::<BenchInt, U1000000>(b);
+    bench_swap::<PtrSwapper, BenchInt, U1000000>(b);
 }
 
 #[bench]
 fn bench_cswap_loop_len_10(b: &mut Bencher) {
-    bench_cswap_loop::<BenchInt, U10>(b);
+    bench_swap::<CLoopSwapper, BenchInt, U10>(b);
 }
 
 #[bench]
 fn bench_cswap_loop_len_100(b: &mut Bencher) {
-    bench_cswap_loop::<BenchInt, U100>(b);
+    bench_swap::<CLoopSwapper, BenchInt, U100>(b);
 }
 
 #[bench]
 fn bench_cswap_loop_len_1000(b: &mut Bencher) {
-    bench_cswap_loop::<BenchInt, U1000>(b);
+    bench_swap::<CLoopSwapper, BenchInt, U1000>(b);
 }
 
 #[bench]
 fn bench_cswap_loop_len_10000(b: &mut Bencher) {
-    bench_cswap_loop::<BenchInt, U10000>(b);
+    bench_swap::<CLoopSwapper, BenchInt, U10000>(b);
 }
 
 #[bench]
 fn bench_cswap_loop_len_100000(b: &mut Bencher) {
-    bench_cswap_loop::<BenchInt, U100000>(b);
+    bench_swap::<CLoopSwapper, BenchInt, U100000>(b);
 }
 
 #[bench]
 fn bench_cswap_loop_len_1000000(b: &mut Bencher) {
-    bench_cswap_loop::<BenchInt, U1000000>(b);
+    bench_swap::<CLoopSwapper, BenchInt, U1000000>(b);
 }
 
 #[bench]
 fn bench_cswap_alloca_len_10(b: &mut Bencher) {
-    bench_cswap_alloca::<BenchInt, U10>(b);
+    bench_swap::<CAllocaSwapper, BenchInt, U10>(b);
 }
 
 #[bench]
 fn bench_cswap_alloca_len_100(b: &mut Bencher) {
-    bench_cswap_alloca::<BenchInt, U100>(b);
+    bench_swap::<CAllocaSwapper, BenchInt, U100>(b);
 }
 
 #[bench]
 fn bench_cswap_alloca_len_1000(b: &mut Bencher) {
-    bench_cswap_alloca::<BenchInt, U1000>(b);
+    bench_swap::<CAllocaSwapper, BenchInt, U1000>(b);
 }
 
 #[bench]
 fn bench_cswap_alloca_len_10000(b: &mut Bencher) {
-    bench_cswap_alloca::<BenchInt, U10000>(b);
+    bench_swap::<CAllocaSwapper, BenchInt, U10000>(b);
 }
 
 #[bench]
 fn bench_cswap_alloca_len_100000(b: &mut Bencher) {
-    bench_cswap_alloca::<BenchInt, U100000>(b);
+    bench_swap::<CAllocaSwapper, BenchInt, U100000>(b);
 }
 
 #[bench]
 fn bench_cswap_alloca_len_1000000(b: &mut Bencher) {
-    bench_cswap_alloca::<BenchInt, U1000000>(b);
+    bench_swap::<CAllocaSwapper, BenchInt, U1000000>(b);
 }
diff --git a/src/cswap.rs b/src/cswap.rs
deleted file mode 100644
index 44db6db..0000000
--- a/src/cswap.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-use crate::bindings;
-use std::cmp::min;
-use std::mem::size_of;
-
-pub fn cswap_loop<T>(a: &mut [T], b: &mut [T]) {
-    unsafe {
-        bindings::swap_loop(
-            a.as_mut_ptr() as *mut i8,
-            b.as_mut_ptr() as *mut i8,
-            (size_of::<T>() * min(a.len(), b.len())) as bindings::size_t,
-        )
-    }
-}
-
-pub fn cswap_malloc<T>(a: &mut [T], b: &mut [T]) {
-    unsafe {
-        bindings::swap_malloc(
-            a.as_mut_ptr() as *mut i8,
-            b.as_mut_ptr() as *mut i8,
-            (size_of::<T>() * min(a.len(), b.len())) as bindings::size_t,
-        )
-    }
-}
-
-pub fn cswap_alloca<T>(a: &mut [T], b: &mut [T]) {
-    unsafe {
-        bindings::swap_alloca(
-            a.as_mut_ptr() as *mut i8,
-            b.as_mut_ptr() as *mut i8,
-            (size_of::<T>() * min(a.len(), b.len())) as bindings::size_t,
-        )
-    }
-}
diff --git a/src/lib.rs b/src/lib.rs
index 62e269a..84e8fdc 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -3,5 +3,4 @@
 
 mod bindings;
 
-pub mod cswap;
-pub mod swap;
+pub mod swapper;
diff --git a/src/swap.rs b/src/swap.rs
deleted file mode 100644
index ef07130..0000000
--- a/src/swap.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-use core::{mem, ptr};
-use num::Num;
-use std::cmp::min;
-
-pub fn swap_loop<T>(a: &mut [T], b: &mut [T]) {
-    for (x, y) in a.iter_mut().zip(b.iter_mut()) {
-        mem::swap(x, y);
-    }
-}
-
-pub fn swap_ptrswap<T>(a: &mut [T], b: &mut [T]) {
-    unsafe { ptr::swap_nonoverlapping(a.as_mut_ptr(), b.as_mut_ptr(), min(a.len(), b.len())) }
-}
-
-/// Exactly equivalent to `swap_2`, but trades the use of unsafe operations against having to know
-/// the exact type and size of the vector at compile time.  Only works with `heapless::Vec`.
-pub fn swap_3<T, N>(a: &mut heapless::Vec<T, N>, b: &mut heapless::Vec<T, N>)
-where
-    N: heapless::ArrayLength<T>,
-    T: Num + Copy,
-{
-    mem::swap(a, b);
-}
diff --git a/src/swapper/c_swap.rs b/src/swapper/c_swap.rs
new file mode 100644
index 0000000..a9d7733
--- /dev/null
+++ b/src/swapper/c_swap.rs
@@ -0,0 +1,43 @@
+use crate::bindings;
+use crate::swapper::Swapper;
+use std::cmp::min;
+use std::mem::size_of;
+
+pub struct CLoopSwapper {}
+impl Swapper for CLoopSwapper {
+    fn swap<T>(a: &mut [T], b: &mut [T]) {
+        unsafe {
+            bindings::swap_loop(
+                a.as_mut_ptr() as *mut i8,
+                b.as_mut_ptr() as *mut i8,
+                (size_of::<T>() * min(a.len(), b.len())) as bindings::size_t,
+            )
+        }
+    }
+}
+
+pub struct CMallocSwapper {}
+impl Swapper for CMallocSwapper {
+    fn swap<T>(a: &mut [T], b: &mut [T]) {
+        unsafe {
+            bindings::swap_malloc(
+                a.as_mut_ptr() as *mut i8,
+                b.as_mut_ptr() as *mut i8,
+                (size_of::<T>() * min(a.len(), b.len())) as bindings::size_t,
+            )
+        }
+    }
+}
+
+pub struct CAllocaSwapper {}
+impl Swapper for CAllocaSwapper {
+    fn swap<T>(a: &mut [T], b: &mut [T]) {
+        unsafe {
+            bindings::swap_alloca(
+                a.as_mut_ptr() as *mut i8,
+                b.as_mut_ptr() as *mut i8,
+                (size_of::<T>() * min(a.len(), b.len())) as bindings::size_t,
+            )
+        }
+    }
+}
diff --git a/src/swapper/mod.rs b/src/swapper/mod.rs
new file mode 100644
index 0000000..47caa9b
--- /dev/null
+++ b/src/swapper/mod.rs
@@ -0,0 +1,7 @@
+mod c_swap;
+mod rust_swap;
+mod swapper;
+
+pub use c_swap::*;
+pub use rust_swap::*;
+pub use swapper::*;
diff --git a/src/swapper/rust_swap.rs b/src/swapper/rust_swap.rs
new file mode 100644
index 0000000..a11f303
--- /dev/null
+++ b/src/swapper/rust_swap.rs
@@ -0,0 +1,20 @@
+use crate::swapper::Swapper;
+
+use core::{mem, ptr};
+use std::cmp::min;
+
+pub struct LoopSwapper {}
+impl Swapper for LoopSwapper {
+    fn swap<T>(a: &mut [T], b: &mut [T]) {
+        for (x, y) in a.iter_mut().zip(b.iter_mut()) {
+            mem::swap(x, y);
+        }
+    }
+}
+
+pub struct PtrSwapper {}
+impl Swapper for PtrSwapper {
+    fn swap<T>(a: &mut [T], b: &mut [T]) {
+        unsafe { ptr::swap_nonoverlapping(a.as_mut_ptr(), b.as_mut_ptr(), min(a.len(), b.len())) }
+    }
+}
diff --git a/src/swapper/swapper.rs b/src/swapper/swapper.rs
new file mode 100644
index 0000000..bf045ee
--- /dev/null
+++ b/src/swapper/swapper.rs
@@ -0,0 +1,3 @@
+pub trait Swapper {
+    fn swap<T>(a: &mut [T], b: &mut [T]);
+}