2017-10-27 9 views
2

Conduitをバイナリファイルを読み込み、正しいヘッダーがあることを確認して、ファイル内の残りのデータを処理する設定に使用したいと考えています。ファイルヘッダーを確認するコンジット

ヘッダーをチェックして残りのデータを次のコンジットに流すコンジットを作成しようとすると、問題が発生します。私はそれらをある例外処理のためにEither Stringモナドに住まわせる。

import Conduit (ConduitM, mapC, mapM_C, takeWhileCE) 
import Data.ByteString.Conversion (toByteString') 

separator :: ByteString 
separator = toByteString' '#' 

check :: ByteString -> Either String() 

confirmHeader :: ConduitM ByteString ByteString (Either String)() 
confirmHeader = do 
    takeWhileC (/= separator) .| mapM_C check 
    mapC id 

separatorは、ヘッダの終わりを事前に定義されたByteString次のとおりです。ここでは、コード(私はCondiut.Attoparsecモジュールがあります認識してんだけど、今のところ、私はそれを自分で書きたいのですが)の簡易版です。行mapC idは、ヘッダーがチェックアウトされた場合、残りのストリームを渡すことになっています。私はcheckの重要でない部分を省いた。

ヘッダーをチェックする部分が機能します。しかし、最後の行は、控えめで非慣用的であることを除けば、機能しません。

runConduit $ yield (toByteString' "header#rest") .| confirmHeader .| sinkList 

のようなものを実行すると、私が期待したようにRight []ではなくRight ["rest"]与えます。何か案は?

答えて

1

takeWhileC (/= separator)さんは全体がByteStringです。それはByteStringのチャンクでは機能しません。 Data.Conduit.Binaryを使用すると、ストリームの個々のバイトを処理できます。以下のコードは「期待どおり」と私は信じています。

module Main (main) where 

import   Conduit 
import   Data.ByteString (ByteString) 
import   Data.ByteString.Conversion (toByteString') 
import   Data.Char (ord) 
import qualified Data.Conduit.Binary as B 
import   GHC.Word (Word8) 

separator :: Word8 
separator = toEnum $ ord '#' 

check :: ByteString -> Either String() 
check _ = Right() 

confirmHeader :: ConduitM ByteString ByteString (Either String)() 
confirmHeader = do 
    B.takeWhile (/= separator) .| mapM_C check 
    B.drop 1 -- drop separator which stayed in stream 
    mapC id 

main :: IO() 
main = print . runConduit $ 
    yield (toByteString' "header#rest") .| confirmHeader .| sinkList 

そして出力:

[nix-shell:/tmp]$ ghc C.hs -fforce-recomp -Wall -Werror -o Main && ./Main 
[1 of 1] Compiling Main    (C.hs, C.o) 
Linking Main ... 
Right ["rest"] 
+0

グレート!小さな詳細として、代わりにtakeWhileCEを選択しましたが、Conduit.Binaryに対してベンチマークを行います。 – jorgen

+0

'takeWhileCE'はうまくいくはずです:私は実際にそれを使いたいと思っていましたが、その名前とConduit.Binaryを忘れていました。 –

+0

ちなみに、あなたは 'mapC id'よりももっとエレガントなものを考えることができますか、それともその標準ですか? – jorgen

関連する問題