1 ///
2 module rxd.rx.example;
3 
4 import std.stdio;
5 import std.traits : Parameters, ReturnType;
6 
7 enum isObserver(O, E) = is(typeof(useObserver!(O, E)()));
8 
9 enum isFunctionLike(F, This) =
10     is(typeof(F(Parameters!This.init)) : ReturnType!This);
11 
12 void useObserver(O, E)()
13 {
14     alias OnNext = void delegate(E);
15     alias OnComplete = void delegate();
16     alias OnError = void delegate(Exception);
17 
18     static assert( isFunctionLike!(typeof(&O.init.onNext), OnNext));
19     static assert( isFunctionLike!(typeof(&O.init.onComplete), OnComplete));
20     static assert( isFunctionLike!(typeof(&O.init.onError), OnError));
21 }
22 
23 unittest
24 {
25     class ObserverClass
26     {
27         void onNext(int) { }
28         void onComplete() { }
29         void onError(Exception) { }
30     }
31 
32     struct ObserverStruct
33     {
34         void onNext(double) const nothrow { }
35         void onComplete() @nogc pure { }
36         void onError(Exception) @safe const { }
37     }
38 
39     useObserver!(ObserverClass, int)();
40     useObserver!(ObserverStruct, double)();
41 }
42 
43 struct Result
44 {
45     alias OnNext = void delegate(int);
46 
47     void subscribe(alias onNext)()
48     {
49         onNext(42);
50     }
51 
52     void subscribe(O)(O observer)
53         if (isObserver!(O, int))
54     {
55         observer.onNext(42);
56     }
57 }
58 
59 auto createDummyObservable()
60 {
61     return Result.init;
62 }
63 
64 unittest
65 {
66 
67     // defines, but does not invoke, the Subscriber's onNext handler
68     // (in this example, the observer is very simple and has only
69     // an onNext handler)
70     alias myOnNext = (int x) => writeln(x);
71 
72     // defines, but does not invoke, the Observable
73     auto myObservable = createDummyObservable();
74 
75     // subscribes the Subscriber to the Observable, and invokes the Observable
76     myObservable.subscribe!(myOnNext)();
77 
78     // go on about my business
79 }