5

パスワードを表す文字列を固定長の10バイトフィールドにシリアル化するように指示するプロトコルを実装しています。このタスクを実行するためにData.Cerealを使用しています。これが私の最近の試みです:

padText :: Int -> Text -> Text
padText fieldLen = T.justifyLeft fieldLen '\NUL'

putPassword :: Putter Password
putPassword = put . TE.encodeUtf8 . padText 10

put on ByteStringsは、エンコード作成の前に追加の8バイトチャンクを追加します。

 runPut $ putPassword "Friend"

結果 :

"\NUL\NUL\NUL\NUL\NUL\NUL\NUL\nFriend\NUL\NUL\NUL\NUL"

余分なチャンクは必要ありません。なぜこのように振る舞うのですか?

元の10バイトだけをシリアル化する方法を知っている人はいますか?

4

2 に答える 2

7

「余分なチャンク」とは、の最初のビットを意味すると思います"\NUL\NUL\NUL\NUL\NUL\NUL\NUL\n。これは64ビット長のフィールド(値がであることに注意してください10)であり、のSerialize定義の一部ですByteString。を呼び出した後、すでにバイト文字列が存在するため、長さフィールドを回避するためにTE.encodeUtf8使用することをお勧めします(または、遅延テキストエンコーディングモジュールをインポートする場合)。putByteStringputLazyByteString

于 2012-07-08T03:46:37.213 に答える
2

ThomasputがByteStringsで述べたように、エンコードされた長さの前に追加されます。以下に実際のインスタンスを示します。

instance Serialize B.ByteString where
    put bs = do put (B.length bs :: Int)
                putByteString bs
   ...

putByteString一人ではありません。解決策は次を使用することputByteStringです:

putPassword :: Putter Password
putPassword = putByteString . TE.encodeUtf8 . padText 10
于 2012-07-08T08:14:16.483 に答える