conduit 1.0.1 → 1.0.2
raw patch · 3 files changed
+67/−2 lines, 3 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Data.Conduit.Text: LengthExceeded :: Int -> TextException
+ Data.Conduit.Text: linesBounded :: MonadThrow m => Int -> Conduit Text m Text
Files
- Data/Conduit/Text.hs +46/−1
- conduit.cabal +1/−1
- test/main.hs +20/−0
Data/Conduit/Text.hs view
@@ -21,6 +21,7 @@ , ascii , iso8859_1 , lines+ , linesBounded , TextException (..) ) where @@ -43,7 +44,7 @@ import Data.Conduit import qualified Data.Conduit.List as CL import Control.Monad.Trans.Class (lift)-import Control.Monad (unless)+import Control.Monad (unless,when) -- | A specific character encoding. --@@ -64,6 +65,9 @@ showsPrec d c = showParen (d > 10) $ showString "Codec " . shows (codecName c) +++ -- | Emit each line separately -- -- Since 0.4.1@@ -86,6 +90,46 @@ where (first', second) = T.break (== '\n') more +++-- | Variant of the lines function with an integer parameter.+-- The text length of any emitted line+-- never exceeds the value of the paramater. Whenever+-- this is about to happen a LengthExceeded exception+-- is thrown. This function should be used instead+-- of the lines function whenever we are dealing with+-- user input (e.g. a file upload) because we can't be sure that+-- user input won't have extraordinarily large lines which would+-- require large amounts of memory if consumed.+linesBounded :: MonadThrow m => Int -> Conduit T.Text m T.Text+linesBounded maxLineLen =+ loop 0 id+ where+ loop len front = await >>= maybe (finish front) (go len front)++ finish front =+ let final = front T.empty+ in unless (T.null final) (yield final)+ go len sofar more =+ case T.uncons second of+ Just (_, second') -> do+ let toYield = sofar first'+ len' = len + T.length first'+ when (len' > maxLineLen)+ (lift $ monadThrow (LengthExceeded maxLineLen))+ yield toYield+ go 0 id second'+ Nothing -> do+ let len' = len + T.length more+ when (len' > maxLineLen) $+ (lift $ monadThrow (LengthExceeded maxLineLen))+ let rest = sofar more+ loop len' $ T.append rest+ where+ (first', second) = T.break (== '\n') more+++ -- | Convert text into bytes, using the provided codec. If the codec is -- not capable of representing an input character, an exception will be thrown. --@@ -123,6 +167,7 @@ -- Since 0.3.0 data TextException = DecodeException Codec Word8 | EncodeException Codec Char+ | LengthExceeded Int | TextException Exc.SomeException deriving (Show, Typeable) instance Exc.Exception TextException
conduit.cabal view
@@ -1,5 +1,5 @@ Name: conduit-Version: 1.0.1+Version: 1.0.2 Synopsis: Streaming data processing library. Description: @conduit@ is a solution to the streaming data problem, allowing for production, transformation, and consumption of streams of data in constant memory. It is an alternative to lazy I\/O which guarantees deterministic resource handling, and fits in the same general solution space as @enumerator@\/@iteratee@ and @pipes@. For a tutorial, please visit <https://haskell.fpcomplete.com/user/snoyberg/library-documentation/conduit-overview>.
test/main.hs view
@@ -401,6 +401,26 @@ x <- CL.sourceList ["foobarbaz", error "ignore me"] C.$$ CT.decode CT.utf8 C.=$ CL.head x `shouldBe` Just "foobarbaz" + describe "text lines bounded" $ do+ it "works across split lines" $+ (CL.sourceList [T.pack "abc", T.pack "d\nef"] C.$= CT.linesBounded 80 C.$$ CL.consume) ==+ [[T.pack "abcd", T.pack "ef"]]+ it "works with multiple lines in an item" $+ (CL.sourceList [T.pack "ab\ncd\ne"] C.$= CT.linesBounded 80 C.$$ CL.consume) ==+ [[T.pack "ab", T.pack "cd", T.pack "e"]]+ it "works with ending on a newline" $+ (CL.sourceList [T.pack "ab\n"] C.$= CT.linesBounded 80 C.$$ CL.consume) ==+ [[T.pack "ab"]]+ it "works with ending a middle item on a newline" $+ (CL.sourceList [T.pack "ab\n", T.pack "cd\ne"] C.$= CT.linesBounded 80 C.$$ CL.consume) ==+ [[T.pack "ab", T.pack "cd", T.pack "e"]]+ it "is not too eager" $ do+ x <- CL.sourceList ["foobarbaz", error "ignore me"] C.$$ CT.decode CT.utf8 C.=$ CL.head+ x `shouldBe` Just "foobarbaz"+ it "throws an exception when lines are too long" $ do+ x <- C.runExceptionT $ CL.sourceList ["hello\nworld"] C.$$ CT.linesBounded 4 C.=$ CL.consume+ show x `shouldBe` show (Left $ CT.LengthExceeded 4 :: Either CT.TextException ())+ describe "binary isolate" $ do it "works" $ do bss <- runResourceT $ CL.sourceList (replicate 1000 "X")