diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,7 @@
+## 0.1.18
+
+* Add `isCompleteInflate`
+
 ## 0.1.17
 
 * Add `bindPortGenEx`
diff --git a/Data/Streaming/Zlib.hs b/Data/Streaming/Zlib.hs
--- a/Data/Streaming/Zlib.hs
+++ b/Data/Streaming/Zlib.hs
@@ -27,6 +27,7 @@
     , finishInflate
     , flushInflate
     , getUnusedInflate
+    , isCompleteInflate
       -- * Deflate
     , Deflate
     , initDeflate
@@ -52,6 +53,7 @@
 import Data.ByteString.Lazy.Internal (defaultChunkSize)
 import Data.Typeable (Typeable)
 import Control.Exception (Exception)
+import Control.Monad (when)
 import Data.IORef
 
 type ZStreamPair = (ForeignPtr ZStreamStruct, ForeignPtr CChar)
@@ -62,6 +64,7 @@
 data Inflate = Inflate
     ZStreamPair
     (IORef S.ByteString) -- last ByteString fed in, needed for getUnusedInflate
+    (IORef Bool)         -- set True when zlib indicates that inflation is complete
     (Maybe S.ByteString) -- dictionary
 
 -- | The state of a deflation (eg, compression) process. All allocated memory
@@ -95,6 +98,9 @@
 instance Exception ZlibException
 
 -- | Some constants for the error codes, used internally
+zStreamEnd :: CInt
+zStreamEnd = 1
+
 zNeedDict :: CInt
 zNeedDict = 2
 
@@ -113,9 +119,10 @@
     withForeignPtr fbuff $ \buff ->
         c_set_avail_out zstr buff $ fromIntegral defaultChunkSize
     lastBS <- newIORef S.empty
-    return $ Inflate (fzstr, fbuff) lastBS Nothing
+    complete <- newIORef False
+    return $ Inflate (fzstr, fbuff) lastBS complete Nothing
 
--- | Initialize an inflation process with the given 'WindowBits'. 
+-- | Initialize an inflation process with the given 'WindowBits'.
 -- Unlike initInflate a dictionary for inflation is set which must
 -- match the one set during compression.
 initInflateWithDictionary :: WindowBits -> S.ByteString -> IO Inflate
@@ -128,7 +135,8 @@
     withForeignPtr fbuff $ \buff ->
         c_set_avail_out zstr buff $ fromIntegral defaultChunkSize
     lastBS <- newIORef S.empty
-    return $ Inflate (fzstr, fbuff) lastBS (Just bs)
+    complete <- newIORef False
+    return $ Inflate (fzstr, fbuff) lastBS complete (Just bs)
 
 -- | Initialize a deflation process with the given compression level and
 -- 'WindowBits'. You will need to call 'feedDeflate' to feed uncompressed
@@ -178,7 +186,7 @@
     :: Inflate
     -> S.ByteString
     -> IO Popper
-feedInflate (Inflate (fzstr, fbuff) lastBS inflateDictionary) bs = do
+feedInflate (Inflate (fzstr, fbuff) lastBS complete inflateDictionary) bs = do
     -- Write the BS to lastBS for use by getUnusedInflate. This is
     -- theoretically unnecessary, since we could just grab the pointer from the
     -- fzstr when needed. However, in that case, we wouldn't be holding onto a
@@ -193,13 +201,15 @@
   where
     inflate zstr = do
         res <- c_call_inflate_noflush zstr
-        if (res == zNeedDict)
+        res2 <- if (res == zNeedDict)
             then maybe (return zNeedDict)
                        (\dict -> (unsafeUseAsCStringLen dict $ \(cstr, len) -> do
                                     c_call_inflate_set_dictionary zstr cstr $ fromIntegral len
                                     c_call_inflate_noflush zstr))
                        inflateDictionary
             else return res
+        when (res2 == zStreamEnd) (writeIORef complete True)
+        return res2
 
 -- | An IO action that returns the next chunk of data, returning 'Nothing' when
 -- there is no more data to be popped.
@@ -243,7 +253,7 @@
 -- data, you will likely have some data still sitting in the buffer. This
 -- function will return it to you.
 finishInflate :: Inflate -> IO S.ByteString
-finishInflate (Inflate (fzstr, fbuff) _ _) =
+finishInflate (Inflate (fzstr, fbuff) _ _ _) =
     withForeignPtr fzstr $ \zstr ->
         withForeignPtr fbuff $ \buff -> do
             avail <- c_get_avail_out zstr
@@ -267,10 +277,17 @@
 --
 -- Since 0.1.11
 getUnusedInflate :: Inflate -> IO S.ByteString
-getUnusedInflate (Inflate (fzstr, _) ref _) = do
+getUnusedInflate (Inflate (fzstr, _) ref _ _) = do
     bs <- readIORef ref
     len <- withForeignPtr fzstr c_get_avail_in
     return $ S.drop (S.length bs - fromIntegral len) bs
+
+-- | Returns True if the inflater has reached end-of-stream, or False if
+-- it is still expecting more data.
+--
+-- Since 0.1.18
+isCompleteInflate :: Inflate -> IO Bool
+isCompleteInflate (Inflate _ _ complete _) = readIORef complete
 
 -- | Feed the given 'S.ByteString' to the deflater. Return a 'Popper',
 -- an IO action that returns the compressed data a chunk at a time.
diff --git a/streaming-commons.cabal b/streaming-commons.cabal
--- a/streaming-commons.cabal
+++ b/streaming-commons.cabal
@@ -1,5 +1,5 @@
 name:                streaming-commons
-version:             0.1.17
+version:             0.1.18
 synopsis:            Common lower-level functions needed by various streaming data libraries
 description:         Provides low-dependency functionality commonly needed by various streaming data libraries, such as conduit and pipes.
 homepage:            https://github.com/fpco/streaming-commons
