1 module itsdangerous.encoding;
2 
3 import std.base64: Base64URLNoPadding, Base64Exception;
4 import std.conv;
5 import std.array;
6 import std.encoding;
7 import std.string: representation;
8 
9 import itsdangerous.exc;
10 
11 __gshared immutable string BASE64_ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_=";
12 
13 string base64Encode(T = string)(T s){
14     static if (is(T == string)){
15         return Base64URLNoPadding.encode(s.representation);
16     } else
17     static if (is(T == ubyte[])) {
18         return Base64URLNoPadding.encode(s);
19     }
20     
21 }
22 
23 string base64Decode(string s){
24     try{
25         return cast(string)Base64URLNoPadding.decode(s);
26     } catch (Base64Exception ex) {
27         throw new BadData("Invalid base64-encoded data: " ~ ex.msg);
28     }
29 }
30 
31 ubyte[] intToBytes(int n){
32     ubyte[4] bytes;
33 
34     bytes[0] = (n >> 24) & 0xFF;
35     bytes[1] = (n >> 16) & 0xFF;
36     bytes[2] = (n >> 8) & 0xFF;
37     bytes[3] = n & 0xFF;
38 
39     return bytes.dup;
40 }
41 
42 int bytesToInt(ubyte[] bytes){
43     return ((bytes[0] & 0xFF) << 24) + ((bytes[1] & 0xFF ) << 16) + ((bytes[2] & 0xFF ) << 8) + (bytes[3] & 0xFF);
44 }
45 
46 auto rsplit(string str, char sep){ // emulating behaviour of python rsplit
47     auto arr = str.split(sep);
48     if(arr.length == 2)
49         return arr;
50     else if (arr.length == 3){
51         auto last = arr[$-1];
52         arr.popBack();
53         return [arr[0] ~ sep ~ arr[1], last];
54     } else {
55         throw new Exception("Unexpected signature: more than 3 elements!");
56     }
57 }
58 
59 unittest {
60     assert(intToBytes(1577992918) == [94, 14, 66, 214]);
61     assert(bytesToInt(intToBytes(1577992918)) == 1577992918);
62 }