1 | | | import 'dart:math' as math; |
2 | | |
|
3 | | | import 'package:meta/meta.dart'; |
4 | | |
|
5 | | | import '../typedefs.dart'; |
6 | | |
|
7 | | | /// Wraps a `List<dynamic>` and a `Cast<E>` converter. Items in the list |
8 | | | /// are converted to `E` on demand i.e. when they are read by the program. |
9 | | | /// Conversion occurs only once for each item and the original `dynamic` item |
10 | | | /// is replaced with the conversion result. |
11 | | | @internal |
12 | | | class LazyInPlaceList<E> implements List<E> { |
13 | | 2 | LazyInPlaceList(this._data, this._cast); |
14 | | |
|
15 | | | final List<dynamic> _data; |
16 | | | final Cast<E> _cast; |
17 | | |
|
18 | | 1 | @override |
19 | | 1 | E get first => _get(0); |
20 | | |
|
21 | | 1 | @override |
22 | | 2 | set first(E value) => _data[0] = value; |
23 | | |
|
24 | | 1 | @override |
25 | | 2 | bool get isEmpty => _data.isEmpty; |
26 | | |
|
27 | | 1 | @override |
28 | | 2 | bool get isNotEmpty => _data.isNotEmpty; |
29 | | |
|
30 | | 1 | @override |
31 | | 2 | Iterator<E> get iterator => _iterate().iterator; |
32 | | |
|
33 | | 1 | @override |
34 | | 3 | E get last => _get(length - 1); |
35 | | |
|
36 | | 1 | @override |
37 | | 4 | set last(E value) => _data[length - 1] = value; |
38 | | |
|
39 | | 2 | @override |
40 | | 4 | int get length => _data.length; |
41 | | |
|
42 | | 1 | @override |
43 | | | set length(int value) { |
44 | | 2 | if (value > length) null as E; |
45 | | 2 | _data.length = value; |
46 | | | } |
47 | | |
|
48 | | 1 | @override |
49 | | | Iterable<E> get reversed sync* { |
50 | | 4 | for (var i = length - 1; i >= 0; i--) { |
51 | | 1 | yield _get(i); |
52 | | | } |
53 | | | } |
54 | | |
|
55 | | 1 | @override |
56 | | | E get single { |
57 | | 1 | if (isEmpty) throw _ListError.noElement(); |
58 | | 3 | if (length > 1) throw _ListError.tooMany(); |
59 | | 0 | return _get(0); |
60 | | | } |
61 | | |
|
62 | | 1 | @override |
63 | | | List<E> operator +(List<E> other) { |
64 | | 3 | final l = length, tl = l + other.length; |
65 | | 2 | if (tl == l) return toList(); |
66 | | 2 | final r = List<E>.filled(tl, other[0]); |
67 | | 2 | for (var i = 0; i < l; i++) { |
68 | | 2 | r[i] = _get(i); |
69 | | | } |
70 | | 1 | r.setRange(l, tl, other); |
71 | | | return r; |
72 | | | } |
73 | | |
|
74 | | 2 | @override |
75 | | 2 | E operator [](int index) => _get(index); |
76 | | |
|
77 | | 1 | @override |
78 | | 2 | void operator []=(int index, E value) => _data[index] = value; |
79 | | |
|
80 | | 1 | @override |
81 | | 2 | void add(E value) => _data.add(value); |
82 | | |
|
83 | | 1 | @override |
84 | | 2 | void addAll(Iterable<E> iterable) => _data.addAll(iterable); |
85 | | |
|
86 | | 2 | @override |
87 | | | bool any(bool Function(E element) test) { |
88 | | 2 | final l = length; |
89 | | 3 | for (var i = 0; i < l; i++) { |
90 | | 4 | if (test(_get(i))) return true; |
91 | | | } |
92 | | | return false; |
93 | | | } |
94 | | |
|
95 | | 1 | @override |
96 | | | Map<int, E> asMap() { |
97 | | 2 | final r = <int, E>{}, l = length; |
98 | | 2 | for (var i = 0; i < l; i++) { |
99 | | 2 | r[i] = _get(i); |
100 | | | } |
101 | | | return r; |
102 | | | } |
103 | | |
|
104 | | 1 | @override |
105 | | 2 | List<R> cast<R>() => _forceCast().cast<R>(); |
106 | | |
|
107 | | 1 | @override |
108 | | 2 | void clear() => _data.clear(); |
109 | | |
|
110 | | 2 | @override |
111 | | | bool contains(Object? element) { |
112 | | 2 | final l = length; |
113 | | 4 | for (var i = 0; i < l; i++) { |
114 | | 4 | if (element == _get(i)) return true; |
115 | | | } |
116 | | | return false; |
117 | | | } |
118 | | |
|
119 | | 1 | @override |
120 | | 1 | E elementAt(int index) => _get(index); |
121 | | |
|
122 | | 1 | @override |
123 | | | bool every(bool Function(E element) test) { |
124 | | 1 | final l = length; |
125 | | 2 | for (var i = 0; i < l; i++) { |
126 | | 2 | if (!test(_get(i))) return false; |
127 | | | } |
128 | | | return true; |
129 | | | } |
130 | | |
|
131 | | 1 | @override |
132 | | | Iterable<U> expand<U>(Iterable<U> Function(E element) toElements) sync* { |
133 | | 1 | final l = length; |
134 | | 2 | for (var i = 0; i < l; i++) { |
135 | | 2 | yield* toElements(_get(i)); |
136 | | | } |
137 | | | } |
138 | | |
|
139 | | 1 | @override |
140 | | | void fillRange(int start, int end, [E? fillValue]) => |
141 | | 2 | _data.fillRange(start, end, fillValue); |
142 | | |
|
143 | | 1 | @override |
144 | | | E firstWhere(bool Function(E element) test, {E Function()? orElse}) { |
145 | | 1 | final l = length; |
146 | | 2 | for (var i = 0; i < l; i++) { |
147 | | 1 | final v = _get(i); |
148 | | 1 | if (test(v)) return v; |
149 | | | } |
150 | | 1 | if (orElse != null) return orElse(); |
151 | | 1 | throw _ListError.noElement(); |
152 | | | } |
153 | | |
|
154 | | 1 | @override |
155 | | | U fold<U>(U initialValue, U Function(U previousValue, E element) combine) { |
156 | | 1 | final l = length; |
157 | | | U res = initialValue; |
158 | | 2 | for (var i = 0; i < l; i++) { |
159 | | 2 | res = combine(res, _get(i)); |
160 | | | } |
161 | | | return res; |
162 | | | } |
163 | | |
|
164 | | 1 | @override |
165 | | | Iterable<E> followedBy(Iterable<E> other) sync* { |
166 | | 1 | final l = length; |
167 | | 2 | for (var i = 0; i < l; i++) { |
168 | | 1 | yield _get(i); |
169 | | | } |
170 | | | yield* other; |
171 | | | } |
172 | | |
|
173 | | 1 | @override |
174 | | | void forEach(void Function(E element) action) { |
175 | | 1 | final l = length; |
176 | | 2 | for (var i = 0; i < l; i++) { |
177 | | 2 | action(_get(i)); |
178 | | | } |
179 | | | } |
180 | | |
|
181 | | 1 | @override |
182 | | | Iterable<E> getRange(int start, int end) sync* { |
183 | | 2 | RangeError.checkValidRange(start, end, length); |
184 | | 2 | for (var i = start; i < end; i++) { |
185 | | 1 | yield _get(i); |
186 | | | } |
187 | | | } |
188 | | |
|
189 | | 1 | @override |
190 | | | int indexOf(E element, [int start = 0]) { |
191 | | 1 | final l = length; |
192 | | 2 | for (var i = start; i < l; i++) { |
193 | | 2 | if (_get(i) == element) return i; |
194 | | | } |
195 | | 1 | return -1; |
196 | | | } |
197 | | |
|
198 | | 1 | @override |
199 | | | int indexWhere(bool Function(E element) test, [int start = 0]) { |
200 | | 1 | final l = length; |
201 | | 2 | for (var i = start; i < l; i++) { |
202 | | 2 | if (test(_get(i))) return i; |
203 | | | } |
204 | | 1 | return -1; |
205 | | | } |
206 | | |
|
207 | | 1 | @override |
208 | | 2 | void insert(int index, E element) => _data.insert(index, element); |
209 | | |
|
210 | | 1 | @override |
211 | | | void insertAll(int index, Iterable<E> iterable) => |
212 | | 2 | _data.insertAll(index, iterable); |
213 | | |
|
214 | | 1 | @override |
215 | | | String join([String separator = ""]) { |
216 | | 1 | final buffer = StringBuffer(); |
217 | | 1 | final l = length; |
218 | | 1 | if (l > 0) { |
219 | | 3 | buffer.write(_get(0).toString()); |
220 | | 2 | for (var i = 1; i < l; i++) { |
221 | | 1 | buffer.write(separator); |
222 | | 3 | buffer.write(_get(i).toString()); |
223 | | | } |
224 | | | } |
225 | | 1 | return buffer.toString(); |
226 | | | } |
227 | | |
|
228 | | 1 | @override |
229 | | | int lastIndexOf(E element, [int? start]) { |
230 | | 4 | for (var i = start ?? (length - 1); i >= 0; i--) { |
231 | | 2 | if (element == _get(i)) return i; |
232 | | | } |
233 | | 1 | return -1; |
234 | | | } |
235 | | |
|
236 | | 1 | @override |
237 | | | int lastIndexWhere(bool Function(E element) test, [int? start]) { |
238 | | 4 | for (var i = start ?? (length - 1); i >= 0; i--) { |
239 | | 2 | if (test(_get(i))) return i; |
240 | | | } |
241 | | 1 | return -1; |
242 | | | } |
243 | | |
|
244 | | 1 | @override |
245 | | | E lastWhere(bool Function(E element) test, {E Function()? orElse}) { |
246 | | 4 | for (var i = length - 1; i >= 0; i--) { |
247 | | 1 | final v = _get(i); |
248 | | 1 | if (test(v)) return v; |
249 | | | } |
250 | | 1 | if (orElse != null) return orElse(); |
251 | | 1 | throw _ListError.noElement(); |
252 | | | } |
253 | | |
|
254 | | 1 | @override |
255 | | | Iterable<U> map<U>(U Function(E e) toElement) sync* { |
256 | | 1 | final l = length; |
257 | | 2 | for (var i = 0; i < l; i++) { |
258 | | 2 | yield toElement(_get(i)); |
259 | | | } |
260 | | | } |
261 | | |
|
262 | | 1 | @override |
263 | | | E reduce(E Function(E value, E element) combine) { |
264 | | 1 | final l = length; |
265 | | 1 | if (l == 0) throw _ListError.noElement(); |
266 | | 1 | E res = _get(0); |
267 | | 2 | for (var i = 1; i < l; i++) { |
268 | | 2 | res = combine(res, _get(i)); |
269 | | | } |
270 | | | return res; |
271 | | | } |
272 | | |
|
273 | | 1 | @override |
274 | | 2 | bool remove(Object? value) => _data.remove(value); |
275 | | |
|
276 | | 1 | @override |
277 | | | E removeAt(int index) { |
278 | | 1 | final v = _get(index); |
279 | | 2 | _data.removeAt(index); |
280 | | | return v; |
281 | | | } |
282 | | |
|
283 | | 1 | @override |
284 | | | E removeLast() { |
285 | | 3 | final v = _get(length - 1); |
286 | | 2 | _data.removeLast(); |
287 | | | return v; |
288 | | | } |
289 | | |
|
290 | | 1 | @override |
291 | | 2 | void removeRange(int start, int end) => _data.removeRange(start, end); |
292 | | |
|
293 | | 1 | @override |
294 | | | void removeWhere(bool Function(E element) test) { |
295 | | 2 | var i = length - 1; |
296 | | 1 | while (i >= 0) { |
297 | | 2 | if (test(_get(i))) { |
298 | | 1 | final e = i + 1; |
299 | | 1 | i--; |
300 | | 3 | while (i >= 0 && test(_get(i))) { |
301 | | 1 | i--; |
302 | | | } |
303 | | 2 | removeRange(i + 1, e); |
304 | | | } else { |
305 | | 1 | i--; |
306 | | | } |
307 | | | } |
308 | | | } |
309 | | |
|
310 | | 1 | @override |
311 | | | void replaceRange(int start, int end, Iterable<E> replacements) => |
312 | | 2 | _data.replaceRange(start, end, replacements); |
313 | | |
|
314 | | 1 | @override |
315 | | | void retainWhere(bool Function(E element) test) => |
316 | | 3 | removeWhere((e) => !test(e)); |
317 | | |
|
318 | | 1 | @override |
319 | | 2 | void setAll(int index, Iterable<E> iterable) => _data.setAll(index, iterable); |
320 | | |
|
321 | | 1 | @override |
322 | | | void setRange(int start, int end, Iterable<E> iterable, |
323 | | | [int skipCount = 0]) => |
324 | | 2 | _data.setRange(start, end, iterable, skipCount); |
325 | | |
|
326 | | 1 | @override |
327 | | 2 | void shuffle([math.Random? random]) => _data.shuffle(random); |
328 | | |
|
329 | | 1 | @override |
330 | | | E singleWhere(bool Function(E element) test, {E Function()? orElse}) { |
331 | | | late E res; |
332 | | 1 | final l = length; |
333 | | | var found = false; |
334 | | 2 | for (var i = 0; i < l; i++) { |
335 | | 1 | final v = _get(i); |
336 | | 1 | if (test(v)) { |
337 | | 1 | if (found) throw _ListError.tooMany(); |
338 | | | found = true; |
339 | | | res = v; |
340 | | | } |
341 | | | } |
342 | | | if (found) return res; |
343 | | 1 | if (orElse != null) return orElse(); |
344 | | 1 | throw _ListError.noElement(); |
345 | | | } |
346 | | |
|
347 | | 1 | @override |
348 | | | Iterable<E> skip(int count) sync* { |
349 | | 1 | final l = length; |
350 | | 2 | for (var i = count; i < l; i++) { |
351 | | 1 | yield _get(i); |
352 | | | } |
353 | | | } |
354 | | |
|
355 | | 1 | @override |
356 | | | Iterable<E> skipWhile(bool Function(E value) test) sync* { |
357 | | | var i = 0; |
358 | | 1 | final l = length; |
359 | | 3 | while (i < l && test(_get(i))) { |
360 | | 1 | i++; |
361 | | | } |
362 | | 1 | while (i < l) { |
363 | | 1 | yield _get(i); |
364 | | 1 | i++; |
365 | | | } |
366 | | | } |
367 | | |
|
368 | | 1 | @override |
369 | | | void sort([int Function(E a, E b)? compare]) { |
370 | | 1 | _forceCast(); |
371 | | | if (compare == null) { |
372 | | 2 | final d = _data.cast<E>(); |
373 | | 1 | d.sort(); |
374 | | | } else { |
375 | | 4 | _data.sort((a, b) => compare(a as E, b as E)); |
376 | | | } |
377 | | | } |
378 | | |
|
379 | | 1 | @override |
380 | | | List<E> sublist(int start, [int? end]) => |
381 | | 3 | getRange(start, end ?? length).toList(); |
382 | | |
|
383 | | 1 | @override |
384 | | | Iterable<E> take(int count) sync* { |
385 | | 2 | final c = math.min(count, length); |
386 | | 2 | for (var i = 0; i < c; i++) { |
387 | | 1 | yield _get(i); |
388 | | | } |
389 | | | } |
390 | | |
|
391 | | 1 | @override |
392 | | | Iterable<E> takeWhile(bool Function(E value) test) sync* { |
393 | | 1 | final l = length; |
394 | | 2 | for (var i = 0; i < l; i++) { |
395 | | 1 | final v = _get(i); |
396 | | 1 | if (!test(v)) break; |
397 | | | yield v; |
398 | | | } |
399 | | | } |
400 | | |
|
401 | | 1 | @override |
402 | | | List<E> toList({bool growable = true}) { |
403 | | 1 | final l = length; |
404 | | 1 | if (l == 0) return growable ? [] : const []; |
405 | | 2 | final res = List.filled(l, _get(0), growable: growable); |
406 | | 2 | for (var i = 1; i < l; i++) { |
407 | | 2 | res[i] = _get(i); |
408 | | | } |
409 | | | return res; |
410 | | | } |
411 | | |
|
412 | | 1 | @override |
413 | | | Set<E> toSet() { |
414 | | 1 | final s = <E>{}, l = length; |
415 | | 2 | for (var i = 0; i < l; i++) { |
416 | | 2 | s.add(_get(i)); |
417 | | | } |
418 | | | return s; |
419 | | | } |
420 | | |
|
421 | | 1 | @override |
422 | | | String toString() { |
423 | | 1 | _forceCast(); |
424 | | 2 | return _data.toString(); |
425 | | | } |
426 | | |
|
427 | | 1 | @override |
428 | | | Iterable<E> where(bool Function(E element) test) sync* { |
429 | | 1 | final l = length; |
430 | | 2 | for (var i = 0; i < l; i++) { |
431 | | 1 | final v = _get(i); |
432 | | 1 | if (test(v)) yield v; |
433 | | | } |
434 | | | } |
435 | | |
|
436 | | 1 | @override |
437 | | | Iterable<U> whereType<U>() sync* { |
438 | | 1 | final l = length; |
439 | | 2 | for (var i = 0; i < l; i++) { |
440 | | 1 | final v = _get(i); |
441 | | 1 | if (v is U) yield v; |
442 | | | } |
443 | | | } |
444 | | |
|
445 | | 1 | List<dynamic> _forceCast() { |
446 | | 1 | final l = length; |
447 | | 2 | for (var i = 0; i < l; i++) { |
448 | | 1 | _get(i); |
449 | | | } |
450 | | 1 | return _data; |
451 | | | } |
452 | | |
|
453 | | 2 | E _get(int idx) { |
454 | | 4 | dynamic v = _data[idx]; |
455 | | 2 | if (v != null && v is! E) { |
456 | | 4 | v = _cast(v); |
457 | | 4 | _data[idx] = v; |
458 | | | } |
459 | | | return v; |
460 | | | } |
461 | | |
|
462 | | 1 | Iterable<E> _iterate() sync* { |
463 | | 1 | final l = length; |
464 | | 2 | for (var i = 0; i < l; i++) { |
465 | | 1 | yield _get(i); |
466 | | | } |
467 | | | } |
468 | | | } |
469 | | |
|
470 | | | // copied from dart-sdk\lib\internal\iterable.dart |
471 | | | sealed class _ListError { |
472 | | 2 | static StateError noElement() => StateError("No element"); |
473 | | 2 | static StateError tooMany() => StateError("Too many elements"); |
474 | | | } |