1 module grpc.core.utils;
2 import interop.headers;
3 import interop.functors;
4 import grpc.logger;
5 import std.experimental.allocator : theAllocator, makeArray, dispose;
6 public import core.time;
7 
8 auto slice_to_string(grpc_slice slice) @nogc {
9     return slice_to_type!string(slice);
10 }
11 
12 auto ref slice_to_type(T)(grpc_slice _slice) @nogc
13 if(__traits(isPOD, T) && __traits(compiles, cast(T)[0x01, 0x02])) {
14     struct Slice {
15         grpc_slice slice;
16         
17         T data() {
18             return cast(T)GRPC_SLICE_START_PTR(slice)[0..GRPC_SLICE_LENGTH(slice)];
19         }
20 
21         alias data this;
22 
23         ~this() {
24             grpc_slice_unref(slice);
25         }
26     }
27 
28     if (GRPC_SLICE_LENGTH(_slice) != 0) {
29         grpc_slice slice = grpc_slice_copy(_slice);
30         grpc_slice_ref(slice);
31         return Slice(slice);
32     }
33 
34     return Slice();
35 }
36 
37 auto byte_buffer_to_string(grpc_byte_buffer* bytebuf) {
38         return byte_buffer_to_type!string(bytebuf);
39 }
40 
41 auto byte_buffer_to_type(T)(grpc_byte_buffer* bytebuf) {
42         grpc_byte_buffer_reader reader;
43         grpc_byte_buffer_reader_init(&reader, bytebuf);
44         grpc_slice slices = grpc_byte_buffer_reader_readall(&reader);
45         grpc_byte_buffer_reader_destroy(&reader);
46         auto val = slice_to_type!T(slices);
47         return val;
48 }
49 
50 /* ensure that you unref after this.. don't want to keep a slice around too long */
51 
52 grpc_slice string_to_slice(string _string) {
53     import std.string : toStringz;
54     grpc_slice slice = grpc_slice_from_copied_string(_string.toStringz);
55     return slice;
56 }
57 
58 grpc_slice type_to_slice(T)(T type) {
59     grpc_slice slice = grpc_slice_from_copied_buffer(cast(const(char*))type.ptr, type.length);
60     return slice;
61 }
62     
63 gpr_timespec durtotimespec(Duration time) @nogc nothrow {
64     gpr_timespec t = gpr_time_from_nanos(time.split!"nsecs"().nsecs, GPR_TIMESPAN);
65     return t;
66 }
67 
68 Duration timespectodur(gpr_timespec time) @nogc nothrow {
69     return gpr_time_to_millis(gpr_time_sub(time, gpr_now(time.clock_type))).msecs; 
70 }
71 
72 import core.memory : GC;
73 void doNotMoveObject(void* ptr, size_t len) @trusted nothrow {
74     GC.addRange(ptr, len);
75     GC.setAttr(cast(void*)ptr, GC.BlkAttr.NO_MOVE);
76     GC.addRoot(ptr);
77 }
78 
79 void okToMoveObject(void* ptr) @trusted nothrow {
80     GC.removeRoot(ptr);
81     GC.clrAttr(cast(void*)ptr, GC.BlkAttr.NO_MOVE);
82     GC.removeRange(ptr);
83 }
84 
85 import grpc.core.tag : Tag;
86 bool callOverDeadline(Tag* _tag) {
87     if (_tag.ctx.details.deadline == -1.seconds) {
88         DEBUG!"call has NO deadline";
89         return false;
90     } else {
91         DEBUG!"%s vs %s"(MonoTime.currTime - _tag.ctx.timestamp, _tag.ctx.details.deadline);
92     }
93 
94     if (MonoTime.currTime - _tag.ctx.timestamp > _tag.ctx.details.deadline) {
95         DEBUG!"reached deadline, cannot go further";
96         return true;
97     }
98     return false;
99 }
100