Std

Mainly a port of Rust's std.
git clone https://git.philomathiclife.com/repos/Std
Log | Files | Refs | README

Peekable.cs (5291B)


      1 using Std.Cmp;
      2 using Std.Convert;
      3 using Std.Maybe;
      4 using Std.Num;
      5 using Std.Ops;
      6 using Std.Result;
      7 using System;
      8 using System.Diagnostics;
      9 using System.Runtime.InteropServices;
     10 #region Namespaces
     11 namespace Std.Iter {
     12     #region Types
     13     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 0)]
     14     public struct Peekable<T, TIter>: IInto<Peekable<T, TIter>>, IIterator<T> where T: notnull where TIter: notnull, IIterator<T> {
     15 
     16         #region Type-level Constructors
     17         #endregion
     18 
     19         #region Instance Constructors
     20         public Peekable() => throw new InvalidOperationException("Parameterless constructor is not allowed to be called!");
     21         internal Peekable(TIter iter) => (_iter, _peeked) = (iter, Maybe<Maybe<T>>.None());
     22         #endregion
     23 
     24         #region Type-level Fields
     25         #endregion
     26 
     27         #region Instance Fields
     28         [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0044:Add readonly modifier", Justification = "Can't be readonly since we call mutable methods on it.")]
     29         TIter _iter;
     30         Maybe<Maybe<T>> _peeked;
     31         #endregion
     32 
     33         #region Type-level Properties
     34         #endregion
     35 
     36         #region Instance Properties
     37         #endregion
     38 
     39         #region Type-level Functions
     40         #endregion
     41 
     42         #region Instance Functions
     43         public Result<Unit, ulong> AdvanceBy(ulong n) {
     44 
     45             if (n == ulong.MinValue) {
     46                 return new(new Unit());
     47             } else {
     48                 var mbe = _peeked;
     49                 _peeked = Maybe<Maybe<T>>.None();
     50                 return mbe.IsSome ? (mbe._some.IsNone ? new(ulong.MinValue) : _iter.AdvanceBy(n - 1ul)) : _iter.AdvanceBy(n);
     51             }
     52         }
     53         public ulong Count() {
     54 
     55             var mbe = _peeked;
     56             _peeked = Maybe<Maybe<T>>.None();
     57             return mbe.IsSome ? (mbe._some.IsSome ? 1ul + _iter.Count() : ulong.MinValue) : _iter.Count();
     58         }
     59         public override readonly bool Equals(object? _) => false;
     60         public TInit Fold<TInit>(TInit init, Fn<TInit, T, TInit> f) where TInit: notnull {
     61 
     62             var mbe = _peeked;
     63             _peeked = Maybe<Maybe<T>>.None();
     64 
     65             if (mbe.IsSome) {
     66 
     67                 if (mbe._some.IsNone) {
     68                     return init;
     69                 } else {
     70                     init = f(init, mbe._some._some);
     71                 }
     72             }
     73             return _iter.Fold(init, f);
     74         }
     75         public override readonly int GetHashCode() => 0;
     76         public readonly Peekable<T, TIter> Into() => this;
     77         public Maybe<T> Last() {
     78 
     79             var mbe = _peeked;
     80             _peeked = Maybe<Maybe<T>>.None();
     81             Maybe<T> val;
     82             
     83             if (mbe.IsSome) {
     84 
     85                 if (mbe._some.IsNone) {
     86                     return Maybe<T>.None();
     87                 } else {
     88                     val = mbe._some;
     89                 }
     90             } else {
     91                 val = Maybe<T>.None();
     92             }
     93             return _iter.Last().Or(val);
     94         }
     95         public Maybe<T> Next() {
     96 
     97             var mbe = _peeked;
     98             _peeked = Maybe<Maybe<T>>.None();
     99             return mbe.IsSome ? mbe._some : _iter.Next();
    100         }
    101         public Maybe<T> NextIf(FnIn<T, bool> f) {
    102 
    103             var val = Next();
    104 
    105             if (val.IsSome && f(in val._some)) {
    106                 return new(val._some);
    107             } else {
    108                 Trace.Assert(_peeked.IsNone);
    109                 _peeked = new(val);
    110                 return Maybe<T>.None();
    111             }
    112         }
    113         public Maybe<T> Peek() {
    114 
    115             if (_peeked.IsNone) {
    116                 _peeked = new(_iter.Next());
    117             }
    118             return _peeked._some;
    119         }
    120         public Prod<ulong, Maybe<ulong>> SizeHint() {
    121 
    122             ulong len;
    123 
    124             if (_peeked.IsSome) {
    125 
    126                 if (_peeked._some.IsNone) {
    127                     return new(ulong.MinValue, new(ulong.MinValue));
    128                 } else {
    129                     len = 1ul;
    130                 }
    131             } else {
    132                 len = ulong.MinValue;
    133             }
    134             var val = _iter.SizeHint();
    135             return new(val.Item0.SaturatingAdd(len), val.Item1.IsSome ? val.Item1._some.CheckedAdd(len) : Maybe<ulong>.None());
    136         }
    137         public override readonly string ToString() => string.Empty;
    138         public Result<TInit, TErr> TryFold<TInit, TErr>(TInit init, Fn<TInit, T, Result<TInit, TErr>> f) where TInit: notnull where TErr: notnull {
    139 
    140             var mbe = _peeked;
    141             _peeked = Maybe<Maybe<T>>.None();
    142 
    143             if (mbe.IsSome) {
    144 
    145                 if (mbe._some.IsNone) {
    146                     return new(init);
    147                 } else {
    148                     var res = f(init, mbe._some._some);
    149 
    150                     if (res.IsErr) {
    151                         return res;
    152                     } else {
    153                         init = res._ok;
    154                     }
    155                 }
    156             }
    157             return _iter.TryFold(init, f);
    158         }
    159         readonly Result<Peekable<T, TIter>, Bottom> ITryInto<Peekable<T, TIter>, Bottom>.TryInto() => new(this);
    160         #endregion
    161 
    162         #region Operators
    163         #endregion
    164 
    165         #region Types
    166         #endregion
    167     }
    168     #endregion
    169 
    170     #region Namespaces
    171     #endregion
    172 }
    173 #endregion