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