diff --git a/source/app.d b/source/app.d
index aa1ce8e..f3ea994 100644
--- a/source/app.d
+++ b/source/app.d
@@ -11,19 +11,28 @@ int main(string[] args)
                              "encrypt" : false,
                              "decrypt" : false ];
 
-    Cipher cipher = Cipher.chacha20;
+    Cipher cipher = Cipher.salsa20;
     string keyFileName = "symkey.asc";
     bool armor;
 
-    auto helpInformation = getopt(
-        args,
-        std.getopt.config.bundling,
-        "gen-key|g", "Generate a new 256 bit key.", &actions["genKey"],
-        "encrypt|e", "Encrypt a message.", &actions["encrypt"],
-        "decrypt|d", "Decrypt a message.", &actions["decrypt"],
-        "cipher|c", "The cipher to use (default: %s).".format(cipher), &cipher,
-        "key|k", "The file which contains the key (default: %s).".format(keyFileName), &keyFileName,
-        "armor|a", "use ascii-armored I/O.", &armor);
+    GetoptResult result;
+    try
+    {
+        result = getopt(
+            args,
+            std.getopt.config.bundling,
+            "gen-key|g", "Generate a new 256 bit key.", &actions["genKey"],
+            "encrypt|e", "Encrypt a message.", &actions["encrypt"],
+            "decrypt|d", "Decrypt a message.", &actions["decrypt"],
+            "cipher|c", "The cipher to use (default: %s).".format(cipher), &cipher,
+            "key|k", "The file which contains the key (default: %s).".format(keyFileName), &keyFileName,
+            "armor|a", "use ascii-armored I/O.", &armor);
+    }
+    catch(Exception e)
+    {
+        stderr.writeln(e.msg);
+        return 1;
+    }
 
     size_t numberOfActions;
     foreach(value; actions.values)
@@ -54,19 +63,22 @@ int main(string[] args)
     }
     else
     {
-        helpInformation.helpWanted = true;
+        result.helpWanted = true;
     }
 
-    if(helpInformation.helpWanted)
-    {
-        defaultGetoptPrinter("Usage: mycrypt [options]\n\nCommon options:",
-            helpInformation.options[$-1..$]);
-        defaultGetoptPrinter("\nGlobal options:",
-            helpInformation.options[$-2..$-1]);
-        defaultGetoptPrinter("\nActions:",
-            helpInformation.options[0..3]);
-        defaultGetoptPrinter("\nAction options:",
-            helpInformation.options[3..5]);
-    }
+    printHelp(result.options);
+
     return 0;
 }
+
+void printHelp(Option[] options)
+{
+    defaultGetoptPrinter("Usage: learncrypt [options]\n\nCommon options:",
+        options[$-1..$]);
+    defaultGetoptPrinter("\nGlobal options:",
+        options[$-2..$-1]);
+    defaultGetoptPrinter("\nActions:",
+        options[0..3]);
+    defaultGetoptPrinter("\nAction options:",
+        options[3..5]);
+}
diff --git a/source/bitmanip.d b/source/bitmanip.d
index 3dd19c7..1d4f5cb 100644
--- a/source/bitmanip.d
+++ b/source/bitmanip.d
@@ -1,8 +1,9 @@
 module bitmanip;
 
 private import std.traits : isUnsigned;
+private import std.bitmanip : nativeToLittleEndian, littleEndianToNative;
 
-UIntType rotateLeft(UIntType)(in UIntType val, in size_t len) nothrow @nogc pure
+UIntType rotateLeft(UIntType)(in UIntType val, in size_t len) nothrow @nogc pure @safe
     if(isUnsigned!UIntType)
 {
     auto reducedLen = len % (8 * UIntType.sizeof);
@@ -19,7 +20,7 @@ unittest
     assert(test[1].rotateLeft(7) == 128);
 }
 
-UIntType rotateRight(UIntType)(in UIntType val, in size_t len) nothrow @nogc pure
+UIntType rotateRight(UIntType)(in UIntType val, in size_t len) nothrow @nogc pure @safe
     if(isUnsigned!UIntType)
 {
     auto reducedLen = len % (8 * UIntType.sizeof);
@@ -35,3 +36,26 @@ unittest
     assert(test[2].rotateRight(1) == 64);
     assert(test[2].rotateRight(7) == 1);
 }
+
+alias littleEndianInv = nativeToLittleEndian;
+
+uint littleEndian(in ubyte[] input) @safe pure nothrow @nogc
+in
+{
+    assert(input.length == uint.sizeof);
+}
+body
+{
+    ubyte[uint.sizeof] buf = input;
+    return littleEndianToNative!uint(buf);
+}
+
+unittest
+{
+    ubyte[] test0 = [0, 0, 0, 0];
+    ubyte[] test1 = [86, 75, 30, 9];
+    ubyte[] test2 = [255, 255, 255, 250];
+    assert(littleEndian(test0) == 0x00000000);
+    assert(littleEndian(test1) == 0x091e4b56);
+    assert(littleEndian(test2) == 0xfaffffff);
+}
diff --git a/source/chacha20.d b/source/chacha20.d
index c128232..f738a9f 100644
--- a/source/chacha20.d
+++ b/source/chacha20.d
@@ -212,30 +212,7 @@ enum string colRound(alias _x00, alias _x01, alias _x02, alias _x03,
                      0x481c2027, 0x53a8e4b5, 0x4c1f89c5, 0x3f78c9c8]);
 }*/
 
-alias littleEndianInv = nativeToLittleEndian;
-
-uint littleEndian(in ubyte[] input)
-in
-{
-    assert(input.length == uint.sizeof);
-}
-body
-{
-    ubyte[uint.sizeof] buf = input;
-    return littleEndianToNative!uint(buf);
-}
-
-unittest
-{
-    ubyte[] test0 = [0, 0, 0, 0];
-    ubyte[] test1 = [86, 75, 30, 9];
-    ubyte[] test2 = [255, 255, 255, 250];
-    assert(littleEndian(test0) == 0x00000000);
-    assert(littleEndian(test1) == 0x091e4b56);
-    assert(littleEndian(test2) == 0xfaffffff);
-}
-
-ubyte[] chacha20(in ubyte[] input)
+ubyte[] chacha20(in ubyte[] input) @safe nothrow pure
 in
 {
     assert(input.length == 64);
@@ -332,7 +309,7 @@ enum ubyte[4] σ1 = [110, 100,  32,  51];
 enum ubyte[4] σ2 = [ 50,  45,  98, 121];
 enum ubyte[4] σ3 = [116, 101,  32, 107];
 
-ubyte[] chacha20Exp(in ubyte[] key, in ubyte[] n)
+ubyte[] chacha20Exp(in ubyte[] key, in ubyte[] n) @safe nothrow pure
 in
 {
     assert(key.length == 32);
diff --git a/source/cipher.d b/source/cipher.d
index 620a731..cddfc9c 100644
--- a/source/cipher.d
+++ b/source/cipher.d
@@ -19,9 +19,9 @@ auto cipherFunction(R)(R range, ubyte[32] key, ubyte[8] nonce, Cipher cipher)
     final switch(cipher)
     {
         case Cipher.salsa20:
-            return salsa20Cipher(range, key, nonce);
+            return range.salsa20Cipher(key, nonce);
 
         case Cipher.chacha20:
-            return salsa20Cipher(range, key, nonce);
+            return range.salsa20Cipher(key, nonce);
     }
 }
diff --git a/source/salsa20.d b/source/salsa20.d
index b184465..b81f5a7 100644
--- a/source/salsa20.d
+++ b/source/salsa20.d
@@ -3,7 +3,6 @@ module salsa20;
 private import std.traits : isUnsigned;
 private import std.string : format;
 private import std.range : isInputRange, isForwardRange, ElementType;
-private import std.bitmanip : nativeToLittleEndian, littleEndianToNative;
 private import std.array;
 
 private import bitmanip;
@@ -212,30 +211,7 @@ unittest
                      0x481c2027, 0x53a8e4b5, 0x4c1f89c5, 0x3f78c9c8]);
 }
 
-alias littleEndianInv = nativeToLittleEndian;
-
-uint littleEndian(in ubyte[] input)
-in
-{
-    assert(input.length == uint.sizeof);
-}
-body
-{
-    ubyte[uint.sizeof] buf = input;
-    return littleEndianToNative!uint(buf);
-}
-
-unittest
-{
-    ubyte[] test0 = [0, 0, 0, 0];
-    ubyte[] test1 = [86, 75, 30, 9];
-    ubyte[] test2 = [255, 255, 255, 250];
-    assert(littleEndian(test0) == 0x00000000);
-    assert(littleEndian(test1) == 0x091e4b56);
-    assert(littleEndian(test2) == 0xfaffffff);
-}
-
-ubyte[] salsa20(in ubyte[] input)
+ubyte[] salsa20(in ubyte[] input) @save pure nothrow @safe
 in
 {
     assert(input.length == 64);
@@ -332,7 +308,7 @@ enum ubyte[4] σ1 = [110, 100,  32,  51];
 enum ubyte[4] σ2 = [ 50,  45,  98, 121];
 enum ubyte[4] σ3 = [116, 101,  32, 107];
 
-ubyte[] salsa20Exp(in ubyte[] key, in ubyte[] n)
+ubyte[] salsa20Exp(in ubyte[] key, in ubyte[] n) @safe pure nothrow
 in
 {
     assert(key.length == 32);