Created
July 20, 2011 22:05
-
-
Save NathanHowell/1096039 to your computer and use it in GitHub Desktop.
Length prefixed gzipped streams
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Data.Binary.Get | |
import qualified Data.ByteString as B | |
import qualified Data.Enumerator as E | |
import qualified Data.Enumerator.Binary as EB | |
import qualified Codec.Zlib.Enum as Z | |
unzipStream :: E.Iteratee B.ByteString IO b | |
-> E.Iteratee B.ByteString IO b | |
unzipStream sink = do | |
-- read four bytes off the wire into a bytestring | |
header <- EB.take 4 | |
-- convert the 4 byte bytestring to a 32 bit little endian integer | |
-- then convert it again to an Integer (required for isolate) | |
let streamLength = fromIntegral $ runGet getWord32le header | |
-- create an Enumerator that is exactly 'streamLength' bytes long | |
-- feed it into zlib's decompressor | |
-- and stream the decompressed results into 'sink', an Iteratee | |
val <- E.joinI (EB.isolate streamLength E.$$ E.joinI (Z.decompress Z.defaultWindowBits E.$$ sink)) | |
isDone <- E.isEOF | |
if isDone | |
-- if we're at the end of the input stream, return the last value. | |
-- you could also build these up during the recursion or simply ignore | |
-- the return value (if any) by returning () | |
then return val | |
-- otherwise recurse, reading the next gzipped entry out of the stream | |
else unzipStream sink | |
main :: IO () -- process ./source.file.bin | |
main = E.run_ $ EB.enumFile "source.file.bin" | |
-- and print the decompressed stream to stdout | |
E.$$ unzipStream (E.printChunks False) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment