1 // Written in the D programming language. 2 3 /** 4 * MessagePack RPC common symbols 5 */ 6 module msgpackrpc.common; 7 8 import msgpack; 9 10 11 /** 12 * See: http://wiki.msgpack.org/display/MSGPACK/RPC+specification#RPCspecification-MessagePackRPCProtocolspecification 13 */ 14 enum MessageType 15 { 16 request = 0, 17 response = 1, 18 notify = 2 19 } 20 21 struct Endpoint 22 { 23 ushort port; 24 string address; 25 26 this(ushort port, string address) 27 { 28 this.port = port; 29 this.address = address; 30 } 31 32 this(string connectionString) 33 { 34 import std.array; 35 auto splitted = connectionString.split(":"); 36 this.address = splitted[0]; 37 import std.conv; 38 this.port = splitted[1].to!ushort; 39 } 40 41 } 42 43 unittest 44 { 45 auto e = Endpoint("127.0.0.1:18800"); 46 assert(e.port = 18800); 47 assert(e.address = "127.0.0.1"); 48 } 49 /** 50 * Base exception for RPC error hierarchy 51 */ 52 class RPCException : Exception 53 { 54 enum Code = ".RPCError"; 55 56 static void rethrow(ref Value error) 57 { 58 if (error.type == Value.type.array) { 59 auto errCode = error.via.array[0].as!string; 60 auto errMsg = error.via.array[1].as!string; 61 62 switch (errCode) { 63 case RPCException.Code: 64 throw new RPCException(errMsg); 65 case TimeoutException.Code: 66 throw new TimeoutException(errMsg); 67 case TransportException.Code: 68 throw new TransportException(errMsg); 69 case CallException.Code: 70 throw new CallException(errMsg); 71 case NoMethodException.Code: 72 throw new NoMethodException(errMsg); 73 case ArgumentException.Code: 74 throw new ArgumentException(errMsg); 75 default: 76 throw new Exception("Unknown code: code = " ~ errCode); 77 } 78 } else { 79 throw new RPCException(error.as!string); 80 } 81 } 82 83 mixin ExceptionConstructor; 84 } 85 86 /// 87 class TimeoutException : RPCException 88 { 89 enum Code = ".TimeoutError"; 90 mixin ExceptionConstructor; 91 } 92 93 /// 94 class TransportException : RPCException 95 { 96 enum Code = ".TransportError"; 97 mixin ExceptionConstructor; 98 } 99 100 /// 101 class CallException : RPCException 102 { 103 enum Code = ".NoMethodError"; 104 mixin ExceptionConstructor; 105 } 106 107 /// 108 class NoMethodException : CallException 109 { 110 enum Code = ".CallError.NoMethodError"; 111 mixin ExceptionConstructor; 112 } 113 114 /// 115 class ArgumentException : CallException 116 { 117 enum Code = ".CallError.ArgumentError"; 118 mixin ExceptionConstructor; 119 } 120 121 private: 122 123 mixin template ExceptionConstructor() 124 { 125 @safe pure nothrow this(string msg) 126 { 127 super(msg); 128 } 129 130 void toMsgpack(Packer)(ref Packer packer, bool withFieldName = false) const 131 { 132 packer.beginArray(2); 133 packer.pack(Code); 134 packer.pack(msg); 135 } 136 } 137 138 unittest 139 { 140 import std.typetuple; 141 142 foreach (E; TypeTuple!(RPCException, TimeoutException, TransportException, CallException, NoMethodException, ArgumentException)) { 143 auto e = new E("hoge"); 144 string[] codeAndMsg; 145 unpack(pack(e), codeAndMsg); 146 assert(codeAndMsg[0] == E.Code); 147 } 148 }