Skip to content

Commit 323012a

Browse files
committed
Memory usage improvements in unescapeText. #593
1 parent 2169adc commit 323012a

File tree

1 file changed

+7
-13
lines changed

1 file changed

+7
-13
lines changed

pure/Data/Aeson/Parser/UnescapePure.hs

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,6 @@ decode UtfTail1 point word = case word of
119119
w | 0x80 <= w && w <= 0xbf -> (UtfGround, setByte1 point word)
120120
_ -> throwDecodeError
121121

122-
{-# INLINE decode #-}
123-
124122
decodeHex :: Word8 -> Word16
125123
decodeHex 48 = 0 -- '0'
126124
decodeHex 49 = 1 -- '1'
@@ -145,12 +143,12 @@ decodeHex 101 = 14 -- 'e'
145143
decodeHex 70 = 15 -- 'F'
146144
decodeHex 102 = 15 -- 'f'
147145
decodeHex _ = throwDecodeError
148-
{-# INLINE decodeHex #-}
149146

150147
unescapeText' :: ByteString -> Text
151148
unescapeText' bs = runText $ \done -> do
152149
dest <- A.new len
153-
(pos, finalState) <- B.foldl' (f' dest) (return (0, StateNone)) bs
150+
151+
(pos, finalState) <- loop dest (0, StateNone) 0
154152

155153
-- Check final state. Currently pos gets only increased over time, so this check should catch overflows.
156154
when ( finalState /= StateNone || pos > len)
@@ -172,11 +170,11 @@ unescapeText' bs = runText $ \done -> do
172170
(st', p) ->
173171
return (pos, StateUtf st' p)
174172

175-
{-# INLINE runUtf #-}
176-
177-
f' dest m c = m >>= \s -> f dest s c
178-
179-
{-# INLINE f' #-}
173+
loop _ ps i | i >= len = return ps
174+
loop dest ps i = do
175+
let c = B.index bs i -- JP: We can use unsafe index once we prove bounds with Liquid Haskell.
176+
ps' <- f dest ps c
177+
loop dest ps' $ i+1
180178

181179
-- No pending state.
182180
f dest (pos, StateNone) c = runUtf dest pos UtfGround 0 c
@@ -253,8 +251,6 @@ unescapeText' bs = runText $ \done -> do
253251
else
254252
writeAndReturn dest pos u StateNone
255253

256-
{-# INLINE f #-}
257-
258254
write :: A.MArray s -> Int -> Word16 -> ST s ()
259255
write dest pos char =
260256
A.unsafeWrite dest pos char
@@ -270,8 +266,6 @@ throwDecodeError :: a
270266
throwDecodeError =
271267
let desc = "Data.Text.Internal.Encoding.decodeUtf8: Invalid UTF-8 stream" in
272268
throw (DecodeError desc Nothing)
273-
{-# INLINE throwDecodeError #-}
274269

275270
unescapeText :: ByteString -> Either UnicodeException Text
276271
unescapeText = unsafeDupablePerformIO . try . evaluate . unescapeText'
277-
{-# INLINE unescapeText #-}

0 commit comments

Comments
 (0)