1 module google.protobuf.wrappers;
2 
3 import std.json : JSONValue;
4 import google.protobuf;
5 
6 struct WrappedValue(T, string messageTypeFullName_)
7 {
8     import std.typecons : Nullable;
9 
10     enum messageTypeFullName = messageTypeFullName_;
11     static assert(messageTypeFullName_.length != 0);
12 
13     private struct _Message
14     {
15         @Proto(1) T value = protoDefaultValue!T;
16     }
17 
18     Nullable!T value;
19 
20     alias value this;
21 
22     inout this(inout T value)
23     {
24         this.value = value;
25     }
26 
27     auto toProtobuf()
28     {
29         return _Message(value).toProtobuf;
30     }
31 
32     auto fromProtobuf(R)(ref R inputRange)
33     {
34         value = inputRange.fromProtobuf!_Message.value;
35         return this;
36     }
37 
38     JSONValue toJSONValue()()
39     {
40         import google.protobuf.json_encoding;
41 
42         return value.isNull ? JSONValue(null) : value.get.toJSONValue;
43     }
44 
45     auto fromJSONValue()(JSONValue jsonValue)
46     {
47         import google.protobuf.json_encoding;
48 
49         if (jsonValue.isNull)
50             value.nullify;
51         else
52             value = jsonValue.fromJSONValue!T;
53         return this;
54     }
55 }
56 
57 alias DoubleValue = WrappedValue!(double, "google.protobuf.DoubleValue");
58 alias FloatValue = WrappedValue!(float, "google.protobuf.FloatValue");
59 alias Int64Value = WrappedValue!(long, "google.protobuf.Int64Value");
60 alias UInt64Value = WrappedValue!(ulong, "google.protobuf.UInt64Value");
61 alias Int32Value = WrappedValue!(int, "google.protobuf.Int32Value");
62 alias UInt32Value = WrappedValue!(uint, "google.protobuf.UInt32Value");
63 alias BoolValue = WrappedValue!(bool, "google.protobuf.BoolValue");
64 alias StringValue = WrappedValue!(string, "google.protobuf.StringValue");
65 alias BytesValue = WrappedValue!(bytes, "google.protobuf.BytesValue");
66 
67 unittest
68 {
69     import std.algorithm.comparison : equal;
70     import std.array : array, empty;
71     import std.meta : AliasSeq;
72 
73     auto buffer = Int64Value(10).toProtobuf.array;
74     assert(equal(buffer, [0x08, 0x0a]));
75     assert(buffer.fromProtobuf!UInt32Value == 10);
76 
77     assert(buffer.empty);
78     foreach (WrappedValue; AliasSeq!(DoubleValue, FloatValue, Int64Value, UInt64Value, Int32Value, UInt32Value,
79             BoolValue, StringValue, BytesValue))
80     {
81         static assert(protoDefaultValue!WrappedValue.isNull);
82         assert(buffer.fromProtobuf!WrappedValue == protoDefaultValue!(typeof(WrappedValue.value.get)));
83     }
84 }