~/bend-docscommunity

text.bend source

text.bend on the hub · documented module

# Text: lines out of a byte stream, and header-safe strings. SMTP is a# line protocol: every command and reply line ends in CRLF, and a CR or# LF smuggled into a field would start a new command or header.import Base# A cut of a buffer: the first complete line and the rest, or the# whole buffer back when no line is complete yet.type Line is Data:  Need{buf: String}  Line{line: String, rest: String}# Lines# -----# A line read backwards, its CR dropped, put back in order.def Text.done(acc: String) -> String:  match acc:    case SNil{}:      SNil{}    case SCon{Chr{13}, t}:      String.reverse(t)    case SCon{c, t}:      String.reverse(SCon{c, t})# The first LF-terminated line of s; Need{""} when there is none.def Text.line(s: String, acc: String) -> Line:  match s:    case SNil{}:      Need{SNil{}}    case SCon{Chr{10}, t}:      Line{Text.done(acc), t}    case SCon{c, t}:      Text.line(t, SCon{c, acc})def Text.cut.fin(l: Line, buf: String) -> Line:  match l:    case Need{_}:      Need{buf}    case Line{a, b}:      Line{a, b}# The first line of buf and the rest, or Need{buf}.def Text.cut(+buf: String) -> Line:  Text.cut.fin(Text.line(buf, SNil{}), buf)# Safe fields# -----------def Text.is_nl(c: Char) -> Bool:  match c:    case Chr{+n}:      U32.is_eq(n, 10) || U32.is_eq(n, 13)def Text.clean.put(nl: Bool, c: Char, rest: String) -> String:  match nl:    case True{}:      rest    case False{}:      SCon{c, rest}# s without its CRs and LFs: safe inside one command or header line.def Text.clean(s: String) -> String:  match s:    case SNil{}:      SNil{}    case SCon{+c, t}:      Text.clean.put(Text.is_nl(c), c, Text.clean(t))# Whether s holds a CR or an LF.def Text.has_nl(s: String) -> Bool:  match s:    case SNil{}:      False{}    case SCon{+c, t}:      Text.is_nl(c) || Text.has_nl(t)# acc reversed in front of tail: the last step of a tail-recursive# builder (a non-tail recursion costs a frame per char in Bend).def Text.onto(acc: String, tail: String) -> String:  match acc:    case SNil{}:      tail    case SCon{c, t}:      Text.onto(t, SCon{c, tail})