From 5eb2a8f7bdda44354c27a2f8cb5267524ba09135 Mon Sep 17 00:00:00 2001
From: lmiskiew <lukasz.miskiewicz20@gmail.com>
Date: Thu, 28 Feb 2019 08:23:11 +0000
Subject: [PATCH] Implement swab

---
 src/header/unistd/mod.rs          | 15 +++++++--
 tests/Makefile                    |  1 +
 tests/expected/unistd/swab.stderr |  0
 tests/expected/unistd/swab.stdout |  0
 tests/unistd/swab.c               | 51 +++++++++++++++++++++++++++++++
 5 files changed, 65 insertions(+), 2 deletions(-)
 create mode 100644 tests/expected/unistd/swab.stderr
 create mode 100644 tests/expected/unistd/swab.stdout
 create mode 100644 tests/unistd/swab.c

diff --git a/src/header/unistd/mod.rs b/src/header/unistd/mod.rs
index 0a1214e20..96803ce71 100644
--- a/src/header/unistd/mod.rs
+++ b/src/header/unistd/mod.rs
@@ -555,9 +555,20 @@ pub extern "C" fn sleep(seconds: c_uint) -> c_uint {
     0
 }
 
-// #[no_mangle]
+#[no_mangle]
 pub extern "C" fn swab(src: *const c_void, dest: *mut c_void, nbytes: ssize_t) {
-    unimplemented!();
+    if nbytes <= 0 {
+        return
+    }
+    let number_of_swaps = nbytes / 2;
+    let mut offset = 0;
+    for i in 0..number_of_swaps {
+        unsafe {
+            src.offset(offset).copy_to(dest.offset(offset + 1), 1);
+            src.offset(offset + 1).copy_to(dest.offset(offset), 1);
+        }
+        offset += 2;
+    }
 }
 
 #[no_mangle]
diff --git a/tests/Makefile b/tests/Makefile
index b2e5396fd..e1bf32db6 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -81,6 +81,7 @@ EXPECT_BINS=\
 	unistd/pipe \
 	unistd/rmdir \
 	unistd/sleep \
+	unistd/swab \
 	unistd/write \
 	waitpid \
 	wchar/mbrtowc \
diff --git a/tests/expected/unistd/swab.stderr b/tests/expected/unistd/swab.stderr
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/expected/unistd/swab.stdout b/tests/expected/unistd/swab.stdout
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/unistd/swab.c b/tests/unistd/swab.c
new file mode 100644
index 000000000..c194ff280
--- /dev/null
+++ b/tests/unistd/swab.c
@@ -0,0 +1,51 @@
+#include <unistd.h>
+
+int main(int argc, char ** argv) {
+
+    const char source[] = {0, 1, 2, 3, 4, 5, 6};
+    char destination[] = {0, 0, 0, 0, 0, 0};
+    const char flipped_source[] = {1, 0, 3, 2, 5, 4};
+    const char first_two_source_bytes_flipped[] = {1, 0};
+
+    swab(source, destination, /* nbytes */ -3);
+    for (int i = 0; i < sizeof(destination); ++i) {
+        if (destination[i] != 0) {
+            puts("If nbytes is negative destionation shouldn't be modified");
+            return 1;
+        }
+    }
+
+    swab(source, destination, /* nbytes */ 0);
+    for (int i = 0; i < sizeof(destination); ++i) {
+        if (destination[i] != 0) {
+            puts("If nbytes is zero destionation shouldn't be modified");
+            return 1;
+        }
+    }
+
+    swab(source, destination, /* nbytes */ 3);
+    for (int i = 0; i < sizeof(first_two_source_bytes_flipped); ++i) {
+        if (destination[i] != first_two_source_bytes_flipped[i]) {
+            puts("copied bytes don't match expected values");
+            return 1;
+        }
+    }
+    // If nbytes is not even it's not specified what should happen to the
+    // last byte so the third byte in destination is not checked.
+    for (int i = sizeof(first_two_source_bytes_flipped) + 1; i < sizeof(destination); ++i) {
+        if (destination[i] != 0) {
+            puts("swab modified too many bytes in destination");
+            return 1;
+        }
+    }
+
+    swab(source, destination, /* nbytes */ sizeof(destination));
+    for (int i = 0; i < sizeof(destination); ++i) {
+        if (destination[i] != flipped_source[i]) {
+            puts("copied bytes don't match expected values");
+            return 1;
+        }
+    }
+
+    return 0;
+}
-- 
GitLab