com.fofx.observething 1.0.0

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 (117) hide show
  1. package/README.md +2 -0
  2. package/README.md.meta +7 -0
  3. package/Runtime/CollectionIdProvider.cs +72 -0
  4. package/Runtime/CollectionIdProvider.cs.meta +2 -0
  5. package/Runtime/IObservable.cs +66 -0
  6. package/Runtime/IObservable.cs.meta +2 -0
  7. package/Runtime/Implementations/Observable.cs +30 -0
  8. package/Runtime/Implementations/Observable.cs.meta +2 -0
  9. package/Runtime/Implementations/ObservableBase.cs +173 -0
  10. package/Runtime/Implementations/ObservableBase.cs.meta +2 -0
  11. package/Runtime/Implementations/ObservableCollection.cs +141 -0
  12. package/Runtime/Implementations/ObservableCollection.cs.meta +2 -0
  13. package/Runtime/Implementations/ObservableDictionary.cs +166 -0
  14. package/Runtime/Implementations/ObservableDictionary.cs.meta +2 -0
  15. package/Runtime/Implementations/ObservableList.cs +163 -0
  16. package/Runtime/Implementations/ObservableList.cs.meta +2 -0
  17. package/Runtime/Implementations/ObservableSet.cs +137 -0
  18. package/Runtime/Implementations/ObservableSet.cs.meta +2 -0
  19. package/Runtime/Implementations/ObservableValue.cs +59 -0
  20. package/Runtime/Implementations/ObservableValue.cs.meta +2 -0
  21. package/Runtime/Implementations.meta +8 -0
  22. package/Runtime/Observables/BatchObservable.cs +72 -0
  23. package/Runtime/Observables/BatchObservable.cs.meta +2 -0
  24. package/Runtime/Observables/CastObservable.cs +128 -0
  25. package/Runtime/Observables/CastObservable.cs.meta +2 -0
  26. package/Runtime/Observables/CombineObservable.cs +96 -0
  27. package/Runtime/Observables/CombineObservable.cs.meta +2 -0
  28. package/Runtime/Observables/CombineValueObservable.cs +319 -0
  29. package/Runtime/Observables/CombineValueObservable.cs.meta +2 -0
  30. package/Runtime/Observables/ConcatObservable.cs +75 -0
  31. package/Runtime/Observables/ConcatObservable.cs.meta +2 -0
  32. package/Runtime/Observables/ContainsObservable.cs +71 -0
  33. package/Runtime/Observables/ContainsObservable.cs.meta +2 -0
  34. package/Runtime/Observables/CountObservable.cs +29 -0
  35. package/Runtime/Observables/CountObservable.cs.meta +2 -0
  36. package/Runtime/Observables/DistinctObservable.cs +55 -0
  37. package/Runtime/Observables/DistinctObservable.cs.meta +2 -0
  38. package/Runtime/Observables/FirstObservable.cs +53 -0
  39. package/Runtime/Observables/FirstObservable.cs.meta +2 -0
  40. package/Runtime/Observables/IndexOfObservable.cs +83 -0
  41. package/Runtime/Observables/IndexOfObservable.cs.meta +2 -0
  42. package/Runtime/Observables/OperationStreamObservable.cs +194 -0
  43. package/Runtime/Observables/OperationStreamObservable.cs.meta +2 -0
  44. package/Runtime/Observables/OrderByObservable.cs +116 -0
  45. package/Runtime/Observables/OrderByObservable.cs.meta +2 -0
  46. package/Runtime/Observables/SelectCollectionObservable.cs +29 -0
  47. package/Runtime/Observables/SelectCollectionObservable.cs.meta +2 -0
  48. package/Runtime/Observables/SelectListObservable.cs +29 -0
  49. package/Runtime/Observables/SelectListObservable.cs.meta +2 -0
  50. package/Runtime/Observables/SelectManyObservable.cs +78 -0
  51. package/Runtime/Observables/SelectManyObservable.cs.meta +2 -0
  52. package/Runtime/Observables/SelectValueObservable.cs +28 -0
  53. package/Runtime/Observables/SelectValueObservable.cs.meta +2 -0
  54. package/Runtime/Observables/SkipWhileObservable.cs +32 -0
  55. package/Runtime/Observables/SkipWhileObservable.cs.meta +2 -0
  56. package/Runtime/Observables/ThenObservable.cs +209 -0
  57. package/Runtime/Observables/ThenObservable.cs.meta +2 -0
  58. package/Runtime/Observables/ToDictionaryObservable.cs +35 -0
  59. package/Runtime/Observables/ToDictionaryObservable.cs.meta +2 -0
  60. package/Runtime/Observables/TrackObservable.cs +74 -0
  61. package/Runtime/Observables/TrackObservable.cs.meta +2 -0
  62. package/Runtime/Observables/UnwrapCollectionObservable.cs +64 -0
  63. package/Runtime/Observables/UnwrapCollectionObservable.cs.meta +2 -0
  64. package/Runtime/Observables/UnwrapListObservable.cs +69 -0
  65. package/Runtime/Observables/UnwrapListObservable.cs.meta +2 -0
  66. package/Runtime/Observables/UnwrapValueObservable.cs +56 -0
  67. package/Runtime/Observables/UnwrapValueObservable.cs.meta +2 -0
  68. package/Runtime/Observables/WhereObservable.cs +85 -0
  69. package/Runtime/Observables/WhereObservable.cs.meta +2 -0
  70. package/Runtime/Observables/WithPreviousObservable.cs +36 -0
  71. package/Runtime/Observables/WithPreviousObservable.cs.meta +2 -0
  72. package/Runtime/Observables.cs +467 -0
  73. package/Runtime/Observables.cs.meta +2 -0
  74. package/Runtime/Observables.meta +8 -0
  75. package/Runtime/ObservationContext.cs +126 -0
  76. package/Runtime/ObservationContext.cs.meta +2 -0
  77. package/Runtime/Observers.cs +403 -0
  78. package/Runtime/Observers.cs.meta +2 -0
  79. package/Runtime/Operators/BatchOperator.cs +71 -0
  80. package/Runtime/Operators/BatchOperator.cs.meta +2 -0
  81. package/Runtime/Operators/CollectionOperator.cs +30 -0
  82. package/Runtime/Operators/CollectionOperator.cs.meta +2 -0
  83. package/Runtime/Operators/DictionaryOperator.cs +45 -0
  84. package/Runtime/Operators/DictionaryOperator.cs.meta +2 -0
  85. package/Runtime/Operators/IInitializationOperationsProvider.cs +10 -0
  86. package/Runtime/Operators/IInitializationOperationsProvider.cs.meta +2 -0
  87. package/Runtime/Operators/ListOperator.cs +44 -0
  88. package/Runtime/Operators/ListOperator.cs.meta +2 -0
  89. package/Runtime/Operators/ObservableOperator.cs +75 -0
  90. package/Runtime/Operators/ObservableOperator.cs.meta +2 -0
  91. package/Runtime/Operators/Operator.cs +65 -0
  92. package/Runtime/Operators/Operator.cs.meta +2 -0
  93. package/Runtime/Operators/SetOperator.cs +44 -0
  94. package/Runtime/Operators/SetOperator.cs.meta +2 -0
  95. package/Runtime/Operators/ValueOperator.cs +30 -0
  96. package/Runtime/Operators/ValueOperator.cs.meta +2 -0
  97. package/Runtime/Operators.meta +8 -0
  98. package/Runtime/PriorityQueue.cs +1096 -0
  99. package/Runtime/PriorityQueue.cs.meta +2 -0
  100. package/Runtime/com.fofx.observething.asmdef +14 -0
  101. package/Runtime/com.fofx.observething.asmdef.meta +7 -0
  102. package/Runtime.meta +8 -0
  103. package/Tests/CollectionObservableTests.cs +739 -0
  104. package/Tests/CollectionObservableTests.cs.meta +2 -0
  105. package/Tests/DictionaryObservableTests.cs +85 -0
  106. package/Tests/DictionaryObservableTests.cs.meta +2 -0
  107. package/Tests/ListObservableTests.cs +148 -0
  108. package/Tests/ListObservableTests.cs.meta +2 -0
  109. package/Tests/ObservationContextTests.cs +359 -0
  110. package/Tests/ObservationContextTests.cs.meta +2 -0
  111. package/Tests/ValueObservableTests.cs +322 -0
  112. package/Tests/ValueObservableTests.cs.meta +2 -0
  113. package/Tests/com.fofx.observething.tests.asmdef +24 -0
  114. package/Tests/com.fofx.observething.tests.asmdef.meta +7 -0
  115. package/Tests.meta +8 -0
  116. package/package.json +24 -0
  117. package/package.json.meta +7 -0
@@ -0,0 +1,319 @@
1
+ using System;
2
+
3
+ namespace ObserveThing
4
+ {
5
+ public class CombineValueObservable<T1, T2> : IDisposable
6
+ {
7
+ private ObservableValue<(T1, T2)> _operand;
8
+ private IDisposable _subscriptions;
9
+
10
+ public CombineValueObservable(IValueObservable<T1> source1, IValueObservable<T2> source2, ObservableValue<(T1, T2)> operand)
11
+ {
12
+ _operand = operand;
13
+ _subscriptions = new ComposedDisposable(
14
+
15
+ source1.Subscribe(
16
+ onNext: x => operand.value = new(x, operand.value.Item2),
17
+ onError: operand.OnError,
18
+ onDispose: Dispose,
19
+ immediate: true
20
+ ),
21
+
22
+ source2.Subscribe(
23
+ onNext: x => operand.value = new(operand.value.Item1, x),
24
+ onError: operand.OnError,
25
+ onDispose: Dispose,
26
+ immediate: true
27
+ )
28
+
29
+ );
30
+ }
31
+
32
+ public void Dispose()
33
+ {
34
+ _subscriptions?.Dispose();
35
+ _subscriptions = null;
36
+ _operand.Dispose();
37
+ }
38
+ }
39
+
40
+ public class CombineValueObservable<T1, T2, T3> : IDisposable
41
+ {
42
+ private ObservableValue<(T1, T2, T3)> _operand;
43
+ private IDisposable _subscriptions;
44
+
45
+ public CombineValueObservable(IValueObservable<T1> source1, IValueObservable<T2> source2, IValueObservable<T3> source3, ObservableValue<(T1, T2, T3)> operand)
46
+ {
47
+ _operand = operand;
48
+ _subscriptions = new ComposedDisposable(
49
+
50
+ source1.Subscribe(
51
+ onNext: x => operand.value = new(x, operand.value.Item2, operand.value.Item3),
52
+ onError: operand.OnError,
53
+ onDispose: Dispose,
54
+ immediate: true
55
+ ),
56
+
57
+ source2.Subscribe(
58
+ onNext: x => operand.value = new(operand.value.Item1, x, operand.value.Item3),
59
+ onError: operand.OnError,
60
+ onDispose: Dispose,
61
+ immediate: true
62
+ ),
63
+
64
+ source3.Subscribe(
65
+ onNext: x => operand.value = new(operand.value.Item1, operand.value.Item2, x),
66
+ onError: operand.OnError,
67
+ onDispose: Dispose,
68
+ immediate: true
69
+ )
70
+
71
+ );
72
+ }
73
+
74
+ public void Dispose()
75
+ {
76
+ _subscriptions?.Dispose();
77
+ _subscriptions = null;
78
+ _operand.Dispose();
79
+ }
80
+ }
81
+
82
+ public class CombineValueObservable<T1, T2, T3, T4> : IDisposable
83
+ {
84
+ private ObservableValue<(T1, T2, T3, T4)> _operand;
85
+ private IDisposable _subscriptions;
86
+
87
+ public CombineValueObservable(IValueObservable<T1> source1, IValueObservable<T2> source2, IValueObservable<T3> source3, IValueObservable<T4> source4, ObservableValue<(T1, T2, T3, T4)> operand)
88
+ {
89
+ _operand = operand;
90
+ _subscriptions = new ComposedDisposable(
91
+
92
+ source1.Subscribe(
93
+ onNext: x => operand.value = new(x, operand.value.Item2, operand.value.Item3, operand.value.Item4),
94
+ onError: operand.OnError,
95
+ onDispose: Dispose,
96
+ immediate: true
97
+ ),
98
+
99
+ source2.Subscribe(
100
+ onNext: x => operand.value = new(operand.value.Item1, x, operand.value.Item3, operand.value.Item4),
101
+ onError: operand.OnError,
102
+ onDispose: Dispose,
103
+ immediate: true
104
+ ),
105
+
106
+ source3.Subscribe(
107
+ onNext: x => operand.value = new(operand.value.Item1, operand.value.Item2, x, operand.value.Item4),
108
+ onError: operand.OnError,
109
+ onDispose: Dispose,
110
+ immediate: true
111
+ ),
112
+
113
+ source4.Subscribe(
114
+ onNext: x => operand.value = new(operand.value.Item1, operand.value.Item2, operand.value.Item3, x),
115
+ onError: operand.OnError,
116
+ onDispose: Dispose,
117
+ immediate: true
118
+ )
119
+
120
+ );
121
+ }
122
+
123
+ public void Dispose()
124
+ {
125
+ _subscriptions?.Dispose();
126
+ _subscriptions = null;
127
+ _operand.Dispose();
128
+ }
129
+ }
130
+
131
+ public class CombineValueObservable<T1, T2, T3, T4, T5> : IDisposable
132
+ {
133
+ private ObservableValue<(T1, T2, T3, T4, T5)> _operand;
134
+ private IDisposable _subscriptions;
135
+
136
+ public CombineValueObservable(IValueObservable<T1> source1, IValueObservable<T2> source2, IValueObservable<T3> source3, IValueObservable<T4> source4, IValueObservable<T5> source5, ObservableValue<(T1, T2, T3, T4, T5)> operand)
137
+ {
138
+ _operand = operand;
139
+ _subscriptions = new ComposedDisposable(
140
+
141
+ source1.Subscribe(
142
+ onNext: x => operand.value = new(x, operand.value.Item2, operand.value.Item3, operand.value.Item4, operand.value.Item5),
143
+ onError: operand.OnError,
144
+ onDispose: Dispose,
145
+ immediate: true
146
+ ),
147
+
148
+ source2.Subscribe(
149
+ onNext: x => operand.value = new(operand.value.Item1, x, operand.value.Item3, operand.value.Item4, operand.value.Item5),
150
+ onError: operand.OnError,
151
+ onDispose: Dispose,
152
+ immediate: true
153
+ ),
154
+
155
+ source3.Subscribe(
156
+ onNext: x => operand.value = new(operand.value.Item1, operand.value.Item2, x, operand.value.Item4, operand.value.Item5),
157
+ onError: operand.OnError,
158
+ onDispose: Dispose,
159
+ immediate: true
160
+ ),
161
+
162
+ source4.Subscribe(
163
+ onNext: x => operand.value = new(operand.value.Item1, operand.value.Item2, operand.value.Item3, x, operand.value.Item5),
164
+ onError: operand.OnError,
165
+ onDispose: Dispose,
166
+ immediate: true
167
+ ),
168
+
169
+ source5.Subscribe(
170
+ onNext: x => operand.value = new(operand.value.Item1, operand.value.Item2, operand.value.Item3, operand.value.Item4, x),
171
+ onError: operand.OnError,
172
+ onDispose: Dispose,
173
+ immediate: true
174
+ )
175
+
176
+ );
177
+ }
178
+
179
+ public void Dispose()
180
+ {
181
+ _subscriptions?.Dispose();
182
+ _subscriptions = null;
183
+ _operand.Dispose();
184
+ }
185
+ }
186
+
187
+ public class CombineValueObservable<T1, T2, T3, T4, T5, T6> : IDisposable
188
+ {
189
+ private ObservableValue<(T1, T2, T3, T4, T5, T6)> _operand;
190
+ private IDisposable _subscriptions;
191
+
192
+ public CombineValueObservable(IValueObservable<T1> source1, IValueObservable<T2> source2, IValueObservable<T3> source3, IValueObservable<T4> source4, IValueObservable<T5> source5, IValueObservable<T6> source6, ObservableValue<(T1, T2, T3, T4, T5, T6)> operand)
193
+ {
194
+ _operand = operand;
195
+ _subscriptions = new ComposedDisposable(
196
+
197
+ source1.Subscribe(
198
+ onNext: x => operand.value = new(x, operand.value.Item2, operand.value.Item3, operand.value.Item4, operand.value.Item5, operand.value.Item6),
199
+ onError: operand.OnError,
200
+ onDispose: Dispose,
201
+ immediate: true
202
+ ),
203
+
204
+ source2.Subscribe(
205
+ onNext: x => operand.value = new(operand.value.Item1, x, operand.value.Item3, operand.value.Item4, operand.value.Item5, operand.value.Item6),
206
+ onError: operand.OnError,
207
+ onDispose: Dispose,
208
+ immediate: true
209
+ ),
210
+
211
+ source3.Subscribe(
212
+ onNext: x => operand.value = new(operand.value.Item1, operand.value.Item2, x, operand.value.Item4, operand.value.Item5, operand.value.Item6),
213
+ onError: operand.OnError,
214
+ onDispose: Dispose,
215
+ immediate: true
216
+ ),
217
+
218
+ source4.Subscribe(
219
+ onNext: x => operand.value = new(operand.value.Item1, operand.value.Item2, operand.value.Item3, x, operand.value.Item5, operand.value.Item6),
220
+ onError: operand.OnError,
221
+ onDispose: Dispose,
222
+ immediate: true
223
+ ),
224
+
225
+ source5.Subscribe(
226
+ onNext: x => operand.value = new(operand.value.Item1, operand.value.Item2, operand.value.Item3, operand.value.Item4, x, operand.value.Item6),
227
+ onError: operand.OnError,
228
+ onDispose: Dispose,
229
+ immediate: true
230
+ ),
231
+
232
+ source6.Subscribe(
233
+ onNext: x => operand.value = new(operand.value.Item1, operand.value.Item2, operand.value.Item3, operand.value.Item4, operand.value.Item5, x),
234
+ onError: operand.OnError,
235
+ onDispose: Dispose,
236
+ immediate: true
237
+ )
238
+
239
+ );
240
+ }
241
+
242
+ public void Dispose()
243
+ {
244
+ _subscriptions?.Dispose();
245
+ _subscriptions = null;
246
+ _operand.Dispose();
247
+ }
248
+ }
249
+
250
+ public class CombineValueObservable<T1, T2, T3, T4, T5, T6, T7> : IDisposable
251
+ {
252
+ private ObservableValue<(T1, T2, T3, T4, T5, T6, T7)> _operand;
253
+ private IDisposable _subscriptions;
254
+
255
+ public CombineValueObservable(IValueObservable<T1> source1, IValueObservable<T2> source2, IValueObservable<T3> source3, IValueObservable<T4> source4, IValueObservable<T5> source5, IValueObservable<T6> source6, IValueObservable<T7> source7, ObservableValue<(T1, T2, T3, T4, T5, T6, T7)> operand)
256
+ {
257
+ _operand = operand;
258
+ _subscriptions = new ComposedDisposable(
259
+
260
+ source1.Subscribe(
261
+ onNext: x => operand.value = new(x, operand.value.Item2, operand.value.Item3, operand.value.Item4, operand.value.Item5, operand.value.Item6, operand.value.Item7),
262
+ onError: operand.OnError,
263
+ onDispose: Dispose,
264
+ immediate: true
265
+ ),
266
+
267
+ source2.Subscribe(
268
+ onNext: x => operand.value = new(operand.value.Item1, x, operand.value.Item3, operand.value.Item4, operand.value.Item5, operand.value.Item6, operand.value.Item7),
269
+ onError: operand.OnError,
270
+ onDispose: Dispose,
271
+ immediate: true
272
+ ),
273
+
274
+ source3.Subscribe(
275
+ onNext: x => operand.value = new(operand.value.Item1, operand.value.Item2, x, operand.value.Item4, operand.value.Item5, operand.value.Item6, operand.value.Item7),
276
+ onError: operand.OnError,
277
+ onDispose: Dispose,
278
+ immediate: true
279
+ ),
280
+
281
+ source4.Subscribe(
282
+ onNext: x => operand.value = new(operand.value.Item1, operand.value.Item2, operand.value.Item3, x, operand.value.Item5, operand.value.Item6, operand.value.Item7),
283
+ onError: operand.OnError,
284
+ onDispose: Dispose,
285
+ immediate: true
286
+ ),
287
+
288
+ source5.Subscribe(
289
+ onNext: x => operand.value = new(operand.value.Item1, operand.value.Item2, operand.value.Item3, operand.value.Item4, x, operand.value.Item6, operand.value.Item7),
290
+ onError: operand.OnError,
291
+ onDispose: Dispose,
292
+ immediate: true
293
+ ),
294
+
295
+ source6.Subscribe(
296
+ onNext: x => operand.value = new(operand.value.Item1, operand.value.Item2, operand.value.Item3, operand.value.Item4, operand.value.Item5, x, operand.value.Item7),
297
+ onError: operand.OnError,
298
+ onDispose: Dispose,
299
+ immediate: true
300
+ ),
301
+
302
+ source7.Subscribe(
303
+ onNext: x => operand.value = new(operand.value.Item1, operand.value.Item2, operand.value.Item3, operand.value.Item4, operand.value.Item5, operand.value.Item6, x),
304
+ onError: operand.OnError,
305
+ onDispose: Dispose,
306
+ immediate: true
307
+ )
308
+
309
+ );
310
+ }
311
+
312
+ public void Dispose()
313
+ {
314
+ _subscriptions?.Dispose();
315
+ _subscriptions = null;
316
+ _operand.Dispose();
317
+ }
318
+ }
319
+ }
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: 874d12647ce3e0c4d9391a224a9c1a44
@@ -0,0 +1,75 @@
1
+ using System;
2
+ using System.Collections.Generic;
3
+
4
+ namespace ObserveThing
5
+ {
6
+ public class ConcatObservable<T> : IDisposable
7
+ {
8
+ private ObservableCollection<T> _operand;
9
+ private CollectionIdProvider _idProvider;
10
+ private Dictionary<uint, uint> _source1IdMap = new Dictionary<uint, uint>();
11
+ private Dictionary<uint, uint> _source2IdMap = new Dictionary<uint, uint>();
12
+
13
+ private IDisposable _subscription;
14
+
15
+ public ConcatObservable(ICollectionObservable<T> source1, ICollectionObservable<T> source2, ObservableCollection<T> operand)
16
+ {
17
+ _idProvider = new CollectionIdProvider(x => !_source1IdMap.ContainsValue(x) && !_source2IdMap.ContainsValue(x));
18
+ _operand = operand;
19
+ _subscription = new ComposedDisposable(
20
+
21
+ source1.SubscribeWithId(
22
+ onAdd: Source1HandleAdd,
23
+ onRemove: Source1HandleRemove,
24
+ onError: _operand.OnError,
25
+ onDispose: Dispose,
26
+ immediate: true
27
+ ),
28
+
29
+ source2.SubscribeWithId(
30
+ onAdd: Source2HandleAdd,
31
+ onRemove: Source2HandleRemove,
32
+ onError: _operand.OnError,
33
+ onDispose: Dispose,
34
+ immediate: true
35
+ )
36
+
37
+ );
38
+ }
39
+
40
+ private void Source1HandleAdd(uint id, T value)
41
+ {
42
+ var newId = _idProvider.GetUnusedId();
43
+ _source1IdMap.Add(id, newId);
44
+ _operand.Add(newId, value);
45
+ }
46
+
47
+ private void Source1HandleRemove(uint id, T value)
48
+ {
49
+ var newId = _source1IdMap[id];
50
+ _source1IdMap.Remove(id);
51
+ _operand.Remove(newId);
52
+ }
53
+
54
+ private void Source2HandleAdd(uint id, T value)
55
+ {
56
+ var newId = _idProvider.GetUnusedId();
57
+ _source2IdMap.Add(id, newId);
58
+ _operand.Add(newId, value);
59
+ }
60
+
61
+ private void Source2HandleRemove(uint id, T value)
62
+ {
63
+ var newId = _source2IdMap[id];
64
+ _source2IdMap.Remove(id);
65
+ _operand.Remove(newId);
66
+ }
67
+
68
+ public void Dispose()
69
+ {
70
+ _subscription?.Dispose();
71
+ _subscription = null;
72
+ _operand.Dispose();
73
+ }
74
+ }
75
+ }
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: da034c02eb7fbd24aa52343dd5d2eca9
@@ -0,0 +1,71 @@
1
+ using System;
2
+ using System.Collections.Generic;
3
+
4
+ namespace ObserveThing
5
+ {
6
+ public class ContainsObservable<T> : IDisposable
7
+ {
8
+ private ObservableValue<bool> _operand;
9
+ private List<T> _list = new List<T>();
10
+ private T _latest = default;
11
+ private IDisposable _subscriptions;
12
+
13
+ public ContainsObservable(ICollectionObservable<T> source, IValueObservable<T> value, ObservableValue<bool> operand)
14
+ {
15
+ _operand = operand;
16
+ _subscriptions = new ComposedDisposable(
17
+
18
+ source.Subscribe(
19
+ onAdd: HandleAdd,
20
+ onRemove: HandleRemove,
21
+ onError: _operand.OnError,
22
+ onDispose: Dispose,
23
+ immediate: true
24
+ ),
25
+
26
+ value.Subscribe(
27
+ onNext: HandleNext,
28
+ onError: _operand.OnError,
29
+ onDispose: Dispose,
30
+ immediate: true
31
+ )
32
+
33
+ );
34
+ }
35
+
36
+ private void HandleAdd(T element)
37
+ {
38
+ _list.Add(element);
39
+
40
+ if (_operand.value)
41
+ return;
42
+
43
+ if (Equals(element, _latest))
44
+ _operand.value = true;
45
+ }
46
+
47
+ private void HandleRemove(T element)
48
+ {
49
+ _list.Remove(element);
50
+
51
+ if (!_operand.value)
52
+ return;
53
+
54
+ if (Equals(element, _latest) && !_list.Contains(element))
55
+ _operand.value = false;
56
+ }
57
+
58
+ private void HandleNext(T value)
59
+ {
60
+ _latest = value;
61
+ _operand.value = _list.Contains(value);
62
+ }
63
+
64
+ public void Dispose()
65
+ {
66
+ _subscriptions?.Dispose();
67
+ _subscriptions = null;
68
+ _operand.Dispose();
69
+ }
70
+ }
71
+ }
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: 8007fd4897c313b408cb6a42f4583fe8
@@ -0,0 +1,29 @@
1
+ using System;
2
+
3
+ namespace ObserveThing
4
+ {
5
+ public class CountObservable<T> : IDisposable
6
+ {
7
+ private ObservableValue<int> _operand;
8
+ private IDisposable _subscriptions;
9
+
10
+ public CountObservable(ICollectionObservable<T> source, ObservableValue<int> operand)
11
+ {
12
+ _operand = operand;
13
+ _subscriptions = source.Subscribe(
14
+ onAdd: _ => operand.value = operand.value + 1,
15
+ onRemove: _ => operand.value = operand.value - 1,
16
+ onError: operand.OnError,
17
+ onDispose: Dispose,
18
+ immediate: true
19
+ );
20
+ }
21
+
22
+ public void Dispose()
23
+ {
24
+ _subscriptions?.Dispose();
25
+ _subscriptions = null;
26
+ _operand.Dispose();
27
+ }
28
+ }
29
+ }
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: 453d787470b6b564da4b522d2a6741e1
@@ -0,0 +1,55 @@
1
+ using System;
2
+ using System.Collections.Generic;
3
+
4
+ namespace ObserveThing
5
+ {
6
+ public class DistinctObservable<T> : IDisposable
7
+ {
8
+ private ObservableSet<T> _operand;
9
+ private Dictionary<T, int> _countByElement = new Dictionary<T, int>();
10
+ private IDisposable _subscriptions;
11
+
12
+ public DistinctObservable(ICollectionObservable<T> source, ObservableSet<T> operand)
13
+ {
14
+ _operand = operand;
15
+ _subscriptions = source.Subscribe(
16
+ onAdd: HandleAdd,
17
+ onRemove: HandleRemove,
18
+ onError: _operand.OnError,
19
+ onDispose: Dispose,
20
+ immediate: true
21
+ );
22
+ }
23
+
24
+ private void HandleAdd(T value)
25
+ {
26
+ bool isNew = !_countByElement.TryGetValue(value, out var count);
27
+ _countByElement[value] = count + 1;
28
+
29
+ if (isNew)
30
+ _operand.Add(value);
31
+ }
32
+
33
+ private void HandleRemove(T value)
34
+ {
35
+ var count = _countByElement[value];
36
+
37
+ if (count > 1)
38
+ {
39
+ _countByElement[value] = count - 1;
40
+ }
41
+ else
42
+ {
43
+ _countByElement.Remove(value);
44
+ _operand.Remove(value);
45
+ }
46
+ }
47
+
48
+ public void Dispose()
49
+ {
50
+ _subscriptions?.Dispose();
51
+ _subscriptions = null;
52
+ _operand.Dispose();
53
+ }
54
+ }
55
+ }
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: 7863e890c2633d14bafff06edee0e7c6
@@ -0,0 +1,53 @@
1
+ using System;
2
+ using System.Collections.Generic;
3
+
4
+ namespace ObserveThing
5
+ {
6
+ public class FirstObservable<T> : IDisposable
7
+ {
8
+ private ObservableValue<(bool found, T value)> _operand;
9
+ private List<(uint id, T value)> _sortedList = new List<(uint id, T value)>();
10
+ private (uint id, T value) _latest;
11
+ private IDisposable _subscriptions;
12
+
13
+ public FirstObservable(ICollectionObservable<T> source, Func<T, IValueObservable<bool>> validate, ObservableValue<(bool found, T value)> operand)
14
+ {
15
+ _operand = operand;
16
+ _subscriptions = source.ObservableWhere(x => validate(x)).SubscribeWithId(
17
+ onAdd: (id, value) =>
18
+ {
19
+ _sortedList.Add(new(id, value));
20
+ _sortedList.Sort((x, y) => x.id.CompareTo(y.id));
21
+ SetValueIfNecessary();
22
+ },
23
+ onRemove: (id, value) =>
24
+ {
25
+ _sortedList.Remove(new(id, value));
26
+ SetValueIfNecessary();
27
+ },
28
+ onError: operand.OnError,
29
+ onDispose: Dispose,
30
+ immediate: true
31
+ );
32
+ }
33
+
34
+ private void SetValueIfNecessary()
35
+ {
36
+ bool found = _sortedList.Count != 0;
37
+ var next = _sortedList.Count == 0 ? new(0, default) : _sortedList[0];
38
+
39
+ if (_latest.id == next.id && Equals(_latest.value, next.value))
40
+ return;
41
+
42
+ _latest = next;
43
+ _operand.value = new(found, _latest.value);
44
+ }
45
+
46
+ public void Dispose()
47
+ {
48
+ _subscriptions?.Dispose();
49
+ _subscriptions = null;
50
+ _operand.Dispose();
51
+ }
52
+ }
53
+ }
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: d856828e138849849bd98637c57b9534