diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@
 * [`FlatParse.Basic`][basic] only supports the above features. If you don't need indentation
   parsing, this is sufficient.
 * [`FlatParse.Stateful`][stateful] additionally supports a built-in `Int` worth of internal state
-  and an additional `Int` reader environment. This can support a wide range of indentation parsing
+  and an additional custom reader environemnt. This can support a wide range of indentation parsing
   features. There is a slight overhead in performance and code size compared to `Basic`. However, in
   small parsers and microbenchmarks the difference between `Basic` and `Stateful` is often reduced
   to near zero by GHC and/or LLVM optimization.
diff --git a/flatparse.cabal b/flatparse.cabal
--- a/flatparse.cabal
+++ b/flatparse.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           flatparse
-version:        0.3.5.0
+version:        0.3.5.1
 synopsis:       High-performance parsing from strict bytestrings
 description:    @Flatparse@ is a high-performance parsing library, focusing on programming languages and
                 human-readable data formats. See the README for more information:
diff --git a/src/FlatParse/Basic.hs b/src/FlatParse/Basic.hs
--- a/src/FlatParse/Basic.hs
+++ b/src/FlatParse/Basic.hs
@@ -907,8 +907,7 @@
 -- | Parse the rest of the current line as a `String`. Assumes UTF-8 encoding,
 --   throws an error if the encoding is invalid.
 takeLine :: Parser e String
-takeLine =
-  branch eof (pure "") do
+takeLine = branch eof (pure "") do
   c <- anyChar
   case c of
     '\n' -> pure ""
@@ -921,12 +920,15 @@
 
 -- | Take the rest of the input as a `String`. Assumes UTF-8 encoding.
 takeRest :: Parser e String
-takeRest = ((:) <$> anyChar <*> takeRest) <|> pure []
+takeRest = branch eof (pure "") do
+  c <- anyChar
+  cs <- takeRest
+  pure (c:cs)
 
 -- | Get the rest of the input as a `String`, but restore the parsing state. Assumes UTF-8 encoding.
 --   This can be used for debugging.
 traceRest :: Parser e String
-traceRest = lookahead traceRest
+traceRest = lookahead takeRest
 
 --------------------------------------------------------------------------------
 
diff --git a/src/FlatParse/Stateful.hs b/src/FlatParse/Stateful.hs
--- a/src/FlatParse/Stateful.hs
+++ b/src/FlatParse/Stateful.hs
@@ -133,7 +133,7 @@
 
   -- * `String` conversions
   , packUTF8
-  , unpackUTF8
+  , Basic.unpackUTF8
 
   -- * Internal functions
   , ensureBytes#
@@ -857,8 +857,7 @@
 -- | Parse the rest of the current line as a `String`. Assumes UTF-8 encoding,
 --   throws an error if the encoding is invalid.
 takeLine :: Parser r e String
-takeLine =
-  branch eof (pure "") do
+takeLine = branch eof (pure "") do
   c <- anyChar
   case c of
     '\n' -> pure ""
@@ -871,20 +870,17 @@
 
 -- | Take the rest of the input as a `String`. Assumes UTF-8 encoding.
 takeRest :: Parser r e String
-takeRest = ((:) <$> anyChar <*> takeRest) <|> pure []
+takeRest = branch eof (pure "") do
+  c <- anyChar
+  cs <- takeRest
+  pure (c:cs)
 
 -- | Get the rest of the input as a `String`, but restore the parsing state. Assumes UTF-8 encoding.
 --   This can be used for debugging.
 traceRest :: Parser r e String
-traceRest = lookahead traceRest
+traceRest = lookahead takeRest
 
 --------------------------------------------------------------------------------
-
--- | Convert an UTF-8-coded `B.ByteString` to a `String`.
-unpackUTF8 :: B.ByteString -> String
-unpackUTF8 str = case runParser takeRest () 0 str of
-  OK a _ _ -> a
-  _        -> error "unpackUTF8: invalid encoding"
 
 -- | Check that the input has at least the given number of bytes.
 ensureBytes# :: Int -> Parser r e ()
