1 module dutils.random;
2 
3 import std.file : read;
4 import std.uuid : UUID;
5 
6 ubyte[] randomBytes(size_t size = size_t.max) {
7   return cast(ubyte[]) read("/dev/urandom", size);
8 }
9 
10 unittest {
11   auto result = randomBytes(10);
12   assert(result.length == 10, "Length of ubyte[] should be 10");
13 }
14 
15 char[] randomHex(size_t size = size_t.max) {
16   return hexString(randomBytes(size / 2));
17 }
18 
19 unittest {
20   auto result = randomHex(20);
21   assert(result.length == 20, "Length of hex string should be 20");
22 }
23 
24 UUID randomUUID() {
25   const uuidData = cast(string) read("/proc/sys/kernel/random/uuid", 36);
26   return UUID(uuidData);
27 }
28 
29 unittest {
30   auto result = randomUUID();
31   assert(result.empty() == false, "UUID should not be empty");
32 }
33 
34 //
35 // Including simple+efficient ubyte2hex converter
36 // from https://forum.dlang.org/post/opsfp9hj065a2sq9@digitalmars.com
37 //
38 private const char[16] hexdigits = "0123456789abcdef";
39 
40 private char[] hexString(ubyte[] d) {
41   char[] result;
42 
43   /* No point converting an empty array now is there? */
44   if (d.length != 0) {
45     ubyte u;
46     uint sz = u.sizeof * 2; /* number of chars required to represent one 'u' */
47     uint ndigits = 0;
48 
49     /* pre-allocate space required. */
50     result = new char[sz * d.length];
51 
52     /* start at end of resulting string, loop back to start. */
53     for (int i = cast(int) d.length - 1; i >= 0; i--) {
54       /*this loop takes the remainder of u/16, uses it as an index
55             into the hexdigits array, then does u/16, repeating
56             till u == 0
57             */
58       u = d[i];
59       for (; u; u /= 16) {
60         /* you can use u & 15 or u % 16 below
61                 both give you the remainder of u/16
62                 */
63         result[result.length - 1 - ndigits] = hexdigits[u & 15];
64         ndigits++;
65       }
66 
67       /* Pad each value with 0's */
68       for (; ndigits < (d.length - i) * sz; ndigits++) {
69         result[result.length - 1 - ndigits] = '0';
70       }
71     }
72   }
73 
74   return result;
75 }
76 
77 unittest {
78   import std.conv : parse;
79 
80   auto bytes = cast(ubyte[]) "12345678901234567890123456789012";
81   auto result = hexString(bytes);
82 
83   assert(result.length == bytes.length * 2, "Length of hex should be twice of the original ubyte[]");
84 }