1 /* 2 * Hunt - A refined core library for D programming language. 3 * 4 * Copyright (C) 2018-2019 HuntLabs 5 * 6 * Website: https://www.huntlabs.net/ 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 12 module hunt.text.Codec; 13 14 15 /** 16 * Fast B64 Encoder/Decoder as described in RFC 1421. 17 * <p>Does not insert or interpret whitespace as described in RFC 18 * 1521. If you require this you must pre/post process your data. 19 * <p> Note that in a web context the usual case is to not want 20 * linebreaks or other white space in the encoded output. 21 */ 22 class B64Code { 23 private enum char __pad = '='; 24 private enum char[] __rfc1421alphabet = 25 [ 26 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 27 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 28 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 29 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' 30 ]; 31 32 private __gshared byte[] __rfc1421nibbles; 33 34 private enum char[] __rfc4648urlAlphabet = 35 [ 36 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 37 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 38 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 39 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_' 40 ]; 41 42 private __gshared byte[] __rfc4648urlNibbles; 43 44 shared static this() { 45 46 __rfc1421nibbles = new byte[256]; 47 for (int i = 0; i < 256; i++) 48 __rfc1421nibbles[i] = -1; 49 for (byte b = 0; b < 64; b++) 50 __rfc1421nibbles[cast(byte) __rfc1421alphabet[b]] = b; 51 __rfc1421nibbles[cast(byte) __pad] = 0; 52 53 __rfc4648urlNibbles = new byte[256]; 54 for (int i = 0; i < 256; i++) 55 __rfc4648urlNibbles[i] = -1; 56 for (byte b = 0; b < 64; b++) 57 __rfc4648urlNibbles[cast(byte) __rfc4648urlAlphabet[b]] = b; 58 __rfc4648urlNibbles[cast(byte) __pad] = 0; 59 } 60 61 private this() { 62 } 63 64 65 66 /** 67 * Fast Base 64 encode as described in RFC 1421. 68 * <p>Does not insert whitespace as described in RFC 1521. 69 * <p> Avoids creating extra copies of the input/output. 70 * 71 * @param b byte array to encode. 72 * @return char array containing the encoded form of the input. 73 */ 74 static const(char)[] encode(byte[] b) { 75 if (b is null) 76 return null; 77 78 int bLen = cast(int)b.length; 79 int cLen = ((bLen + 2) / 3) * 4; 80 char[] c = new char[cLen]; 81 int ci = 0; 82 int bi = 0; 83 byte b0, b1, b2; 84 int stop = (bLen / 3) * 3; 85 while (bi < stop) { 86 b0 = b[bi++]; 87 b1 = b[bi++]; 88 b2 = b[bi++]; 89 c[ci++] = __rfc1421alphabet[(b0 >>> 2) & 0x3f]; 90 c[ci++] = __rfc1421alphabet[(b0 << 4) & 0x3f | (b1 >>> 4) & 0x0f]; 91 c[ci++] = __rfc1421alphabet[(b1 << 2) & 0x3f | (b2 >>> 6) & 0x03]; 92 c[ci++] = __rfc1421alphabet[b2 & 0x3f]; 93 } 94 95 if (bLen != bi) { 96 switch (bLen % 3) { 97 case 2: 98 b0 = b[bi++]; 99 b1 = b[bi++]; 100 c[ci++] = __rfc1421alphabet[(b0 >>> 2) & 0x3f]; 101 c[ci++] = __rfc1421alphabet[(b0 << 4) & 0x3f | (b1 >>> 4) & 0x0f]; 102 c[ci++] = __rfc1421alphabet[(b1 << 2) & 0x3f]; 103 c[ci++] = __pad; 104 break; 105 106 case 1: 107 b0 = b[bi++]; 108 c[ci++] = __rfc1421alphabet[(b0 >>> 2) & 0x3f]; 109 c[ci++] = __rfc1421alphabet[(b0 << 4) & 0x3f]; 110 c[ci++] = __pad; 111 c[ci++] = __pad; 112 break; 113 114 default: 115 break; 116 } 117 } 118 119 return c; 120 } 121 122 }