Take.cs (4097B)
1 using Std.Convert; 2 using Std.Maybe; 3 using Std.Ops; 4 using Std.Result; 5 using System; 6 using System.Runtime.InteropServices; 7 #region Namespaces 8 namespace Std.Iter { 9 #region Types 10 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 0)] 11 public struct Take<T, TIter>: IInto<Take<T, TIter>>, IIterator<T> where T: notnull where TIter: notnull, IIterator<T> { 12 13 #region Type-level Constructors 14 #endregion 15 16 #region Instance Constructors 17 public Take() => throw new InvalidOperationException("Parameterless constructor is not allowed to be called!"); 18 internal Take(TIter iter, ulong n) => (_iter, _n) = (iter, n); 19 #endregion 20 21 #region Type-level Fields 22 #endregion 23 24 #region Instance Fields 25 ulong _n; 26 [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0044:Add readonly modifier", Justification = "Can't be readonly since we call mutable methods on it.")] 27 TIter _iter; 28 #endregion 29 30 #region Type-level Properties 31 #endregion 32 33 #region Instance Properties 34 #endregion 35 36 #region Type-level Functions 37 #endregion 38 39 #region Instance Functions 40 public Result<Unit, ulong> AdvanceBy(ulong n) { 41 42 if (_n >= n) { 43 _n -= n; 44 return _iter.AdvanceBy(n); 45 } else if (_n == ulong.MinValue) { 46 return new(ulong.MinValue); 47 } else { 48 var res = _iter.AdvanceBy(_n); 49 n = _n; 50 _n = ulong.MinValue; 51 return res.IsErr ? res : new(n); 52 } 53 } 54 public ulong Count() => IIterator<T>.CountDefault(ref this); 55 public override readonly bool Equals(object? _) => false; 56 public TInit Fold<TInit>(TInit init, Fn<TInit, T, TInit> f) where TInit: notnull { 57 58 static Fn<TInit, T, Result<TInit, Bottom>> fn(Fn<TInit, T, TInit> g) => (acc, x) => new(g(acc, x)); 59 return TryFold(init, fn(f))._ok; 60 } 61 public override readonly int GetHashCode() => 0; 62 public readonly Take<T, TIter> Into() => this; 63 public Maybe<T> Last() { 64 65 var n = _n; 66 _n = ulong.MinValue; 67 68 if (n > ulong.MinValue) { 69 var res = _iter.AdvanceBy(n); 70 71 if (res.IsErr) { 72 return Maybe<T>.None(); 73 } 74 } 75 return _iter.Last(); 76 } 77 public Maybe<T> Next() { 78 79 if (_n != ulong.MinValue) { 80 _n -= 1ul; 81 return _iter.Next(); 82 } else { 83 return Maybe<T>.None(); 84 } 85 } 86 public Prod<ulong, Maybe<ulong>> SizeHint() { 87 88 if (_n == ulong.MinValue) { return new(ulong.MinValue, new(ulong.MinValue)); } 89 var val = _iter.SizeHint(); 90 return new(val.Item0 <= _n ? val.Item0 : _n, val.Item1.IsSome && val.Item1._some < _n ? val.Item1 : new(_n)); ; 91 } 92 public override readonly string ToString() => string.Empty; 93 public Result<TInit, TErr> TryFold<TInit, TErr>(TInit init, Fn<TInit, T, Result<TInit, TErr>> f) where TInit: notnull where TErr: notnull { 94 95 if (_n == ulong.MinValue) { 96 return new(init); 97 } else { 98 var n = _n; 99 Fn<TInit, T, Result<TInit, Result<TInit, TErr>>> check() => (acc, x) => { 100 n -= 1ul; 101 var r = f(acc, x); 102 return n == ulong.MinValue ? new(r) : (r.IsErr ? new(r) : new(r._ok)); 103 }; 104 var res = _iter.TryFold(init, check()); 105 _n = n; 106 return res.IsErr ? res._err : new(res._ok); 107 } 108 } 109 readonly Result<Take<T, TIter>, Bottom> ITryInto<Take<T, TIter>, Bottom>.TryInto() => new(this); 110 #endregion 111 112 #region Operators 113 #endregion 114 115 #region Types 116 #endregion 117 } 118 #endregion 119 120 #region Namespaces 121 #endregion 122 } 123 #endregion