1 /* 2 * hunt-amqp-client: AMQP Client Library for D Programming Language. Support for RabbitMQ and other AMQP Server. 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.amqp.client.AsyncResult; 13 14 import hunt.Exceptions; 15 import hunt.Functions; 16 import hunt.Object; 17 18 alias AsyncResultHandler(T) = Action1!(AsyncResult!T); 19 alias AsyncVoidHandler = AsyncResultHandler!Void; 20 alias VoidAsyncResult = AsyncResult!Void; 21 22 interface IAsyncResult { 23 24 /** 25 * A Throwable describing failure. This will be null if the operation succeeded. 26 * 27 * @return the cause or null if the operation succeeded. 28 */ 29 Throwable cause(); 30 31 /** 32 * Did it succeed? 33 * 34 * @return true if it succeded or false otherwise 35 */ 36 bool succeeded(); 37 38 /** 39 * Did it fail? 40 * 41 * @return true if it failed or false otherwise 42 */ 43 bool failed(); 44 45 } 46 47 /** 48 * Encapsulates the result of an asynchronous operation. 49 * <p> 50 * Many operations in Vert.x APIs provide results back by passing an instance of this in a {@link hunt.net.Handler}. 51 * <p> 52 * The result can either have failed or succeeded. 53 * <p> 54 * If it failed then the cause of the failure is available with {@link #cause}. 55 * <p> 56 * If it succeeded then the actual result is available with {@link #result} 57 * 58 * @author <a href="http://tfox.org">Tim Fox</a> 59 */ 60 interface AsyncResult(T) : IAsyncResult { 61 62 /** 63 * The result of the operation. This will be null if the operation failed. 64 * 65 * @return the result or null if the operation failed. 66 */ 67 T result(); 68 69 /** 70 * Apply a {@code mapper} function on this async result.<p> 71 * 72 * The {@code mapper} is called with the completed value and this mapper returns a value. This value will complete the result returned by this method call.<p> 73 * 74 * When this async result is failed, the failure will be propagated to the returned async result and the {@code mapper} will not be called. 75 * 76 * @param mapper the mapper function 77 * @return the mapped async result 78 */ 79 final AsyncResult!(U) map(U)(Function!(T, U) mapper) { 80 if (mapper is null) { 81 throw new NullPointerException(); 82 } 83 return new class AsyncResult!(U) { 84 override U result() { 85 if (succeeded()) { 86 return mapper(this.outer.result()); 87 } else { 88 return null; 89 } 90 } 91 92 override Throwable cause() { 93 return this.outer.cause(); 94 } 95 96 override bool succeeded() { 97 return this.outer.succeeded(); 98 } 99 100 override bool failed() { 101 return this.outer.failed(); 102 } 103 }; 104 } 105 106 /** 107 * Map the result of this async result to a specific {@code value}.<p> 108 * 109 * When this async result succeeds, this {@code value} will succeeed the async result returned by this method call.<p> 110 * 111 * When this async result fails, the failure will be propagated to the returned async result. 112 * 113 * @param value the value that eventually completes the mapped async result 114 * @return the mapped async result 115 */ 116 final AsyncResult!(V) map(V)(V value) { 117 return map!(V)((t) => value); 118 } 119 120 /** 121 * Map the result of this async result to {@code null}.<p> 122 * 123 * This is a convenience for {@code asyncResult.map((T) null)} or {@code asyncResult.map((Void) null)}.<p> 124 * 125 * When this async result succeeds, {@code null} will succeeed the async result returned by this method call.<p> 126 * 127 * When this async result fails, the failure will be propagated to the returned async result. 128 * 129 * @return the mapped async result 130 */ 131 final AsyncResult!(V) mapEmpty(V)() { 132 return map!(V)(V.init); 133 } 134 135 /** 136 * Apply a {@code mapper} function on this async result.<p> 137 * 138 * The {@code mapper} is called with the failure and this mapper returns a value. This value will complete the result returned by this method call.<p> 139 * 140 * When this async result is succeeded, the value will be propagated to the returned async result and the {@code mapper} will not be called. 141 * 142 * @param mapper the mapper function 143 * @return the mapped async result 144 */ 145 final AsyncResult!(T) otherwise(Function!(Throwable, T) mapper) { 146 if (mapper is null) { 147 throw new NullPointerException(); 148 } 149 return new class AsyncResult!(T) { 150 override T result() { 151 if (this.outer.succeeded()) { 152 return this.outer.result(); 153 } else if (this.outer.failed()) { 154 return mapper(this.outer.cause()); 155 } else { 156 static if(is(T == class) || is(T == interface)) { 157 return null; 158 } else { 159 return T.init; 160 } 161 } 162 } 163 164 override Throwable cause() { 165 return null; 166 } 167 168 override bool succeeded() { 169 return this.outer.succeeded() || this.outer.failed(); 170 } 171 172 override bool failed() { 173 return false; 174 } 175 }; 176 } 177 178 /** 179 * Map the failure of this async result to a specific {@code value}.<p> 180 * 181 * When this async result fails, this {@code value} will succeeed the async result returned by this method call.<p> 182 * 183 * When this async succeeds, the result will be propagated to the returned async result. 184 * 185 * @param value the value that eventually completes the mapped async result 186 * @return the mapped async result 187 */ 188 final AsyncResult!(T) otherwise(T value) { 189 return otherwise((err) => value); 190 } 191 192 /** 193 * Map the failure of this async result to {@code null}.<p> 194 * 195 * This is a convenience for {@code asyncResult.otherwise((T) null)}.<p> 196 * 197 * When this async result fails, the {@code null} will succeeed the async result returned by this method call.<p> 198 * 199 * When this async succeeds, the result will be propagated to the returned async result. 200 * 201 * @return the mapped async result 202 */ 203 final AsyncResult!(T) otherwiseEmpty() { 204 return otherwise((err) => T.init); 205 } 206 207 } 208 209 AsyncResult!T succeededResult(T)(T v) { 210 return new class AsyncResult!(T) { 211 override T result() { 212 return v; 213 } 214 215 override Throwable cause() { 216 return null; 217 } 218 219 override bool succeeded() { 220 return true; 221 } 222 223 override bool failed() { 224 return false; 225 } 226 }; 227 } 228 229 230 AsyncResult!T failedResult(T)(Throwable t) { 231 return new class AsyncResult!(T) { 232 override T result() { 233 static if(is(T == class) || is(T == interface)) { 234 return null; 235 } else { 236 return T.init; 237 } 238 } 239 240 override Throwable cause() { 241 return t; 242 } 243 244 override bool succeeded() { 245 return false; 246 } 247 248 override bool failed() { 249 return true; 250 } 251 }; 252 }