use Iter Iter, IntoIter, into-iter, Iter, next, take-while, take, for-each, null, drop', count, to, map use Term use Char (is-digit) use Str Str, chars, parse-int use Error todo, or-fail, panic, assert use StaticSize (StaticSize) use SmolStr (SmolStr) use Misc is-just # I'm taking over the module. # This scanner will be treated as a byte scanner FIRST with Char methods n shii. # actually, just handle any type, whatever. Scanner it s it byte-offset Size inst Iter Scanner next (self) case ((&self&.s) next()) Just(c) self <&.byte-offset= self&.byte-offset + c.num-bytes return Just(c) None return None inst IntoIter Scanner into-iter (self): self fn mk (s it) <= IntoIter it: Scanner { s: s into-iter(), byte-offset: 0 } # todo: bad name fn mk-from-strview (s StrView) -> Scanner StrView: { s, byte-offset: 0 } fn mk-from-str(s str) <= Str str: Scanner { s: s chars(), byte-offset: 0 } fn is-at-end (sc Ptr (Scanner s)) -> Bool <= Iter s return sc null() ###### CHAR STUFF fn scan-int (sc Ptr (Scanner s)) -> Maybe I64 <= Iter s, IntoIter s digit-chars = sc take-while(is-digit) if digit-chars null() return None sc drop'(digit-chars count()) return digit-chars parse-int() fn int (sc Ptr (Scanner s)) -> Maybe I64 <= Iter s, IntoIter s, Str s: scan-int(sc) # another name! fn char(sc Ptr (Scanner s)) -> Maybe Char <= Iter s, IntoIter s: next(&sc&.s) fn peek (sc Ptr (Scanner s)) <= Iter s, IntoIter s: sc&.s Iter.head() fn try-char (sc Ptr (Scanner s), char Char) -> Bool <= Iter s, IntoIter s if sc peek() == Just(char) sc drop'(1) return True return False fn char-satisfies' (sc Ptr (Scanner s), condition Char -> Bool) -> Maybe Char <= Iter s, IntoIter s case sc&.s Iter.head() Just(c) if condition(c) sc drop'(1) return Just(c) else return None None return None fn char-satisfies (sc Ptr (Scanner s), condition Char -> Bool) -> Bool <= Iter s, IntoIter s: sc char-satisfies'(condition) is-just() fn matches-str (sc Ptr (Scanner s), s Str) -> Bool <= Iter s, IntoIter s skip = 0 ss =& s chars() sccp =& sc&.s Misc.own() while True case (sccp next(), ss next()) ((_, None)) sc drop'(skip) return True ((Just(c1), Just(c2))) if c1 /= c2 return False skip <= skip + 1 _ return False # different name :) fn skip-while (sc Ptr (Scanner s), condition Char -> Bool) <= Iter s, IntoIter s while sc char-satisfies(condition) pass ###### U8 STUFF # actually, it does not require any specific type. fn n-items (sc Ptr (Scanner it), _ StaticSize len) -> Array len elem <= Iter it arr =& @undefined for i in 0 to (len - 1) el = next(&sc&.s) or-fail('(Scan.n-bytes) iterator too shawt nigga') arr Array.set(Mem.i32-size(i), el) return arr& fn int-be (sc Ptr (Scanner it), num-bytes U32) <= Iter it int = 0 for i in 0 to (Mem.u32-i32(num-bytes) - 1) el = next(&sc&.s) or-fail('(Scan.n-bytes) iterator too shawt nigga') as U8 int <= int Math.lshift(8) + Mem.cast-on-zeroed(el) return int fn smol-str (sc Ptr (Scanner it), sz Size) -> SmolStr <= Iter it, IntoIter it max-ss-sz = SmolStr.max-sz() if sz > max-ss-sz panic('(Scan.scan-smol-str) max smol str size is \(max-ss-sz), but wanted size \(sz)') smol-str = SmolStr.from-bytes(sc&.s take(sz)) drop'(&sc&.s, sz) return smol-str #### StrView fn take-str-while (sc Ptr (Scanner StrView), fun Char -> Bool) -> StrView s = sc&.s StrView.take-while(fun) sc <&.s= sc&.s StrView.byte-substr-from(s StrView.num-bytes()) return s # maybe we should just add an Iter instance to StrView? fn drop-str-while (sc Ptr (Scanner StrView), fun Char -> Bool) _ = sc take-str-while(fun) #### Sub Scanner # (mostly to compute CRC n shi) CounterIter it it it count Size inst IntoIter CounterIter into-iter (self): self inst Iter CounterIter next (self) case next(&self&.it) None return None Just(x) self <&.count= self&.count + 1 return Just(x) fn sub-scanner (sc Ptr (Scanner it), scanmap it -> it') -> Scanner (CounterIter it'): Scanner { s: CounterIter { it: scanmap(sc&.s), count: 0 }, byte-offset: sc&.byte-offset } fn finish-sub-scanner (sc Ptr (Scanner it), ssc Ptr (Scanner (CounterIter it'))) <= Iter it sc drop'(ssc&.s.count) # fn sub-finish (sc Ptr (Scanner it)) # sub scanner thing... this is soooo bad... fn with-sub-scanner (sc Ptr (Scanner it), scanmap it -> it', fun Ptr (Scanner (CounterIter it')) -> a) -> a <= IntoIter it', Iter it ssc =& sc sub-scanner(scanmap) x = fun(ssc) sc finish-sub-scanner(ssc) return x