com.backnd.database 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/Attributes/ColumnAttribute.cs +46 -0
  2. package/Attributes/ColumnAttribute.cs.meta +11 -0
  3. package/Attributes/PrimaryKeyAttribute.cs +12 -0
  4. package/Attributes/PrimaryKeyAttribute.cs.meta +11 -0
  5. package/Attributes/TableAttribute.cs +44 -0
  6. package/Attributes/TableAttribute.cs.meta +11 -0
  7. package/Attributes.meta +8 -0
  8. package/BACKND.Database.asmdef +14 -0
  9. package/BACKND.Database.asmdef.meta +7 -0
  10. package/BaseModel.cs +22 -0
  11. package/BaseModel.cs.meta +11 -0
  12. package/Client.cs +490 -0
  13. package/Client.cs.meta +11 -0
  14. package/Editor/BACKND.Database.Editor.asmdef +18 -0
  15. package/Editor/BACKND.Database.Editor.asmdef.meta +7 -0
  16. package/Editor/PackageAssetInstaller.cs +251 -0
  17. package/Editor/PackageAssetInstaller.cs.meta +11 -0
  18. package/Editor.meta +8 -0
  19. package/Exceptions/DatabaseException.cs +34 -0
  20. package/Exceptions/DatabaseException.cs.meta +11 -0
  21. package/Exceptions.meta +8 -0
  22. package/Internal/ExpressionAnalyzer.cs +433 -0
  23. package/Internal/ExpressionAnalyzer.cs.meta +11 -0
  24. package/Internal/QueryTypes.cs +61 -0
  25. package/Internal/QueryTypes.cs.meta +11 -0
  26. package/Internal/SqlBuilder.cs +375 -0
  27. package/Internal/SqlBuilder.cs.meta +11 -0
  28. package/Internal/ValueFormatter.cs +103 -0
  29. package/Internal/ValueFormatter.cs.meta +11 -0
  30. package/Internal.meta +8 -0
  31. package/Network/DatabaseExecutor.cs +171 -0
  32. package/Network/DatabaseExecutor.cs.meta +11 -0
  33. package/Network/DatabaseRequest.cs +16 -0
  34. package/Network/DatabaseRequest.cs.meta +11 -0
  35. package/Network/DatabaseResponse.cs +81 -0
  36. package/Network/DatabaseResponse.cs.meta +11 -0
  37. package/Network.meta +8 -0
  38. package/QueryBuilder.cs +1001 -0
  39. package/QueryBuilder.cs.meta +11 -0
  40. package/README.md +24 -0
  41. package/TheBackend~/Plugins/Android/Backend.aar +0 -0
  42. package/TheBackend~/Plugins/Backend.dll +0 -0
  43. package/TheBackend~/Plugins/Editor/TheBackendMultiSettingEditor.dll +0 -0
  44. package/TheBackend~/Plugins/Editor/TheBackendSettingEditor.dll +0 -0
  45. package/TheBackend~/Plugins/LitJSON.dll +0 -0
  46. package/TheBackend~/Plugins/Settings/TheBackendHashKeySettings.dll +0 -0
  47. package/TheBackend~/Plugins/Settings/TheBackendMultiSettings.dll +0 -0
  48. package/TheBackend~/Plugins/Settings/TheBackendSettings.dll +0 -0
  49. package/Tools/BTask.cs +905 -0
  50. package/Tools/BTask.cs.meta +11 -0
  51. package/Tools/DatabaseLoop.cs +110 -0
  52. package/Tools/DatabaseLoop.cs.meta +11 -0
  53. package/Tools/JsonHelper.cs +82 -0
  54. package/Tools/JsonHelper.cs.meta +11 -0
  55. package/Tools.meta +8 -0
  56. package/TransactionBuilder.cs +154 -0
  57. package/TransactionBuilder.cs.meta +11 -0
  58. package/TransactionQueryBuilder.cs +205 -0
  59. package/TransactionQueryBuilder.cs.meta +11 -0
  60. package/TransactionResult.cs +33 -0
  61. package/TransactionResult.cs.meta +11 -0
  62. package/package.json +20 -0
  63. package/package.json.meta +7 -0
package/Tools/BTask.cs ADDED
@@ -0,0 +1,905 @@
1
+ using System;
2
+ using System.Collections;
3
+ using System.Runtime.CompilerServices;
4
+ using System.Threading;
5
+
6
+ using UnityEngine;
7
+ using UnityEngine.Networking;
8
+
9
+ namespace BACKND.Database
10
+ {
11
+ [AsyncMethodBuilder(typeof(BTaskMethodBuilder))]
12
+ public class BTask : IEnumerator
13
+ {
14
+ protected bool isCompleted;
15
+ protected Exception exception;
16
+ protected Action continuation;
17
+ protected CancellationToken cancellationToken;
18
+
19
+ public bool IsCompleted => isCompleted;
20
+ public bool IsFaulted => exception != null;
21
+ public bool IsCanceled => cancellationToken.IsCancellationRequested;
22
+
23
+ public Exception GetException() => exception;
24
+
25
+ public BTask()
26
+ {
27
+ }
28
+
29
+ public BTask(CancellationToken cancellationToken)
30
+ {
31
+ this.cancellationToken = cancellationToken;
32
+ cancellationToken.Register(OnCanceled);
33
+ }
34
+
35
+ protected void ScheduleContinuation(Action action)
36
+ {
37
+ if (action == null)
38
+ {
39
+ return;
40
+ }
41
+
42
+
43
+ #if UNITY_EDITOR
44
+ if (!Application.isPlaying)
45
+ {
46
+ void EditorUpdate()
47
+ {
48
+ UnityEditor.EditorApplication.update -= EditorUpdate;
49
+ action();
50
+ }
51
+ UnityEditor.EditorApplication.update += EditorUpdate;
52
+ return;
53
+ }
54
+ #endif
55
+
56
+ DatabaseLoop.OnLateUpdate += ExecuteAction;
57
+
58
+ void ExecuteAction()
59
+ {
60
+ DatabaseLoop.OnLateUpdate -= ExecuteAction;
61
+ action();
62
+ }
63
+ }
64
+
65
+ public void SetResult()
66
+ {
67
+ if (isCompleted) return;
68
+
69
+ isCompleted = true;
70
+ if (continuation != null)
71
+ {
72
+ ScheduleContinuation(continuation);
73
+ #if UNITY_EDITOR
74
+ if (!Application.isPlaying)
75
+ {
76
+ UnityEditor.EditorApplication.QueuePlayerLoopUpdate();
77
+ }
78
+ #endif
79
+ }
80
+ }
81
+
82
+ public void SetException(Exception ex)
83
+ {
84
+ if (isCompleted) return;
85
+
86
+ exception = ex;
87
+ isCompleted = true;
88
+ if (continuation != null)
89
+ {
90
+ ScheduleContinuation(continuation);
91
+ #if UNITY_EDITOR
92
+ if (!Application.isPlaying)
93
+ {
94
+ UnityEditor.EditorApplication.QueuePlayerLoopUpdate();
95
+ }
96
+ #endif
97
+ }
98
+ }
99
+
100
+ protected virtual void OnCanceled()
101
+ {
102
+ SetException(new OperationCanceledException(cancellationToken));
103
+ }
104
+
105
+ public BTaskAwaiter GetAwaiter()
106
+ {
107
+ return new BTaskAwaiter(this);
108
+ }
109
+
110
+ internal void OnCompleted(Action continuation)
111
+ {
112
+ this.continuation = continuation;
113
+ if (isCompleted)
114
+ {
115
+ ScheduleContinuation(continuation);
116
+ #if UNITY_EDITOR
117
+ if (!Application.isPlaying)
118
+ {
119
+ UnityEditor.EditorApplication.QueuePlayerLoopUpdate();
120
+ }
121
+ #endif
122
+ }
123
+ }
124
+
125
+ public BTask ContinueWith(Action<BTask> continuation)
126
+ {
127
+ var nextTask = new BTask();
128
+
129
+ OnCompleted(() =>
130
+ {
131
+ try
132
+ {
133
+ continuation(this);
134
+ nextTask.SetResult();
135
+ }
136
+ catch (Exception ex)
137
+ {
138
+ nextTask.SetException(ex);
139
+ }
140
+ });
141
+
142
+ return nextTask;
143
+ }
144
+
145
+ public BTask<TResult> ContinueWith<TResult>(Func<BTask, TResult> continuation)
146
+ {
147
+ var nextTask = new BTask<TResult>();
148
+
149
+ OnCompleted(() =>
150
+ {
151
+ try
152
+ {
153
+ if (IsFaulted)
154
+ {
155
+ nextTask.SetException(GetException());
156
+ }
157
+ else
158
+ {
159
+ var result = continuation(this);
160
+ nextTask.SetResult(result);
161
+ }
162
+ }
163
+ catch (Exception ex)
164
+ {
165
+ nextTask.SetException(ex);
166
+ }
167
+ });
168
+
169
+ return nextTask;
170
+ }
171
+
172
+ public object Current => null;
173
+
174
+ public bool MoveNext()
175
+ {
176
+ return !IsCompleted;
177
+ }
178
+
179
+ public void Reset()
180
+ {
181
+ throw new NotSupportedException();
182
+ }
183
+
184
+ public static BTask Yield()
185
+ {
186
+ var task = new BTask();
187
+
188
+ #if UNITY_EDITOR
189
+ if (!Application.isPlaying)
190
+ {
191
+ UnityEditor.EditorApplication.delayCall += () => task.SetResult();
192
+ return task;
193
+ }
194
+ #endif
195
+
196
+ task.ScheduleContinuation(() => task.SetResult());
197
+ return task;
198
+ }
199
+
200
+ public static BTask NextFrame()
201
+ {
202
+ var task = new BTask();
203
+ var currentFrameTime = Time.realtimeSinceStartup;
204
+
205
+ #if UNITY_EDITOR
206
+ if (!Application.isPlaying)
207
+ {
208
+ UnityEditor.EditorApplication.delayCall += () => task.SetResult();
209
+ return task;
210
+ }
211
+ #endif
212
+
213
+ void CheckFrame()
214
+ {
215
+ if (Time.realtimeSinceStartup > currentFrameTime)
216
+ {
217
+ task.SetResult();
218
+ }
219
+ else
220
+ {
221
+ task.ScheduleContinuation(CheckFrame);
222
+ }
223
+ }
224
+
225
+ task.ScheduleContinuation(CheckFrame);
226
+ return task;
227
+ }
228
+
229
+ public static BTask Delay(float seconds)
230
+ {
231
+ var task = new BTask();
232
+ var targetTime = Time.realtimeSinceStartup + seconds;
233
+
234
+
235
+ #if UNITY_EDITOR
236
+ if (!Application.isPlaying)
237
+ {
238
+ void EditorUpdate()
239
+ {
240
+ if (Time.realtimeSinceStartup >= targetTime)
241
+ {
242
+ UnityEditor.EditorApplication.update -= EditorUpdate;
243
+ task.SetResult();
244
+ }
245
+ }
246
+ UnityEditor.EditorApplication.update += EditorUpdate;
247
+ return task;
248
+ }
249
+ #endif
250
+
251
+ void CheckTime()
252
+ {
253
+ if (Time.realtimeSinceStartup >= targetTime)
254
+ {
255
+ task.SetResult();
256
+ }
257
+ else
258
+ {
259
+ task.ScheduleContinuation(CheckTime);
260
+ }
261
+ }
262
+
263
+ task.ScheduleContinuation(CheckTime);
264
+ return task;
265
+ }
266
+
267
+ public static BTask CompletedTask
268
+ {
269
+ get
270
+ {
271
+ var task = new BTask();
272
+ task.SetResult();
273
+ return task;
274
+ }
275
+ }
276
+
277
+ public static BTask FromException(Exception exception)
278
+ {
279
+ var task = new BTask();
280
+ task.SetException(exception);
281
+ return task;
282
+ }
283
+
284
+ public static BTask FromCanceled(CancellationToken cancellationToken)
285
+ {
286
+ var task = new BTask(cancellationToken);
287
+ task.SetException(new OperationCanceledException(cancellationToken));
288
+ return task;
289
+ }
290
+
291
+ public static BTask Run(Action action)
292
+ {
293
+ var task = new BTask();
294
+
295
+ try
296
+ {
297
+ action();
298
+ task.SetResult();
299
+ }
300
+ catch (Exception ex)
301
+ {
302
+ task.SetException(ex);
303
+ }
304
+
305
+ return task;
306
+ }
307
+
308
+ public static BTask<T> Run<T>(Func<T> function)
309
+ {
310
+ var task = new BTask<T>();
311
+
312
+ try
313
+ {
314
+ var result = function();
315
+ task.SetResult(result);
316
+ }
317
+ catch (Exception ex)
318
+ {
319
+ task.SetException(ex);
320
+ }
321
+
322
+ return task;
323
+ }
324
+
325
+ public static BTask WhenAll(params BTask[] tasks)
326
+ {
327
+ var resultTask = new BTask();
328
+
329
+ if (tasks == null || tasks.Length == 0)
330
+ {
331
+ resultTask.SetResult();
332
+ return resultTask;
333
+ }
334
+
335
+ var remainingCount = tasks.Length;
336
+ Exception firstException = null;
337
+
338
+ foreach (var task in tasks)
339
+ {
340
+ task.OnCompleted(() =>
341
+ {
342
+ if (task.IsFaulted && firstException == null)
343
+ {
344
+ firstException = task.GetException();
345
+ }
346
+
347
+ if (Interlocked.Decrement(ref remainingCount) == 0)
348
+ {
349
+ if (firstException != null)
350
+ {
351
+ resultTask.SetException(firstException);
352
+ }
353
+ else
354
+ {
355
+ resultTask.SetResult();
356
+ }
357
+ }
358
+ });
359
+ }
360
+
361
+ return resultTask;
362
+ }
363
+
364
+ public static BTask<T[]> WhenAll<T>(params BTask<T>[] tasks)
365
+ {
366
+ var resultTask = new BTask<T[]>();
367
+
368
+ if (tasks == null || tasks.Length == 0)
369
+ {
370
+ resultTask.SetResult(new T[0]);
371
+ return resultTask;
372
+ }
373
+
374
+ var results = new T[tasks.Length];
375
+ var remainingCount = tasks.Length;
376
+ Exception firstException = null;
377
+
378
+ for (int i = 0; i < tasks.Length; i++)
379
+ {
380
+ var index = i;
381
+ var task = tasks[i];
382
+
383
+ task.OnCompleted(() =>
384
+ {
385
+ if (task.IsFaulted)
386
+ {
387
+ if (firstException == null)
388
+ {
389
+ firstException = task.GetException();
390
+ }
391
+ }
392
+ else
393
+ {
394
+ results[index] = task.Result;
395
+ }
396
+
397
+ if (Interlocked.Decrement(ref remainingCount) == 0)
398
+ {
399
+ if (firstException != null)
400
+ {
401
+ resultTask.SetException(firstException);
402
+ }
403
+ else
404
+ {
405
+ resultTask.SetResult(results);
406
+ }
407
+ }
408
+ });
409
+ }
410
+
411
+ return resultTask;
412
+ }
413
+
414
+ public static BTask<BTask> WhenAny(params BTask[] tasks)
415
+ {
416
+ var resultTask = new BTask<BTask>();
417
+
418
+ if (tasks == null || tasks.Length == 0)
419
+ {
420
+ resultTask.SetException(new ArgumentException("tasks array is empty"));
421
+ return resultTask;
422
+ }
423
+
424
+ var isCompleted = 0;
425
+
426
+ foreach (var task in tasks)
427
+ {
428
+ task.OnCompleted(() =>
429
+ {
430
+ if (Interlocked.CompareExchange(ref isCompleted, 1, 0) == 0)
431
+ {
432
+ resultTask.SetResult(task);
433
+ }
434
+ });
435
+ }
436
+
437
+ return resultTask;
438
+ }
439
+
440
+ }
441
+
442
+ [AsyncMethodBuilder(typeof(BTaskMethodBuilder<>))]
443
+ public class BTask<T> : BTask, IEnumerator
444
+ {
445
+ private T result;
446
+
447
+ public T Result
448
+ {
449
+ get
450
+ {
451
+ if (IsFaulted)
452
+ throw GetException();
453
+ if (!IsCompleted)
454
+ throw new InvalidOperationException("Task not completed");
455
+ return result;
456
+ }
457
+ }
458
+
459
+ public BTask() : base()
460
+ {
461
+ }
462
+
463
+ public BTask(CancellationToken cancellationToken) : base(cancellationToken)
464
+ {
465
+ }
466
+
467
+ public void SetResult(T value)
468
+ {
469
+ if (isCompleted) return;
470
+
471
+ result = value;
472
+ base.SetResult();
473
+ }
474
+
475
+ public new BTaskAwaiter<T> GetAwaiter()
476
+ {
477
+ return new BTaskAwaiter<T>(this);
478
+ }
479
+
480
+ public static BTask<T> FromResult(T result)
481
+ {
482
+ var task = new BTask<T>();
483
+ task.SetResult(result);
484
+ return task;
485
+ }
486
+
487
+ public static new BTask<T> FromException(Exception exception)
488
+ {
489
+ var task = new BTask<T>();
490
+ task.SetException(exception);
491
+ return task;
492
+ }
493
+
494
+ public static new BTask<T> FromCanceled(CancellationToken cancellationToken)
495
+ {
496
+ var task = new BTask<T>(cancellationToken);
497
+ task.SetException(new OperationCanceledException(cancellationToken));
498
+ return task;
499
+ }
500
+
501
+ public BTask ContinueWith(Action<BTask<T>> continuation)
502
+ {
503
+ var nextTask = new BTask();
504
+
505
+ OnCompleted(() =>
506
+ {
507
+ try
508
+ {
509
+ continuation(this);
510
+ nextTask.SetResult();
511
+ }
512
+ catch (Exception ex)
513
+ {
514
+ nextTask.SetException(ex);
515
+ }
516
+ });
517
+
518
+ return nextTask;
519
+ }
520
+
521
+ public BTask<TResult> ContinueWith<TResult>(Func<BTask<T>, TResult> continuation)
522
+ {
523
+ var nextTask = new BTask<TResult>();
524
+
525
+ OnCompleted(() =>
526
+ {
527
+ try
528
+ {
529
+ if (IsFaulted)
530
+ {
531
+ nextTask.SetException(GetException());
532
+ }
533
+ else
534
+ {
535
+ var result = continuation(this);
536
+ nextTask.SetResult(result);
537
+ }
538
+ }
539
+ catch (Exception ex)
540
+ {
541
+ nextTask.SetException(ex);
542
+ }
543
+ });
544
+
545
+ return nextTask;
546
+ }
547
+
548
+ public BTask<TResult> Then<TResult>(Func<T, TResult> selector)
549
+ {
550
+ var nextTask = new BTask<TResult>();
551
+
552
+ OnCompleted(() =>
553
+ {
554
+ try
555
+ {
556
+ if (IsFaulted)
557
+ {
558
+ nextTask.SetException(GetException());
559
+ }
560
+ else
561
+ {
562
+ var result = selector(this.Result);
563
+ nextTask.SetResult(result);
564
+ }
565
+ }
566
+ catch (Exception ex)
567
+ {
568
+ nextTask.SetException(ex);
569
+ }
570
+ });
571
+
572
+ return nextTask;
573
+ }
574
+
575
+ public BTask<TResult> Then<TResult>(Func<T, BTask<TResult>> selector)
576
+ {
577
+ var nextTask = new BTask<TResult>();
578
+
579
+ OnCompleted(() =>
580
+ {
581
+ try
582
+ {
583
+ if (IsFaulted)
584
+ {
585
+ nextTask.SetException(GetException());
586
+ }
587
+ else
588
+ {
589
+ var innerTask = selector(this.Result);
590
+ innerTask.OnCompleted(() =>
591
+ {
592
+ if (innerTask.IsFaulted)
593
+ {
594
+ nextTask.SetException(innerTask.GetException());
595
+ }
596
+ else
597
+ {
598
+ nextTask.SetResult(innerTask.Result);
599
+ }
600
+ });
601
+ }
602
+ }
603
+ catch (Exception ex)
604
+ {
605
+ nextTask.SetException(ex);
606
+ }
607
+ });
608
+
609
+ return nextTask;
610
+ }
611
+ }
612
+
613
+ public struct BTaskAwaiter : INotifyCompletion
614
+ {
615
+ private readonly BTask task;
616
+
617
+ public BTaskAwaiter(BTask task)
618
+ {
619
+ this.task = task;
620
+ }
621
+
622
+ public bool IsCompleted => task.IsCompleted;
623
+
624
+ public void GetResult()
625
+ {
626
+ if (task.IsFaulted)
627
+ {
628
+ throw task.GetException();
629
+ }
630
+ }
631
+
632
+ public void OnCompleted(Action continuation)
633
+ {
634
+ task.OnCompleted(continuation);
635
+ }
636
+ }
637
+
638
+ public struct BTaskAwaiter<T> : INotifyCompletion
639
+ {
640
+ private readonly BTask<T> task;
641
+
642
+ public BTaskAwaiter(BTask<T> task)
643
+ {
644
+ this.task = task;
645
+ }
646
+
647
+ public bool IsCompleted => task.IsCompleted;
648
+
649
+ public T GetResult()
650
+ {
651
+ return task.Result;
652
+ }
653
+
654
+ public void OnCompleted(Action continuation)
655
+ {
656
+ task.OnCompleted(continuation);
657
+ }
658
+ }
659
+
660
+ public class BTaskMethodBuilder
661
+ {
662
+ private BTask _task;
663
+
664
+ public static BTaskMethodBuilder Create()
665
+ {
666
+ return new BTaskMethodBuilder { _task = new BTask() };
667
+ }
668
+
669
+ public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine
670
+ {
671
+ stateMachine.MoveNext();
672
+ }
673
+
674
+ public void SetStateMachine(IAsyncStateMachine stateMachine) { }
675
+
676
+ public void SetResult()
677
+ {
678
+ _task.SetResult();
679
+ }
680
+
681
+ public void SetException(Exception exception)
682
+ {
683
+ _task.SetException(exception);
684
+ }
685
+
686
+ public BTask Task => _task;
687
+
688
+ public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
689
+ where TAwaiter : INotifyCompletion
690
+ where TStateMachine : IAsyncStateMachine
691
+ {
692
+ awaiter.OnCompleted(stateMachine.MoveNext);
693
+ }
694
+
695
+ public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
696
+ where TAwaiter : ICriticalNotifyCompletion
697
+ where TStateMachine : IAsyncStateMachine
698
+ {
699
+ awaiter.OnCompleted(stateMachine.MoveNext);
700
+ }
701
+ }
702
+
703
+ public class BTaskMethodBuilder<T>
704
+ {
705
+ private BTask<T> _task;
706
+
707
+ public static BTaskMethodBuilder<T> Create()
708
+ {
709
+ return new BTaskMethodBuilder<T> { _task = new BTask<T>() };
710
+ }
711
+
712
+ public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine
713
+ {
714
+ stateMachine.MoveNext();
715
+ }
716
+
717
+ public void SetStateMachine(IAsyncStateMachine stateMachine) { }
718
+
719
+ public void SetResult(T result)
720
+ {
721
+ _task.SetResult(result);
722
+ }
723
+
724
+ public void SetException(Exception exception)
725
+ {
726
+ _task.SetException(exception);
727
+ }
728
+
729
+ public BTask<T> Task => _task;
730
+
731
+ public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
732
+ where TAwaiter : INotifyCompletion
733
+ where TStateMachine : IAsyncStateMachine
734
+ {
735
+ awaiter.OnCompleted(stateMachine.MoveNext);
736
+ }
737
+
738
+ public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
739
+ where TAwaiter : ICriticalNotifyCompletion
740
+ where TStateMachine : IAsyncStateMachine
741
+ {
742
+ awaiter.OnCompleted(stateMachine.MoveNext);
743
+ }
744
+ }
745
+
746
+ public static class BTaskWebRequestExtensions
747
+ {
748
+ public static BTaskWebRequest GetWebRequestAsBTask(this UnityWebRequest request)
749
+ {
750
+ return new BTaskWebRequest(request);
751
+ }
752
+
753
+ public static BTaskWebRequest SendWebRequestAsBTask(this UnityWebRequest request, CancellationToken cancellationToken = default)
754
+ {
755
+ request.SendWebRequest();
756
+ return new BTaskWebRequest(request, cancellationToken);
757
+ }
758
+ }
759
+
760
+ public class BTaskWebRequest : BTask<UnityWebRequest>
761
+ {
762
+ private readonly UnityWebRequest webRequest;
763
+
764
+ public BTaskWebRequest(UnityWebRequest webRequest, CancellationToken cancellationToken = default) : base(cancellationToken)
765
+ {
766
+ this.webRequest = webRequest;
767
+
768
+ if (webRequest.isDone)
769
+ {
770
+ HandleCompletion();
771
+ }
772
+ else
773
+ {
774
+ StartPolling();
775
+ }
776
+
777
+ if (cancellationToken != default)
778
+ {
779
+ cancellationToken.Register(() =>
780
+ {
781
+ webRequest.Abort();
782
+ OnCanceled();
783
+ });
784
+ }
785
+ }
786
+
787
+ private void StartPolling()
788
+ {
789
+ void CheckCompletion()
790
+ {
791
+ if (webRequest.isDone)
792
+ {
793
+ HandleCompletion();
794
+ }
795
+ else if (!IsCanceled)
796
+ {
797
+ ScheduleContinuation(CheckCompletion);
798
+ }
799
+ }
800
+
801
+ ScheduleContinuation(CheckCompletion);
802
+ }
803
+
804
+ private void HandleCompletion()
805
+ {
806
+ if (webRequest.result == UnityWebRequest.Result.Success)
807
+ {
808
+ SetResult(webRequest);
809
+ }
810
+ else
811
+ {
812
+ var error = new UnityWebRequestException(
813
+ webRequest.error,
814
+ webRequest.responseCode,
815
+ webRequest.result
816
+ );
817
+ SetException(error);
818
+ }
819
+ }
820
+ }
821
+
822
+ public class UnityWebRequestException : Exception
823
+ {
824
+ public long ResponseCode { get; }
825
+ public UnityWebRequest.Result Result { get; }
826
+
827
+ public UnityWebRequestException(string message, long responseCode, UnityWebRequest.Result result)
828
+ : base($"WebRequest failed: {message} (Code: {responseCode}, Result: {result})")
829
+ {
830
+ ResponseCode = responseCode;
831
+ Result = result;
832
+ }
833
+ }
834
+
835
+ public static class BTaskAsyncOperationExtensions
836
+ {
837
+ public static BTaskAsyncOperation ToBTask(this AsyncOperation operation)
838
+ {
839
+ return new BTaskAsyncOperation(operation);
840
+ }
841
+ }
842
+
843
+ public class BTaskAsyncOperation : BTask<AsyncOperation>
844
+ {
845
+ private readonly AsyncOperation operation;
846
+
847
+ public BTaskAsyncOperation(AsyncOperation operation) : base()
848
+ {
849
+ this.operation = operation;
850
+
851
+ if (operation.isDone)
852
+ {
853
+ SetResult(operation);
854
+ }
855
+ else
856
+ {
857
+ operation.completed += OnCompleted;
858
+ }
859
+ }
860
+
861
+ private void OnCompleted(AsyncOperation op)
862
+ {
863
+ SetResult(op);
864
+ }
865
+ }
866
+
867
+ public class BTaskCompletionSource
868
+ {
869
+ private BTask _task;
870
+ private bool _completed = false;
871
+ private readonly object _lock = new object();
872
+
873
+ public BTaskCompletionSource()
874
+ {
875
+ _task = new BTask();
876
+ }
877
+
878
+ public BTask Task => _task;
879
+
880
+ public void SetResult()
881
+ {
882
+ lock (_lock)
883
+ {
884
+ if (_completed) return;
885
+ _completed = true;
886
+ _task.SetResult();
887
+ }
888
+ }
889
+
890
+ public void SetException(System.Exception exception)
891
+ {
892
+ lock (_lock)
893
+ {
894
+ if (_completed) return;
895
+ _completed = true;
896
+ _task.SetException(exception);
897
+ }
898
+ }
899
+
900
+ public void SetCanceled()
901
+ {
902
+ SetException(new System.OperationCanceledException());
903
+ }
904
+ }
905
+ }