1 module clid.validate; 2 3 import std.stdio : stderr; 4 import std.traits : FunctionTypeOf, Parameters; 5 6 /** 7 * Validates a command line argument. 8 */ 9 bool Validate(alias f)(string arg, int n) @property // @suppress(dscanner.style.phobos_naming_convention) 10 if (is(FunctionTypeOf!(f) == function) && is(Parameters!(f)[1] == int)) 11 { 12 return f(arg, n); 13 } 14 15 /** 16 * Validates a command line argument. 17 */ 18 bool Validate(alias f)(string arg, string str) @property // @suppress(dscanner.style.phobos_naming_convention) 19 if (is(FunctionTypeOf!(f) == function) && is(Parameters!(f)[1] == string)) 20 { 21 return f(arg, str); 22 } 23 24 /** 25 * Validates that the string is not empty. 26 */ 27 bool isNotEmpty(string arg, string str) 28 { 29 if (str.length == 0) 30 { 31 stderr.writeln("Argument " ~ arg ~ " must not be empty string"); 32 return false; 33 } 34 return true; 35 } 36 37 unittest 38 { 39 assert(isNotEmpty("--arg", "") == false); 40 assert(isNotEmpty("--arg", null) == false); 41 assert(isNotEmpty("--arg", "wow") == true); 42 assert(isNotEmpty("--arg", " ") == true); 43 } 44 45 /** 46 * Validates that argument refers to a valid file. 47 */ 48 bool isFile(string arg, string str) 49 { 50 import std.file : exists, fileIsFile = isFile; 51 52 if (!str.exists || !str.fileIsFile) 53 { 54 stderr.writeln("Argument " ~ arg ~ " must refer to a file that exists"); 55 return false; 56 } 57 return true; 58 } 59 60 /** 61 * Validates that argument refers to a valid directory. 62 */ 63 bool isDir(string arg, string str) 64 { 65 import std.file : exists, dirIsDir = isDir; 66 67 if (!str.exists || !str.dirIsDir) 68 { 69 stderr.writeln("Argument " ~ arg ~ " must refer to a directory that exists"); 70 return false; 71 } 72 return true; 73 } 74 75 /** 76 * Validates that the argument does not refer to anything on the filesystem. 77 */ 78 bool doesNotExist(string arg, string str) 79 { 80 import std.file : exists; 81 82 if (str.exists) 83 { 84 stderr.writeln("Argument " ~ arg ~ " must not refer to a file that already exists"); 85 return false; 86 } 87 return true; 88 } 89 90 /** 91 * Makes sure a given argument is a positive number (n >= 0). 92 */ 93 bool isPositive(string arg, int value) 94 { 95 if (value < 0) 96 { 97 stderr.writeln("Argument " ~ arg ~ " must be positive"); 98 return false; 99 } 100 return true; 101 } 102 103 unittest 104 { 105 assert(isPositive("--arg", 1) == true); 106 assert(isPositive("--arg", 0) == true); 107 assert(isPositive("--arg", -1) == false); 108 } 109 110 /** 111 * Makes sure a given argument is a negative number (n <= 0). 112 */ 113 bool isNegative(string arg, int value) 114 { 115 if (value > 0) 116 { 117 stderr.writeln("Argument " ~ arg ~ " must be negative"); 118 return false; 119 } 120 return true; 121 } 122 123 unittest 124 { 125 assert(isNegative("--arg", 1) == false); 126 assert(isNegative("--arg", 0) == true); 127 assert(isNegative("--arg", -1) == true); 128 } 129 130 /** 131 * Checks that a given argument is a valid port number (n > 0 && n < 65536). 132 */ 133 bool isPortNumber(string arg, int value) 134 { 135 if (value > 0 && value <= 0xFFFF) 136 return true; 137 stderr.writeln("Argument " ~ arg ~ " must be a port number within range of [1, 65535]"); 138 return false; 139 } 140 141 unittest 142 { 143 assert(isPortNumber("--arg", 1) == true); 144 assert(isPortNumber("--arg", 0xFFFF) == true); 145 assert(isPortNumber("--arg", 0) == false); 146 assert(isPortNumber("--arg", 0x10000) == false); 147 }