SkipWhile.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the Apache 2.0 License.
  3. // See the LICENSE file in the project root for more information.
  4. using System.Collections.Generic;
  5. using System.Diagnostics;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8. namespace System.Linq
  9. {
  10. public static partial class AsyncEnumerable
  11. {
  12. public static IAsyncEnumerable<TSource> SkipWhile<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
  13. {
  14. if (source == null)
  15. throw Error.ArgumentNull(nameof(source));
  16. if (predicate == null)
  17. throw Error.ArgumentNull(nameof(predicate));
  18. #if USE_ASYNC_ITERATOR
  19. return Create(Core);
  20. async IAsyncEnumerator<TSource> Core(CancellationToken cancellationToken)
  21. {
  22. await using (var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false))
  23. {
  24. while (await e.MoveNextAsync())
  25. {
  26. var element = e.Current;
  27. if (!predicate(element))
  28. {
  29. yield return element;
  30. while (await e.MoveNextAsync())
  31. {
  32. yield return e.Current;
  33. }
  34. yield break;
  35. }
  36. }
  37. }
  38. }
  39. #else
  40. return new SkipWhileAsyncIterator<TSource>(source, predicate);
  41. #endif
  42. }
  43. public static IAsyncEnumerable<TSource> SkipWhile<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int, bool> predicate)
  44. {
  45. if (source == null)
  46. throw Error.ArgumentNull(nameof(source));
  47. if (predicate == null)
  48. throw Error.ArgumentNull(nameof(predicate));
  49. #if USE_ASYNC_ITERATOR
  50. return Create(Core);
  51. async IAsyncEnumerator<TSource> Core(CancellationToken cancellationToken)
  52. {
  53. await using (var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false))
  54. {
  55. var index = -1;
  56. while (await e.MoveNextAsync())
  57. {
  58. checked
  59. {
  60. index++;
  61. }
  62. var element = e.Current;
  63. if (!predicate(element, index))
  64. {
  65. yield return element;
  66. while (await e.MoveNextAsync())
  67. {
  68. yield return e.Current;
  69. }
  70. yield break;
  71. }
  72. }
  73. }
  74. }
  75. #else
  76. return new SkipWhileWithIndexAsyncIterator<TSource>(source, predicate);
  77. #endif
  78. }
  79. internal static IAsyncEnumerable<TSource> SkipWhileAwaitCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<bool>> predicate)
  80. {
  81. if (source == null)
  82. throw Error.ArgumentNull(nameof(source));
  83. if (predicate == null)
  84. throw Error.ArgumentNull(nameof(predicate));
  85. #if USE_ASYNC_ITERATOR
  86. return Create(Core);
  87. async IAsyncEnumerator<TSource> Core(CancellationToken cancellationToken)
  88. {
  89. await using (var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false))
  90. {
  91. while (await e.MoveNextAsync())
  92. {
  93. var element = e.Current;
  94. if (!await predicate(element).ConfigureAwait(false))
  95. {
  96. yield return element;
  97. while (await e.MoveNextAsync())
  98. {
  99. yield return e.Current;
  100. }
  101. yield break;
  102. }
  103. }
  104. }
  105. }
  106. #else
  107. return new SkipWhileAsyncIteratorWithTask<TSource>(source, predicate);
  108. #endif
  109. }
  110. #if !NO_DEEP_CANCELLATION
  111. internal static IAsyncEnumerable<TSource> SkipWhileAwaitWithCancellationCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<bool>> predicate)
  112. {
  113. if (source == null)
  114. throw Error.ArgumentNull(nameof(source));
  115. if (predicate == null)
  116. throw Error.ArgumentNull(nameof(predicate));
  117. #if USE_ASYNC_ITERATOR
  118. return Create(Core);
  119. async IAsyncEnumerator<TSource> Core(CancellationToken cancellationToken)
  120. {
  121. await using (var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false))
  122. {
  123. while (await e.MoveNextAsync())
  124. {
  125. var element = e.Current;
  126. if (!await predicate(element, cancellationToken).ConfigureAwait(false))
  127. {
  128. yield return element;
  129. while (await e.MoveNextAsync())
  130. {
  131. yield return e.Current;
  132. }
  133. yield break;
  134. }
  135. }
  136. }
  137. }
  138. #else
  139. return new SkipWhileAsyncIteratorWithTaskAndCancellation<TSource>(source, predicate);
  140. #endif
  141. }
  142. #endif
  143. internal static IAsyncEnumerable<TSource> SkipWhileAwaitCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int, ValueTask<bool>> predicate)
  144. {
  145. if (source == null)
  146. throw Error.ArgumentNull(nameof(source));
  147. if (predicate == null)
  148. throw Error.ArgumentNull(nameof(predicate));
  149. #if USE_ASYNC_ITERATOR
  150. return Create(Core);
  151. async IAsyncEnumerator<TSource> Core(CancellationToken cancellationToken)
  152. {
  153. await using (var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false))
  154. {
  155. var index = -1;
  156. while (await e.MoveNextAsync())
  157. {
  158. checked
  159. {
  160. index++;
  161. }
  162. var element = e.Current;
  163. if (!await predicate(element, index).ConfigureAwait(false))
  164. {
  165. yield return element;
  166. while (await e.MoveNextAsync())
  167. {
  168. yield return e.Current;
  169. }
  170. yield break;
  171. }
  172. }
  173. }
  174. }
  175. #else
  176. return new SkipWhileWithIndexAsyncIteratorWithTask<TSource>(source, predicate);
  177. #endif
  178. }
  179. #if !NO_DEEP_CANCELLATION
  180. internal static IAsyncEnumerable<TSource> SkipWhileAwaitWithCancellationCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int, CancellationToken, ValueTask<bool>> predicate)
  181. {
  182. if (source == null)
  183. throw Error.ArgumentNull(nameof(source));
  184. if (predicate == null)
  185. throw Error.ArgumentNull(nameof(predicate));
  186. #if USE_ASYNC_ITERATOR
  187. return Create(Core);
  188. async IAsyncEnumerator<TSource> Core(CancellationToken cancellationToken)
  189. {
  190. await using (var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false))
  191. {
  192. var index = -1;
  193. while (await e.MoveNextAsync())
  194. {
  195. checked
  196. {
  197. index++;
  198. }
  199. var element = e.Current;
  200. if (!await predicate(element, index, cancellationToken).ConfigureAwait(false))
  201. {
  202. yield return element;
  203. while (await e.MoveNextAsync())
  204. {
  205. yield return e.Current;
  206. }
  207. yield break;
  208. }
  209. }
  210. }
  211. }
  212. #else
  213. return new SkipWhileWithIndexAsyncIteratorWithTaskAndCancellation<TSource>(source, predicate);
  214. #endif
  215. }
  216. #endif
  217. #if !USE_ASYNC_ITERATOR
  218. private sealed class SkipWhileAsyncIterator<TSource> : AsyncIterator<TSource>
  219. {
  220. private readonly Func<TSource, bool> _predicate;
  221. private readonly IAsyncEnumerable<TSource> _source;
  222. private bool _doMoveNext;
  223. private IAsyncEnumerator<TSource> _enumerator;
  224. public SkipWhileAsyncIterator(IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
  225. {
  226. Debug.Assert(predicate != null);
  227. Debug.Assert(source != null);
  228. _source = source;
  229. _predicate = predicate;
  230. }
  231. public override AsyncIteratorBase<TSource> Clone()
  232. {
  233. return new SkipWhileAsyncIterator<TSource>(_source, _predicate);
  234. }
  235. public override async ValueTask DisposeAsync()
  236. {
  237. if (_enumerator != null)
  238. {
  239. await _enumerator.DisposeAsync().ConfigureAwait(false);
  240. _enumerator = null;
  241. }
  242. await base.DisposeAsync().ConfigureAwait(false);
  243. }
  244. protected override async ValueTask<bool> MoveNextCore()
  245. {
  246. switch (_state)
  247. {
  248. case AsyncIteratorState.Allocated:
  249. _enumerator = _source.GetAsyncEnumerator(_cancellationToken);
  250. // skip elements as requested
  251. while (await _enumerator.MoveNextAsync().ConfigureAwait(false))
  252. {
  253. var element = _enumerator.Current;
  254. if (!_predicate(element))
  255. {
  256. _doMoveNext = false;
  257. _state = AsyncIteratorState.Iterating;
  258. goto case AsyncIteratorState.Iterating;
  259. }
  260. }
  261. break;
  262. case AsyncIteratorState.Iterating:
  263. if (_doMoveNext && await _enumerator.MoveNextAsync().ConfigureAwait(false))
  264. {
  265. _current = _enumerator.Current;
  266. return true;
  267. }
  268. if (!_doMoveNext)
  269. {
  270. _current = _enumerator.Current;
  271. _doMoveNext = true;
  272. return true;
  273. }
  274. break;
  275. }
  276. await DisposeAsync().ConfigureAwait(false);
  277. return false;
  278. }
  279. }
  280. private sealed class SkipWhileWithIndexAsyncIterator<TSource> : AsyncIterator<TSource>
  281. {
  282. private readonly Func<TSource, int, bool> _predicate;
  283. private readonly IAsyncEnumerable<TSource> _source;
  284. private bool _doMoveNext;
  285. private IAsyncEnumerator<TSource> _enumerator;
  286. private int _index;
  287. public SkipWhileWithIndexAsyncIterator(IAsyncEnumerable<TSource> source, Func<TSource, int, bool> predicate)
  288. {
  289. Debug.Assert(predicate != null);
  290. Debug.Assert(source != null);
  291. _source = source;
  292. _predicate = predicate;
  293. }
  294. public override AsyncIteratorBase<TSource> Clone()
  295. {
  296. return new SkipWhileWithIndexAsyncIterator<TSource>(_source, _predicate);
  297. }
  298. public override async ValueTask DisposeAsync()
  299. {
  300. if (_enumerator != null)
  301. {
  302. await _enumerator.DisposeAsync().ConfigureAwait(false);
  303. _enumerator = null;
  304. }
  305. await base.DisposeAsync().ConfigureAwait(false);
  306. }
  307. protected override async ValueTask<bool> MoveNextCore()
  308. {
  309. switch (_state)
  310. {
  311. case AsyncIteratorState.Allocated:
  312. _enumerator = _source.GetAsyncEnumerator(_cancellationToken);
  313. _index = -1;
  314. // skip elements as requested
  315. while (await _enumerator.MoveNextAsync().ConfigureAwait(false))
  316. {
  317. var element = _enumerator.Current;
  318. checked
  319. {
  320. _index++;
  321. }
  322. if (!_predicate(element, _index))
  323. {
  324. _doMoveNext = false;
  325. _state = AsyncIteratorState.Iterating;
  326. goto case AsyncIteratorState.Iterating;
  327. }
  328. }
  329. break;
  330. case AsyncIteratorState.Iterating:
  331. if (_doMoveNext && await _enumerator.MoveNextAsync().ConfigureAwait(false))
  332. {
  333. _current = _enumerator.Current;
  334. return true;
  335. }
  336. if (!_doMoveNext)
  337. {
  338. _current = _enumerator.Current;
  339. _doMoveNext = true;
  340. return true;
  341. }
  342. break;
  343. }
  344. await DisposeAsync().ConfigureAwait(false);
  345. return false;
  346. }
  347. }
  348. private sealed class SkipWhileAsyncIteratorWithTask<TSource> : AsyncIterator<TSource>
  349. {
  350. private readonly Func<TSource, ValueTask<bool>> _predicate;
  351. private readonly IAsyncEnumerable<TSource> _source;
  352. private bool _doMoveNext;
  353. private IAsyncEnumerator<TSource> _enumerator;
  354. public SkipWhileAsyncIteratorWithTask(IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<bool>> predicate)
  355. {
  356. Debug.Assert(predicate != null);
  357. Debug.Assert(source != null);
  358. _source = source;
  359. _predicate = predicate;
  360. }
  361. public override AsyncIteratorBase<TSource> Clone()
  362. {
  363. return new SkipWhileAsyncIteratorWithTask<TSource>(_source, _predicate);
  364. }
  365. public override async ValueTask DisposeAsync()
  366. {
  367. if (_enumerator != null)
  368. {
  369. await _enumerator.DisposeAsync().ConfigureAwait(false);
  370. _enumerator = null;
  371. }
  372. await base.DisposeAsync().ConfigureAwait(false);
  373. }
  374. protected override async ValueTask<bool> MoveNextCore()
  375. {
  376. switch (_state)
  377. {
  378. case AsyncIteratorState.Allocated:
  379. _enumerator = _source.GetAsyncEnumerator(_cancellationToken);
  380. // skip elements as requested
  381. while (await _enumerator.MoveNextAsync().ConfigureAwait(false))
  382. {
  383. var element = _enumerator.Current;
  384. if (!await _predicate(element).ConfigureAwait(false))
  385. {
  386. _doMoveNext = false;
  387. _state = AsyncIteratorState.Iterating;
  388. goto case AsyncIteratorState.Iterating;
  389. }
  390. }
  391. break;
  392. case AsyncIteratorState.Iterating:
  393. if (_doMoveNext && await _enumerator.MoveNextAsync().ConfigureAwait(false))
  394. {
  395. _current = _enumerator.Current;
  396. return true;
  397. }
  398. if (!_doMoveNext)
  399. {
  400. _current = _enumerator.Current;
  401. _doMoveNext = true;
  402. return true;
  403. }
  404. break;
  405. }
  406. await DisposeAsync().ConfigureAwait(false);
  407. return false;
  408. }
  409. }
  410. #if !NO_DEEP_CANCELLATION
  411. private sealed class SkipWhileAsyncIteratorWithTaskAndCancellation<TSource> : AsyncIterator<TSource>
  412. {
  413. private readonly Func<TSource, CancellationToken, ValueTask<bool>> _predicate;
  414. private readonly IAsyncEnumerable<TSource> _source;
  415. private bool _doMoveNext;
  416. private IAsyncEnumerator<TSource> _enumerator;
  417. public SkipWhileAsyncIteratorWithTaskAndCancellation(IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<bool>> predicate)
  418. {
  419. Debug.Assert(predicate != null);
  420. Debug.Assert(source != null);
  421. _source = source;
  422. _predicate = predicate;
  423. }
  424. public override AsyncIteratorBase<TSource> Clone()
  425. {
  426. return new SkipWhileAsyncIteratorWithTaskAndCancellation<TSource>(_source, _predicate);
  427. }
  428. public override async ValueTask DisposeAsync()
  429. {
  430. if (_enumerator != null)
  431. {
  432. await _enumerator.DisposeAsync().ConfigureAwait(false);
  433. _enumerator = null;
  434. }
  435. await base.DisposeAsync().ConfigureAwait(false);
  436. }
  437. protected override async ValueTask<bool> MoveNextCore()
  438. {
  439. switch (_state)
  440. {
  441. case AsyncIteratorState.Allocated:
  442. _enumerator = _source.GetAsyncEnumerator(_cancellationToken);
  443. // skip elements as requested
  444. while (await _enumerator.MoveNextAsync().ConfigureAwait(false))
  445. {
  446. var element = _enumerator.Current;
  447. if (!await _predicate(element, _cancellationToken).ConfigureAwait(false))
  448. {
  449. _doMoveNext = false;
  450. _state = AsyncIteratorState.Iterating;
  451. goto case AsyncIteratorState.Iterating;
  452. }
  453. }
  454. break;
  455. case AsyncIteratorState.Iterating:
  456. if (_doMoveNext && await _enumerator.MoveNextAsync().ConfigureAwait(false))
  457. {
  458. _current = _enumerator.Current;
  459. return true;
  460. }
  461. if (!_doMoveNext)
  462. {
  463. _current = _enumerator.Current;
  464. _doMoveNext = true;
  465. return true;
  466. }
  467. break;
  468. }
  469. await DisposeAsync().ConfigureAwait(false);
  470. return false;
  471. }
  472. }
  473. #endif
  474. private sealed class SkipWhileWithIndexAsyncIteratorWithTask<TSource> : AsyncIterator<TSource>
  475. {
  476. private readonly Func<TSource, int, ValueTask<bool>> _predicate;
  477. private readonly IAsyncEnumerable<TSource> _source;
  478. private bool _doMoveNext;
  479. private IAsyncEnumerator<TSource> _enumerator;
  480. private int _index;
  481. public SkipWhileWithIndexAsyncIteratorWithTask(IAsyncEnumerable<TSource> source, Func<TSource, int, ValueTask<bool>> predicate)
  482. {
  483. Debug.Assert(predicate != null);
  484. Debug.Assert(source != null);
  485. _source = source;
  486. _predicate = predicate;
  487. }
  488. public override AsyncIteratorBase<TSource> Clone()
  489. {
  490. return new SkipWhileWithIndexAsyncIteratorWithTask<TSource>(_source, _predicate);
  491. }
  492. public override async ValueTask DisposeAsync()
  493. {
  494. if (_enumerator != null)
  495. {
  496. await _enumerator.DisposeAsync().ConfigureAwait(false);
  497. _enumerator = null;
  498. }
  499. await base.DisposeAsync().ConfigureAwait(false);
  500. }
  501. protected override async ValueTask<bool> MoveNextCore()
  502. {
  503. switch (_state)
  504. {
  505. case AsyncIteratorState.Allocated:
  506. _enumerator = _source.GetAsyncEnumerator(_cancellationToken);
  507. _index = -1;
  508. // skip elements as requested
  509. while (await _enumerator.MoveNextAsync().ConfigureAwait(false))
  510. {
  511. var element = _enumerator.Current;
  512. checked
  513. {
  514. _index++;
  515. }
  516. if (!await _predicate(element, _index).ConfigureAwait(false))
  517. {
  518. _doMoveNext = false;
  519. _state = AsyncIteratorState.Iterating;
  520. goto case AsyncIteratorState.Iterating;
  521. }
  522. }
  523. break;
  524. case AsyncIteratorState.Iterating:
  525. if (_doMoveNext && await _enumerator.MoveNextAsync().ConfigureAwait(false))
  526. {
  527. _current = _enumerator.Current;
  528. return true;
  529. }
  530. if (!_doMoveNext)
  531. {
  532. _current = _enumerator.Current;
  533. _doMoveNext = true;
  534. return true;
  535. }
  536. break;
  537. }
  538. await DisposeAsync().ConfigureAwait(false);
  539. return false;
  540. }
  541. }
  542. #if !NO_DEEP_CANCELLATION
  543. private sealed class SkipWhileWithIndexAsyncIteratorWithTaskAndCancellation<TSource> : AsyncIterator<TSource>
  544. {
  545. private readonly Func<TSource, int, CancellationToken, ValueTask<bool>> _predicate;
  546. private readonly IAsyncEnumerable<TSource> _source;
  547. private bool _doMoveNext;
  548. private IAsyncEnumerator<TSource> _enumerator;
  549. private int _index;
  550. public SkipWhileWithIndexAsyncIteratorWithTaskAndCancellation(IAsyncEnumerable<TSource> source, Func<TSource, int, CancellationToken, ValueTask<bool>> predicate)
  551. {
  552. Debug.Assert(predicate != null);
  553. Debug.Assert(source != null);
  554. _source = source;
  555. _predicate = predicate;
  556. }
  557. public override AsyncIteratorBase<TSource> Clone()
  558. {
  559. return new SkipWhileWithIndexAsyncIteratorWithTaskAndCancellation<TSource>(_source, _predicate);
  560. }
  561. public override async ValueTask DisposeAsync()
  562. {
  563. if (_enumerator != null)
  564. {
  565. await _enumerator.DisposeAsync().ConfigureAwait(false);
  566. _enumerator = null;
  567. }
  568. await base.DisposeAsync().ConfigureAwait(false);
  569. }
  570. protected override async ValueTask<bool> MoveNextCore()
  571. {
  572. switch (_state)
  573. {
  574. case AsyncIteratorState.Allocated:
  575. _enumerator = _source.GetAsyncEnumerator(_cancellationToken);
  576. _index = -1;
  577. // skip elements as requested
  578. while (await _enumerator.MoveNextAsync().ConfigureAwait(false))
  579. {
  580. var element = _enumerator.Current;
  581. checked
  582. {
  583. _index++;
  584. }
  585. if (!await _predicate(element, _index, _cancellationToken).ConfigureAwait(false))
  586. {
  587. _doMoveNext = false;
  588. _state = AsyncIteratorState.Iterating;
  589. goto case AsyncIteratorState.Iterating;
  590. }
  591. }
  592. break;
  593. case AsyncIteratorState.Iterating:
  594. if (_doMoveNext && await _enumerator.MoveNextAsync().ConfigureAwait(false))
  595. {
  596. _current = _enumerator.Current;
  597. return true;
  598. }
  599. if (!_doMoveNext)
  600. {
  601. _current = _enumerator.Current;
  602. _doMoveNext = true;
  603. return true;
  604. }
  605. break;
  606. }
  607. await DisposeAsync().ConfigureAwait(false);
  608. return false;
  609. }
  610. }
  611. #endif
  612. #endif
  613. }
  614. }