Skip to content

Commit e921526

Browse files
committed
feat: DecodeResult.terminate
1 parent 59fee81 commit e921526

3 files changed

Lines changed: 22 additions & 16 deletions

File tree

Binary/Basic.lean

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ instance : ToString DecodeError where
2424
inductive DecodeResult (α) where
2525
| success (x : α) (k : Decoder)
2626
| error (err : DecodeError) (cur : Decoder)
27-
| pending (fn : ByteArray → DecodeResult α)
27+
| pending (fn : Option ByteArray → DecodeResult α)
2828
deriving Inhabited
2929

3030
@[always_inline]
@@ -60,6 +60,13 @@ def DecodeResult.feed {α} (bytes : ByteArray) : DecodeResult α → DecodeResul
6060
| .error err k => .error err (k.append bytes)
6161
| .pending fn => fn bytes
6262

63+
/-- Immediately terminate the pending state. -/
64+
@[always_inline]
65+
def DecodeResult.terminate {α} : DecodeResult α → DecodeResult α
66+
| .success x k => .success x k
67+
| .error err k => .error err k
68+
| .pending _ => .error .eoi { data := {}, offset := 0 }
69+
6370
@[always_inline]
6471
instance : Monad Get where
6572
pure x := fun d => DecodeResult.success x d
@@ -191,12 +198,15 @@ Catch any `DecodeError.eoi` and recover to a pending state rather than exit with
191198
* ensure that `x` terminates when enough bytes are fed,
192199
* or define your own pending function to cache intermediate result as much as possible.
193200
-/
194-
@[specialize, always_inline]
201+
@[specialize]
195202
partial def pending (x : Get α) : Get α := do
196203
try x
197204
catch err =>
198205
match err with
199-
| .eoi => fun d => .pending fun bytes => pending x (d.append bytes)
206+
| .eoi => fun d => .pending fun bytes? =>
207+
match bytes? with
208+
| none => DecodeResult.mkEOI d
209+
| some bytes => pending x (d.append bytes)
200210
| e => throw e
201211

202212
namespace Primitive

Binary/Get.lean

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ public section
1111
def fail (msg : String) : Get α :=
1212
throw (.userError msg)
1313

14-
@[always_inline, specialize]
14+
@[specialize]
1515
def many (p : Get α) : Get (Array α) := do
1616
let mut data := #[]
1717
repeat
1818
let some x ← optional p | break
1919
data := data.push x
2020
return data
2121

22-
@[always_inline, specialize]
22+
@[inline, specialize]
2323
def many1 (p : Get α) : Get (Array α) := do
2424
let first ← p
2525
let rest ← many p
@@ -35,6 +35,13 @@ def shouldBeEOI (includeUnExpected : Bool := false) : Get Unit := do
3535
else
3636
fail "expected EOI"
3737

38+
@[always_inline]
39+
def notFollowedBy (p : Get α) : Get Unit := fun d =>
40+
match p d with
41+
| .success _ _ => DecodeResult.error (.userError "unexpected lookahead") d
42+
| .error _ _ => DecodeResult.success () d
43+
| .pending _ => DecodeResult.error (.userError "unexpected pending lookahead") d
44+
3845
-- TODO: refactor following definitions for performance
3946

4047
@[inline, specialize]

Binary/UTF8/Get.lean

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,6 @@ namespace Binary.UTF8
1111
private def byteToChar (b : UInt8) : Char :=
1212
Char.ofNat b.toNat
1313

14-
-- @[always_inline]
15-
-- private def charToString (c : Char) : String :=
16-
-- String.ofList [c] -- TODO: how about `Char.toString`?
17-
1814
@[always_inline]
1915
private def chars_to_string (xs : Array Char) : String :=
2016
String.ofList xs.toList
@@ -50,10 +46,3 @@ def manyChars (p : Get Char) : Get String :=
5046
@[always_inline, specialize]
5147
def many1Chars (p : Get Char) : Get String :=
5248
chars_to_string <$> many1 p
53-
54-
@[always_inline]
55-
def notFollowedBy (p : Get α) : Get Unit := fun d =>
56-
match p d with
57-
| .success _ _ => DecodeResult.error (.userError "unexpected lookahead") d
58-
| .error _ _ => DecodeResult.success () d
59-
| .pending _ => DecodeResult.error (.userError "unexpected pending lookahead") d

0 commit comments

Comments
 (0)