1 /*
2  * Copyright (c) 2017-2019 sel-project
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in all
12  * copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  *
22  */
23 /**
24  * Copyright: Copyright (c) 2017-2019 sel-project
25  * License: MIT
26  * Authors: Kripth
27  * Source: $(HTTP github.com/sel-project/selery/source/selery/util/util.d, selery/util/util.d)
28  */
29 module selery.util.util;
30 
31 import core.stdc.time : time_t, time;
32 
33 import std.conv : to, ConvException;
34 import std.datetime : Clock, UTC;
35 import std.traits : isArray, isAssociativeArray, isSafe;
36 
37 /**
38  * Gets the seconds from January 1st, 1970.
39  */
40 public @property @safe time_t seconds() {
41 	return time(null);
42 }
43 
44 /**
45  * Gets the milliseconds from January 1st, 1970.
46  */
47 public @property @safe ulong milliseconds() {
48 	auto t = Clock.currTime(UTC());
49 	return t.toUnixTime!long * 1000 + t.fracSecs.total!"msecs";
50 }
51 
52 /**
53  * Gets the microseconds from January 1st, 1970.
54  */
55 public @property @safe ulong microseconds() {
56 	auto t = Clock.currTime(UTC());
57 	return t.toUnixTime!long * 1000 + t.fracSecs.total!"usecs";
58 }
59 
60 /** 
61  * Calls a function on every element in the array.
62  * Example:
63  * ---
64  * Effect effect = new Effect(Effects.REGENERATION, 60, "V");
65  * 
66  * // classic method
67  * foreach(ref Player player ; players) {
68  *    player.addEffect(effect);
69  * }
70  * 
71  * // faster and easier method
72  * players.call!"addEffect"(effect);
73  * ---
74  */
75 public void call(string func, T, E...)(T array, E args) if((isArray!T || isAssociativeArray!T) && !isSafe!(__traits(getMember, typeof(T.init[0]), func))) {
76 	foreach(ref element ; array) {
77 		mixin("element." ~ func ~ "(args);");
78 	}
79 }
80 
81 /// ditto
82 public @safe void call(string func, T, E...)(T array, E args) if((isArray!T || isAssociativeArray!T) && isSafe!(__traits(getMember, typeof(T.init[0]), func))) {
83 	foreach(ref element ; array) {
84 		mixin("element." ~ func ~ "(args);");
85 	}
86 }
87 
88 /**
89  * Performs a safe conversion.
90  * Example:
91  * ---
92  * assert(90.safe!ubyte == 90);
93  * assert(256.safe!ubyte == 255);
94  * ---
95  */
96 public @property @safe T safe(T, E)(E value) {
97 	try {
98 		return value > T.max ? T.max : (value < T.min ? T.min : to!T(value));
99 	} catch(ConvException e) {
100 		return T.init;
101 	}
102 }