1 module awebview.wrapper.webstringarray;
2 
3 import std.traits;
4 
5 import awebview.wrapper.cpp;
6 import awebview.wrapper.webstring : WebString;
7 import awebview.wrapper.webstring;
8 import awebview.wrapper.webstring;
9 import awebview.wrapper.weakref;
10 
11 import carbon.memory;
12 import carbon.nonametype;
13 
14 
15 
16 struct WebStringArray
17 {
18     alias PayloadType(This) = typeof(This.init.payload);
19 
20 
21     @property
22     ref WebStringArrayCpp payload() nothrow @nogc
23     {
24         if(!_instance.refCountedStore.isInitialized)
25             __ctor(cast(CppObj)null);
26 
27         return _instance.refCountedPayload;
28     }
29 
30 
31     @property
32     ref inout(WebStringArrayCpp) payload(this T)() inout nothrow @nogc
33     if(is(T == const) || is(T == immutable))
34     {
35         if(this._instance.refCountedStore.isInitialized)
36             return *cast(typeof(return)*)&(this._instance.refCountedPayload());
37         else
38             return *cast(typeof(return)*)WebStringArrayCpp._emptyInstance;
39     }
40 
41 
42     this(ref const WebStringArrayCpp ws) nothrow @nogc
43     {
44         _instance = Instance(RefCountedNoGC!WebStringArrayCpp(ws.cppObj));
45     }
46 
47 
48     this(in WebStringCpp[] ws) nothrow @nogc
49     {
50         _instance = Instance(RefCountedNoGC!WebStringArrayCpp(ws));
51     }
52 
53 
54     this(in WebString[] ws) nothrow @nogc
55     {
56         _instance = Instance(RefCountedNoGC!WebStringArrayCpp(ws));
57     }
58 
59 
60     this(in awebview.wrapper.cpp.WebStringArray cppObj) nothrow @nogc
61     {
62         _instance = Instance(RefCountedNoGC!WebStringArrayCpp(cppObj));
63     }
64 
65 
66     this(uint n)
67     {
68         _instance = Instance(RefCountedNoGC!WebStringArrayCpp(n));
69     }
70 
71 
72     this(Char)(in Char[][] str)
73     {
74         _instance = Instance(RefCountedNoGC!WebStringArrayCpp(str));
75     }
76 
77 
78     WebStringArray dup() const nothrow @nogc @property
79     {
80         WebStringArray ws = this.cppObj;
81         return ws;
82     }
83 
84 
85     @property
86     inout(awebview.wrapper.cpp.WebStringArray)
87         cppObj(this T)() inout nothrow @nogc
88     { return cast(typeof(return))(cast(T*)&this).payload.cppObj; }
89 
90 
91     uint length() const nothrow @nogc
92     { return payload.length; }
93 
94     bool empty() const nothrow @nogc
95     { return payload.empty; }
96 
97     awebview.wrapper.webstring.WeakRef!(WebStringCpp) opIndex(size_t idx) @nogc nothrow
98     { return payload[idx]; }
99 
100     awebview.wrapper.webstring.WeakRef!(const(WebStringCpp)) opIndex(size_t idx) const @nogc nothrow
101     { return payload[idx]; }
102 
103     void opOpAssign(string op : "~", Char)(in Char[] str)
104     if(isSomeChar!Char)
105     {
106         WebStringCpp ws = str;
107         this ~= ws.cppObj;
108     }
109 
110 
111     void opOpAssign(string op : "~", Char)(in Char[][] str)
112     {
113         foreach(e; str){
114             WebStringCpp ws = str;
115             this ~= str.cppObj;
116         }
117     }
118 
119 
120     void opOpAssign(string op : "~")(const WebString str)
121     {
122         this ~= str.cppObj;
123     }
124 
125 
126     void opOpAssign(string op : "~")(ref const WebStringCpp str)
127     {
128         this ~= str.cppObj;
129     }
130 
131 
132     void opOpAssign(string op : "~")(in awebview.wrapper.cpp.WebString cppStr)
133     {
134         if(!_instance.refCountedStore.isInitialized){
135             __ctor(0);
136             this.payload ~= cppStr;
137             return;
138         }
139 
140 
141         if(_instance.refCountedStore.refCount > 1)
142             this = this.dup;
143 
144         this.payload ~= cppStr;
145     }
146 
147 
148     bool opEquals(ref const WebStringArrayCpp rhs) const nothrow @nogc
149     { return payload == rhs; }
150 
151 
152     bool opEquals(const WebStringArray rhs) const nothrow @nogc
153     { return payload == rhs.payload; }
154 
155     bool opEquals(E)(in E[] rhs) const
156     if(is(typeof(this[0] == rhs[0])))
157     { return payload == rhs; }
158 
159 
160     int opCmp(ref const WebStringArrayCpp rhs) const nothrow @nogc
161     { return payload.opCmp(rhs); }
162 
163     int opCmp(const WebStringArray rhs) const nothrow @nogc
164     { return payload.opCmp(rhs.payload); }
165 
166     int opCmp(E)(in E[] rhs) const
167     if(is(typeof(this[0].opCmp(rhs[0]))))
168     { return payload.opCmp(rhs); }
169 
170   private:
171     Instance _instance;
172 
173     static auto _dummyTypeCreate()
174     {
175         static struct Dummy
176         {
177             RefCountedNoGC!WebStringArrayCpp obj;
178             alias obj this;
179         }
180 
181         return Dummy();
182     }
183 
184     alias Instance = typeof(_dummyTypeCreate());
185     alias CppObj = awebview.wrapper.cpp.WebStringArray;
186 }
187 
188 @nogc unittest {
189     WebStringArray ws;
190 }
191 
192 
193 struct WebStringArrayCpp
194 {
195     this(in awebview.wrapper.cpp.WebStringArray p) @nogc nothrow
196     {
197         if(p is null)
198             WebStringArrayMember.ctor(this.cppObj!false);
199         else
200             WebStringArrayMember.ctor(this.cppObj!false, p);
201     }
202 
203 
204     this(uint n) @nogc nothrow
205     {
206         WebStringArrayMember.ctor(this.cppObj!false, n);
207     }
208 
209 
210     this(in WebString[] strarr) @nogc nothrow
211     {
212         WebStringArrayMember.ctor(this.cppObj!false);
213 
214         foreach(const ref e; strarr)
215             this ~= e;
216     }
217 
218 
219     this(in WebStringCpp[] strarr) @nogc nothrow
220     {
221         WebStringArrayMember.ctor(this.cppObj!false);
222 
223         foreach(const ref e; strarr)
224             this ~= e;
225     }
226 
227 
228     this(Char)(in Char[][] strarr) @nogc nothrow
229     if(isSomeChar!Char)
230     {
231         WebStringArrayMember.ctor(this.cppObj!false);
232 
233         foreach(const ref e; strarr)
234             this ~= e;
235     }
236 
237 
238     this(this) @nogc nothrow
239     {
240         if(cppField.vector_ !is null){
241             WebStringArrayCpp copy = WebStringArrayCpp(this.cppObj!false);
242             this._field = copy._field;
243             copy.cppField.vector_ = null;
244         }
245     }
246 
247 
248     ~this() @nogc nothrow
249     {
250         if(cppField.vector_ !is null){
251             WebStringArrayMember.dtor(this.cppObj!false);
252             cppField.vector_ = null;
253         }
254     }
255 
256 
257     uint length() const @nogc nothrow { return WebStringArrayMember.size(this.cppObj); }
258 
259     bool empty() const @nogc nothrow { return this.length == 0; }
260 
261     WeakRef!(WebStringCpp) opIndex(size_t idx) @nogc nothrow
262     in{
263         assert(idx <= uint.max);
264     }
265     body{
266         return WebStringArrayMember.At(this.cppObj, cast(uint)idx).weakRef!WebStringCpp;
267     }
268 
269 
270     WeakRef!(const(WebStringCpp)) opIndex(size_t idx) const @nogc nothrow
271     in{
272         assert(idx <= uint.max);
273     }
274     body{
275         return WebStringArrayMember.At(this.cppObj, cast(uint)idx).weakRef!WebStringCpp;
276     }
277 
278 
279     private
280     ref inout(CppObj.Field) cppField() inout @property pure nothrow @trusted @nogc
281     {
282         return *cast(typeof(return)*)_field.ptr;
283     }
284 
285 
286     CppObj cppObj(bool withInitialize = true)() nothrow @trusted @property @nogc
287     {
288         CppObj ret = cast(CppObj)cast(void*)_field.ptr;
289 
290       static if(withInitialize)
291         if(cppField.vector_ is null)
292             WebStringArrayMember.ctor(ret);
293 
294         return ret;
295     }
296 
297 
298     inout(CppObj) cppObj() inout nothrow @trusted @property @nogc
299     {
300         if(cppField.vector_ is null)
301             return cast(inout(CppObj))cast(inout(void)*)_emptyInstance._field.ptr;
302         else
303             return cast(inout(CppObj))cast(inout(void)*)_field.ptr;
304     }
305 
306 
307     void opOpAssign(string op : "~", Char)(in Char[] str)
308     if(isSomeChar!Char)
309     {
310         WebString ws = str;
311         this ~= ws;
312     }
313 
314 
315     void opOpAssign(string op : "~", Char)(in Char[][] strs)
316     if(isSomeChar!Char)
317     {
318         foreach(const ref e; strs)
319             this ~= e;
320     }
321 
322 
323     void opOpAssign(string op : "~")(auto ref const WebString str)
324     {
325         WebStringArrayMember.Push(this.cppObj, str.cppObj);
326     }
327 
328 
329     void opOpAssign(string op : "~")(auto ref const WebStringArrayCpp strs)
330     {
331         foreach(i; 0 .. strs.length)
332             this ~= strs[i];
333     }
334 
335 
336     void opOpAssign(string op : "~")(in awebview.wrapper.cpp.WebString cppStr)
337     {
338         WebStringArrayMember.Push(this.cppObj, cppStr);
339     }
340 
341 
342     bool opEquals()(ref const WebStringArrayCpp rhs) const nothrow @nogc
343     {
344         return opEqualsImpl(rhs);
345     }
346 
347 
348     bool opEquals(E)(in E[] rhs) const
349     if(is(typeof(this[0] == rhs[0])))
350     {
351         return opEqualsImpl(rhs);
352     }
353 
354 
355     bool opEquals(in awebview.wrapper.cpp.WebStringArray cobj) const nothrow @nogc
356     {
357         auto wr = cobj.weakRef!WebStringArrayCpp;
358         return this == wr.get;
359     }
360 
361 
362     int opCmp(ref const WebStringArrayCpp rhs) const nothrow @nogc
363     {
364         return opCmpImpl(rhs);
365     }
366 
367 
368     int opCmp(E)(in E[] rhs) const
369     if(is(typeof(this[0].opCmp(rhs[0]))))
370     {
371         return opCmpImpl(rhs);
372     }
373 
374 
375     int opCmp(in awebview.wrapper.cpp.WebStringArray cobj) const nothrow @nogc
376     {
377         auto wr = cobj.weakRef!WebStringArrayCpp;
378         return this.opCmp(wr.get);
379     }
380 
381 
382     static
383     auto weakRef(HandleWSA)(HandleWSA ws) @trusted
384     if(is(HandleWSA : const(awebview.wrapper.cpp.WebStringArray)))
385     {
386       static if(is(HandleWSA == awebview.wrapper.cpp.WebStringArray))
387         WebStringArrayCpp* wsp = cast(WebStringArrayCpp*)cast(void*)ws;
388       else static if(is(HandleWSA == const(awebview.wrapper.cpp.WebStringArray)))
389         const(WebStringArrayCpp)* wsp = cast(const(WebStringArrayCpp)*)cast(const(void)*)ws;
390       else
391         immutable(WebStringArrayCpp)* wsp = cast(immutable(WebStringArrayCpp)*)cast(immutable(void)*)ws;
392 
393         return refP(wsp);
394     }
395 
396 
397   private:
398     ubyte[CppObj.Field.sizeof] _field;
399 
400     static shared immutable(WebStringArrayCpp*) _emptyInstance;
401 
402     alias CppObj = awebview.wrapper.cpp.WebStringArray;
403 
404     shared static this()
405     {
406         WebStringArrayCpp* _empty = new WebStringArrayCpp;
407         WebStringArrayMember.ctor(_empty.cppObj!false);
408         _emptyInstance = cast(immutable)_empty;
409     }
410 
411 
412     bool opEqualsImpl(T)(ref T rhs) const
413     {
414         immutable lenThis = this.length;
415 
416         if(lenThis != rhs.length)
417             return false;
418 
419         foreach(i; 0 .. lenThis)
420             if(this[i] != rhs[i])
421                 return false;
422 
423         return true;
424     }
425 
426 
427     int opCmpImpl(T)(ref T rhs) const
428     {
429         immutable lenThis = this.length,
430                   lenRhs = rhs.length;
431 
432         if(lenThis < lenRhs)
433             return -1;
434         else if(lenThis > lenRhs)
435             return 1;
436 
437         foreach(i; 0 .. lenThis){
438             if(int res = this[i].opCmp(rhs[i]))
439                 return res;
440         }
441 
442         return 0;
443     }
444 }
445 
446 
447 unittest
448 {
449     WebStringArrayCpp arr;
450     assert(arr.length == 0);
451     assert(arr.empty);
452     assert(arr == arr);
453 
454     arr ~= "foobar";
455     assert(arr.length == 1);
456     assert(arr[0] == "foobar");
457     assert(arr == ["foobar"]);
458 
459     arr ~= "ああああ";
460     assert(arr.length == 2);
461     assert(arr[1] == "ああああ");
462     assert(arr == ["foobar", "ああああ"]);
463 }
464 
465 unittest
466 {
467     WebStringArrayCpp arr = ["オーサミウム", "オーサミウム", "おーさみうむ"];
468     assert(arr.length == 3);
469     assert(!arr.empty);
470 
471     auto arr2 = arr;
472     assert(arr2 == arr);
473     assert(arr2.cppObj != arr.cppObj);
474 }