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"

我不想要额外的块。为什么put会有这种行为?

有谁知道如何只序列化 10 个原始字节?

4

2 回答 2

7

我假设“额外的块”是指"\NUL\NUL\NUL\NUL\NUL\NUL\NUL\n. 这是一个 64 位长度的字段(注意它的值是10),它是ByteString. 由于您在调用后已经有一个字节串TE.encodeUtf8,我建议您只使用putByteString以避免长度字段(或者putLazyByteString如果您正在导入惰性文本编码模块)。

于 2012-07-08T03:46:37.213 回答
2

正如托马斯put在 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 回答