1 module fluentasserts.core.operations.between;
2 
3 import fluentasserts.core.results;
4 import fluentasserts.core.evaluation;
5 
6 import fluentasserts.core.lifecycle;
7 
8 import std.conv;
9 import std.datetime;
10 
11 version(unittest) {
12   import fluentasserts.core.expect;
13 }
14 
15 ///
16 IResult[] between(T)(ref Evaluation evaluation) @safe nothrow {
17   evaluation.message.addText(" and ");
18   evaluation.message.addValue(evaluation.expectedValue.meta["1"]);
19   evaluation.message.addText(". ");
20 
21   T currentValue;
22   T limit1;
23   T limit2;
24 
25   try {
26     currentValue = evaluation.currentValue.strValue.to!T;
27     limit1 = evaluation.expectedValue.strValue.to!T;
28     limit2 = evaluation.expectedValue.meta["1"].to!T;
29   } catch(Exception e) {
30     return [ new MessageResult("Can't convert the values to " ~ T.stringof) ];
31   }
32 
33   return betweenResults(currentValue, limit1, limit2, evaluation);
34 }
35 
36 
37 ///
38 IResult[] betweenDuration(ref Evaluation evaluation) @safe nothrow {
39   evaluation.message.addText(" and ");
40 
41   Duration currentValue;
42   Duration limit1;
43   Duration limit2;
44 
45   try {
46     currentValue = dur!"nsecs"(evaluation.currentValue.strValue.to!size_t);
47     limit1 = dur!"nsecs"(evaluation.expectedValue.strValue.to!size_t);
48     limit2 = dur!"nsecs"(evaluation.expectedValue.meta["1"].to!size_t);
49 
50     evaluation.message.addValue(limit2.to!string);
51   } catch(Exception e) {
52     return [ new MessageResult("Can't convert the values to Duration") ];
53   }
54 
55   evaluation.message.addText(". ");
56 
57   return betweenResults(currentValue, limit1, limit2, evaluation);
58 }
59 
60 ///
61 IResult[] betweenSysTime(ref Evaluation evaluation) @safe nothrow {
62   evaluation.message.addText(" and ");
63 
64   SysTime currentValue;
65   SysTime limit1;
66   SysTime limit2;
67 
68   try {
69     currentValue = SysTime.fromISOExtString(evaluation.currentValue.strValue);
70     limit1 = SysTime.fromISOExtString(evaluation.expectedValue.strValue);
71     limit2 = SysTime.fromISOExtString(evaluation.expectedValue.meta["1"]);
72 
73     evaluation.message.addValue(limit2.toISOExtString);
74   } catch(Exception e) {
75     return [ new MessageResult("Can't convert the values to Duration") ];
76   }
77 
78   evaluation.message.addText(". ");
79 
80   return betweenResults(currentValue, limit1, limit2, evaluation);
81 }
82 
83 private IResult[] betweenResults(T)(T currentValue, T limit1, T limit2, ref Evaluation evaluation) {
84   T min = limit1 < limit2 ? limit1 : limit2;
85   T max = limit1 > limit2 ? limit1 : limit2;
86 
87   auto isLess = currentValue <= min;
88   auto isGreater = currentValue >= max;
89   auto isBetween = !isLess && !isGreater;
90 
91   string interval;
92 
93   try {
94     interval = "a value " ~ (evaluation.isNegated ? "outside" : "inside") ~ " (" ~ min.to!string ~ ", " ~ max.to!string ~ ") interval";
95   } catch(Exception) {
96     interval = "a value " ~ (evaluation.isNegated ? "outside" : "inside") ~ " the interval";
97   }
98 
99   IResult[] results = [];
100 
101   if(!evaluation.isNegated) {
102     if(!isBetween) {
103       evaluation.message.addValue(evaluation.currentValue.niceValue);
104 
105       if(isGreater) {
106         evaluation.message.addText(" is greater than or equal to ");
107         try evaluation.message.addValue(max.to!string);
108         catch(Exception) {}
109       }
110 
111       if(isLess) {
112         evaluation.message.addText(" is less than or equal to ");
113         try evaluation.message.addValue(min.to!string);
114         catch(Exception) {}
115       }
116 
117       evaluation.message.addText(".");
118 
119       results ~= new ExpectedActualResult(interval, evaluation.currentValue.niceValue);
120     }
121   } else if(isBetween) {
122     results ~= new ExpectedActualResult(interval, evaluation.currentValue.niceValue);
123   }
124 
125   return results;
126 }