FlatMapInternal.cs (3782B)
1 using Std.Maybe; 2 using Std.Ops; 3 using Std.Result; 4 using System; 5 using System.Runtime.InteropServices; 6 #region Namespaces 7 namespace Std.Iter { 8 #region Types 9 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 0)] 10 struct FlatMapInternal<T, TInnerIter, TIter>: IFusedIterator<T> where T: notnull where TInnerIter: notnull, IIterator<T> where TIter: notnull, IIterator<TInnerIter> { 11 12 #region Type-level Constructors 13 #endregion 14 15 #region Instance Constructors 16 public FlatMapInternal() => throw new InvalidOperationException("Parameterless constructor is not allowed to be called!"); 17 internal FlatMapInternal(TIter iter) => (_iter, _inner, _innerIsSome) = (iter.Fuse<TIter, TInnerIter>(), default!, false); 18 #endregion 19 20 #region Type-level Fields 21 #endregion 22 23 #region Instance Fields 24 Fuse<TInnerIter, TIter> _iter; 25 TInnerIter _inner; 26 bool _innerIsSome; 27 #endregion 28 29 #region Type-level Properties 30 #endregion 31 32 #region Instance Properties 33 #endregion 34 35 #region Type-level Functions 36 #endregion 37 38 #region Instance Functions 39 public Result<Unit, ulong> AdvanceBy(ulong n) => IIterator<T>.AdvanceByDefault(ref this, n); 40 public ulong Count() => IIterator<T>.CountDefault(ref this); 41 public TInit Fold<TInit>(TInit init, Fn<TInit, T, TInit> f) where TInit: notnull { 42 static Fn<TInit, TInnerIter, TInit> flatten(Fn<TInit, T, TInit> fold) => (acc, x) => x.Fold(acc, fold); 43 return (_innerIsSome ? new Maybe<TInnerIter>(_inner!) : Maybe<TInnerIter>.None()).IntoIter().Chain<Maybe.IntoIterator<TInnerIter>, TInnerIter, Fuse<TInnerIter, TIter>>(_iter).Fold(init, flatten(f)); 44 } 45 public Maybe<T> Last() => IIterator<T>.LastDefault(ref this); 46 public Maybe<T> Next() { 47 48 while (true) { 49 50 if (_innerIsSome) { 51 var val = _inner!.Next(); 52 53 if (val.IsSome) { 54 return val; 55 } else { 56 _innerIsSome = false; 57 } 58 } else { 59 var val = _iter.Next(); 60 _innerIsSome = val.IsSome; 61 if (_innerIsSome) { _inner = val._some; } else { return Maybe<T>.None(); } 62 } 63 } 64 } 65 public Prod<ulong, Maybe<ulong>> SizeHint() { 66 67 var inner = _innerIsSome ? _inner!.SizeHint() : new(ulong.MinValue, new(ulong.MinValue)); 68 var (low, high) = _iter.SizeHint(); 69 return low == ulong.MinValue && high.IsSome && high._some == ulong.MinValue ? inner : (new(inner.Item0, Maybe<ulong>.None())); 70 } 71 public Result<TInit, TErr> TryFold<TInit, TErr>(TInit init, Fn<TInit, T, Result<TInit, TErr>> f) where TInit: notnull where TErr: notnull { 72 73 Result<TInit, TErr> res; 74 75 if (_innerIsSome) { 76 res = _inner!.TryFold(init, f); 77 78 if (res.IsErr) { 79 return res; 80 } else { 81 init = res._ok; 82 _innerIsSome = false; 83 } 84 } 85 var inner = _inner; 86 Fn<TInit, TInnerIter, Result<TInit, TErr>> flatten(Fn<TInit, T, Result<TInit, TErr>> fold) => (acc, x) => { var r = x.TryFold(acc, fold); inner = x; return r; }; 87 res = _iter.TryFold(init, flatten(f)); 88 (_inner, _innerIsSome) = (inner, res.IsErr); 89 return res; 90 } 91 #endregion 92 93 #region Operators 94 #endregion 95 96 #region Types 97 #endregion 98 } 99 #endregion 100 101 #region Namespaces 102 #endregion 103 } 104 #endregion