1 module serialportx.util;
2 
3 import std.range;
4 import std.algorithm;
5 
6 import std.datetime.stopwatch;
7 
8 void msleep(Duration dt) @nogc
9 {
10     version (Have_vibe_core)
11     {
12         import vibe.core.core : sleep;
13         (cast(void function(Duration) @nogc) &sleep)(dt);
14     }
15     else
16     {
17         import std.concurrency : scheduler, yield, ThreadScheduler;
18         import core.thread : Fiber, Thread;
19 
20         if (scheduler is null)
21         {
22             Thread.sleep(dt);
23         }
24         else if (cast(ThreadScheduler)scheduler)
25         {
26             Thread.sleep(dt);
27         }
28         else
29         {
30             const tm = StopWatch(AutoStart.yes);
31             do (cast(void function() @nogc nothrow) &yield)(); while (tm.peek < dt);
32         }
33     }
34 }
35 
36 package bool hasFlag(A,B)(A a, B b) @property { return (a & b) == b; }
37 
38 struct Pair(A,B) { A a; B b; }
39 auto pair(A,B)(A a, B b) { return Pair!(A,B)(a, b); }
40 
41 struct PairList(A,B)
42 {
43     Pair!(A,B)[] list;
44     this(Pair!(A,B)[] list) { this.list = list; }
45 
46     @safe pure @nogc nothrow const
47     {
48         size_t countA(A a) { return list.map!(a=>a.a).count(a); }
49         size_t countB(B b) { return list.map!(a=>a.b).count(b); }
50 
51         bool isUniqA() @property { return list.all!(v=>countA(v.a) == 1); }
52         bool isUniqB() @property { return list.all!(v=>countB(v.b) == 1); }
53 
54         B firstA2B(A a, B defalutValue)
55         {
56             auto f = list.find!(v=>v.a == a);
57             if (f.empty) return defalutValue;
58             else return f.front.b;
59         }
60 
61         A firstB2A(B b, A defalutValue)
62         {
63             auto f = list.find!(v=>v.b == b);
64             if (f.empty) return defalutValue;
65             else return f.front.a;
66         }
67     }
68 
69     @safe pure nothrow const
70     {
71         auto allA2B(A a) { return list.filter!(v=>v.a == a).map!(v=>v.b); }
72         auto allB2A(B b) { return list.filter!(v=>v.b == b).map!(v=>v.a); }
73     }
74 }
75 
76 auto pairList(A,B)(Pair!(A,B)[] list...) { return PairList!(A,B)(list.dup); }
77 
78 unittest
79 {
80     auto pl = pairList(
81         pair(1, "hello"),
82         pair(1, "ololo"),
83         pair(2, "world"),
84         pair(3, "okda")
85     );
86 
87     assert(pl.countA(1) == 2);
88     assert(pl.firstA2B(1, "ok") == "hello");
89     assert(pl.countB("ok") == 0);
90     assert(pl.countB("okda") == 1);
91     assert(pl.firstB2A("okda", 0) == 3);
92     assert(pl.isUniqA == false);
93     assert(pl.isUniqB == true);
94 }
95 
96 unittest
97 {
98     static immutable pl = pairList(
99         pair(1, "hello"),
100         pair(2, "world"),
101         pair(3, "okda")
102     );
103 
104     static assert(pl.firstA2B(2, "ok") == "world");
105 }
106 
107 unittest
108 {
109     import std.algorithm : sum;
110     import std.string : join;
111 
112     immutable pl = pairList(
113         pair(1, "hello"),
114         pair(2, "okda"),
115         pair(1, "world"),
116         pair(3, "okda")
117     );
118 
119     assert(pl.allA2B(1).join(" ") == "hello world");
120     assert(pl.allB2A("okda").sum == 5);
121 }