| 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 | | | } |