1 module grpc.common.metadata;
2 import interop.headers;
3 import grpc.logger;
4 import grpc.common.cq;
5 import grpc.core.utils;
6 import grpc.core.sync.mutex;
7 import grpc.core.resource;
8 import interop.functors;
9 import automem;
10 import core.lifetime;
11 
12 /*
13     INFO: This ARRAY SHOULD *NEVER* be shared across threads.
14     It is not thread-safe.
15 */
16 struct MetadataArray {
17 @safe @nogc:
18     private {
19         shared(Mutex) mutex;
20         SharedResource _meta;
21     }
22     
23     inout(grpc_metadata_array)* handle() inout @trusted nothrow {
24         return cast(typeof(return)) _meta.handle;
25     }
26 
27     @property ulong capacity() {
28         mutex.lock;
29         scope(exit) mutex.unlock;
30         
31         return handle.capacity;
32     }
33 
34     @property ulong count() {
35         mutex.lock;
36         scope(exit) mutex.unlock;
37         
38         grpc_metadata_array* arr = handle;
39         
40         ulong count = arr.count;
41         return count;
42     }
43 
44     grpc_metadata* opIndex(size_t i1) {
45         mutex.lock;
46         scope(exit) mutex.unlock;
47         assert(i1 < count, "out of range");
48         return () @trusted {
49             return &handle.metadata[i1];
50         } ();
51     }
52 
53     void cleanup() {
54         if (handle.metadata == null) return;
55 
56         () @trusted {
57             grpcwrap_metadata_array_destroy_metadata_only(handle);
58         } ();
59 
60         handle.metadata = null;
61         handle.count = 0;
62         handle.capacity = 0;
63     }
64 
65     static MetadataArray create() @trusted {
66         static bool release(shared(void)* ptr) @trusted nothrow {
67             grpc_metadata_array* array = cast(grpc_metadata_array*)ptr;
68             if (array.metadata) {
69                 for (int i = 0; i < array.count; i++) {
70                     grpc_slice_unref(array.metadata[i].key);
71                     grpc_slice_unref(array.metadata[i].value);
72                 }
73                 gpr_free(cast(void*)array.metadata);
74                 array.metadata = null;
75             }
76             gpr_free(cast(void*)ptr);
77             return true;
78         }
79 
80         grpc_metadata_array* mt = cast(grpc_metadata_array*)gpr_zalloc((grpc_metadata_array).sizeof);
81         if(mt != null) {
82             grpcwrap_metadata_array_init(mt, 1);
83             return MetadataArray(cast(shared)Mutex.create(), SharedResource(cast(shared)mt, &release));
84         }
85         assert(0, "malloc error");
86     }
87     
88     ~this() {
89         _meta.forceRelease();
90     }
91 }
92