diff --git a/library/Potoki/Cereal/Consume.hs b/library/Potoki/Cereal/Consume.hs
--- a/library/Potoki/Cereal/Consume.hs
+++ b/library/Potoki/Cereal/Consume.hs
@@ -5,6 +5,7 @@
 import Potoki.Core.Consume
 import Data.Serialize
 import qualified Potoki.Core.Fetch as E
+import qualified Potoki.Cereal.Transform as D
 
 
 get :: Get a -> Consume ByteString (Either String a)
@@ -21,5 +22,12 @@
           Partial newDecodeChunk -> loop newDecodeChunk
           Done result _ -> return (Right result)
           Fail error _ -> return (Left (fromString error))
-        in join (fetchIO none some)
+        in do
+          fetch <- fetchIO
+          case fetch of
+            Nothing -> none
+            Just res -> some res
     in loop (runGetPartial get)
+    
+encodeToFile :: Serialize a => FilePath -> Consume a (Either IOException ())
+encodeToFile = transform D.encode . writeBytesToFile
diff --git a/library/Potoki/Cereal/Produce.hs b/library/Potoki/Cereal/Produce.hs
--- a/library/Potoki/Cereal/Produce.hs
+++ b/library/Potoki/Cereal/Produce.hs
@@ -6,8 +6,20 @@
 import Data.Serialize
 import qualified Data.ByteString.Lazy as A
 import qualified Data.ByteString.Lazy.Internal as A
+import qualified Potoki.Cereal.Transform as D
+import qualified Data.Serialize as C
+import Potoki.Core.Transform
 
 
 put :: Put -> Produce ByteString
 put =
   lazyByteString . runPutLazy
+
+fileDecoded :: C.Serialize a => FilePath -> Produce (Either IOException (Either Text a))
+fileDecoded = transform (right D.decode) . fileBytes
+
+directoryDecoded :: C.Serialize a => FilePath -> Produce (Either IOException (Either Text a))
+directoryDecoded dirPath =
+  transform
+    (right (produce fileDecoded) >>^ join)
+    (directoryContents dirPath)
diff --git a/library/Potoki/Cereal/Transform.hs b/library/Potoki/Cereal/Transform.hs
new file mode 100644
--- /dev/null
+++ b/library/Potoki/Cereal/Transform.hs
@@ -0,0 +1,84 @@
+module Potoki.Cereal.Transform
+(
+  encode,
+  decode,
+)
+where
+
+import Potoki.Cereal.Prelude
+import Potoki.Core.Transform
+import qualified Potoki.Core.Fetch as A
+import qualified Potoki.Core.Transform as D
+import qualified Data.Attoparsec.Types as B
+import qualified Data.Serialize as C
+
+
+encode :: C.Serialize element => Transform element ByteString
+encode =
+  arr C.encode
+
+decode :: C.Serialize element => Transform ByteString (Either Text element)
+decode =
+  runPartialDecoder (C.runGetPartial C.get)
+
+result2IResult :: C.Result decoded -> B.IResult ByteString decoded
+result2IResult =
+  \case
+    C.Fail err input -> B.Fail input [] err
+    C.Partial func   -> B.Partial $ result2IResult . func
+    C.Done val input -> B.Done input val
+
+{-# INLINE runPartialDecoder #-}
+runPartialDecoder :: forall decoded. (ByteString -> C.Result decoded) -> Transform ByteString (Either Text decoded)
+runPartialDecoder inputToResult =
+  Transform $ \ inputFetch -> return $ A.Fetch $ do
+    unconsumedRef <- newIORef mempty
+    finishedRef <- newIORef False
+    fetchParsed inputFetch finishedRef unconsumedRef
+  where
+    fetchParsed :: A.Fetch ByteString -> IORef Bool -> IORef ByteString -> IO (Maybe (Either Text decoded))
+    fetchParsed (A.Fetch inputFetchIO) finishedRef unconsumedRef =
+      do
+        finished <- readIORef finishedRef
+        if finished
+          then return Nothing
+          else do
+            unconsumed <- readIORef unconsumedRef
+            if unconsumed == mempty
+              then do
+                inputFetch <- inputFetchIO
+                case inputFetch of
+                  Nothing    -> return Nothing
+                  Just input -> do
+                    if input == mempty
+                      then return Nothing
+                      else matchResult $ inputToResult input
+              else do
+                writeIORef unconsumedRef mempty
+                matchResult $ inputToResult unconsumed
+      where
+        matchResult =
+          \ case
+            C.Partial inputToResultVal1 ->
+              consume' inputToResultVal1
+            C.Done decoded unconsumed ->
+              do
+                writeIORef unconsumedRef unconsumed
+                return $ Just (Right decoded)
+            C.Fail message unconsumed ->
+              do
+                writeIORef unconsumedRef unconsumed
+                writeIORef finishedRef True
+                return $ Just (Left resultMessage)
+              where
+                resultMessage =
+                  fromString message
+        consume' inputToResultVal2 = do
+          inputFetch <- inputFetchIO
+          case inputFetch of
+            Nothing -> do
+              writeIORef finishedRef True
+              matchResult $ inputToResultVal2 mempty
+            Just input -> do
+              when (input == mempty) (writeIORef finishedRef True)
+              matchResult $ inputToResultVal2 input
diff --git a/potoki-cereal.cabal b/potoki-cereal.cabal
--- a/potoki-cereal.cabal
+++ b/potoki-cereal.cabal
@@ -1,15 +1,15 @@
 name:
   potoki-cereal
 version:
-  0.2
+  0.2.1
 synopsis:
   Streaming serialization
 category:
   Potoki, Streaming
 homepage:
-  https://github.com/metrix-ai/potoki-cereal 
+  https://github.com/metrix-ai/potoki-cereal
 bug-reports:
-  https://github.com/metrix-ai/potoki-cereal/issues 
+  https://github.com/metrix-ai/potoki-cereal/issues
 author:
   Nikita Volkov <nikita.y.volkov@mail.ru>
 maintainer:
@@ -41,12 +41,17 @@
   exposed-modules:
     Potoki.Cereal.Consume
     Potoki.Cereal.Produce
+    Potoki.Cereal.Transform
   other-modules:
     Potoki.Cereal.Prelude
   build-depends:
     base >=4.7 && <5,
+    potoki-core >= 2.2.1 && < 2.3,
+    text >= 1 && < 2,
+    cereal >= 0.5 && < 0.6,
+    bytestring >= 0.10 && < 0.11,
+    base-prelude >= 1 && < 2,
+    attoparsec >=0.13 && <0.15,
+    acquire >=0.2 && <0.3,
     base-prelude >=1 && <2,
-    bytestring >=0.10 && <0.11,
-    cereal >=0.5 && <0.6,
-    potoki-core >=1.5.3 && <1.6,
-    text >=1 && <2
+    text >= 1 && < 2
