1 /++ 2 + IRC user masks. 3 +/ 4 module virc.usermask; 5 6 import std.algorithm : findSplit; 7 import std.range; 8 import std.typecons : Nullable; 9 10 /++ 11 + IRC user masks are generally in the form nick!ident@hostname. This struct 12 + exists for easy separation and manipulation of each piece of the mask. This 13 + also accepts cases where the ident and host are not present. 14 +/ 15 struct UserMask { 16 /// 17 string nickname; 18 /// 19 Nullable!string ident; 20 /// 21 Nullable!string host; 22 /// 23 this(string maskString) @safe pure nothrow @nogc { 24 auto split = maskString.findSplit("!"); 25 nickname = split[0]; 26 if ((split[1] == "!") && (split[2].length > 0)) { 27 auto split2 = split[2].findSplit("@"); 28 ident = split2[0]; 29 if (split2[1] == "@") { 30 host = split2[2]; 31 } 32 } else { 33 auto split2 = maskString.findSplit("@"); 34 nickname = split2[0]; 35 if (split2[1] == "@") { 36 host = split2[2]; 37 } 38 } 39 } 40 void toString(T)(T sink) const if (isOutputRange!(T, const(char))) { 41 put(sink, nickname); 42 if (!ident.isNull) { 43 put(sink, '!'); 44 put(sink, ident.get); 45 assert(!host.isNull); 46 } 47 if (!host.isNull) { 48 put(sink, '@'); 49 put(sink, host.get); 50 } 51 } 52 auto toHash() const { 53 auto hash = nickname.hashOf(); 54 if (!ident.isNull) { 55 hash = ident.get.hashOf(hash); 56 } 57 if (!host.isNull) { 58 hash = host.get.hashOf(hash); 59 } 60 return hash; 61 } 62 } 63 64 @safe pure nothrow @nogc unittest { 65 with (UserMask("localhost")) { 66 assert(nickname == "localhost"); 67 assert(ident.isNull); 68 assert(host.isNull); 69 } 70 with (UserMask("user!id@example.net")) { 71 assert(nickname == "user"); 72 assert(ident.get == "id"); 73 assert(host.get == "example.net"); 74 } 75 with (UserMask("user!id@example!!!.net")) { 76 assert(nickname == "user"); 77 assert(ident.get == "id"); 78 assert(host.get == "example!!!.net"); 79 } 80 with (UserMask("user!id@ex@mple!!!.net")) { 81 assert(nickname == "user"); 82 assert(ident.get == "id"); 83 assert(host.get == "ex@mple!!!.net"); 84 } 85 with (UserMask("user!id!@ex@mple!!!.net")) { 86 assert(nickname == "user"); 87 assert(ident.get == "id!"); 88 assert(host.get == "ex@mple!!!.net"); 89 } 90 with (UserMask("user!id")) { 91 assert(nickname == "user"); 92 assert(ident.get == "id"); 93 assert(host.isNull); 94 } 95 with (UserMask("user@example.net")) { 96 assert(nickname == "user"); 97 assert(ident.isNull); 98 assert(host.get == "example.net"); 99 } 100 } 101 @safe pure unittest { 102 import std.conv : text; 103 { 104 UserMask mask; 105 mask.nickname = "Nick"; 106 assert(mask.text == "Nick"); 107 } 108 { 109 UserMask mask; 110 mask.nickname = "Nick"; 111 mask.ident = "user"; 112 mask.host = "domain"; 113 assert(mask.text == "Nick!user@domain"); 114 } 115 }