我正在实现一个协议,该协议规定表示密码的字符串应序列化为固定长度的10字节字段。我正在使用Data.Cereal来执行此任务。这是我最近的一次:
padText :: Int -> Text -> Text
padText fieldLen = T.justifyLeft fieldLen '\NUL'
putPassword :: Putter Password
putPassword = put . TE.encodeUtf8 . padText 10
穿上ByteStrings,在它编码的前面添加一个额外的8字节块:
runPut $ putPassword "Friend"
结果:
"\NUL\NUL\NUL\NUL\NUL\NUL\NUL\nFriend\NUL\NUL\NUL\NUL"
我不想要额外的块。为什么这样表现?
有谁知道如何仅序列化10个原始字节?
答案 0 :(得分:7)
我认为“额外的块”是指"\NUL\NUL\NUL\NUL\NUL\NUL\NUL\n
的第一位。这是一个64位长的字段(注意它的值是10
),它是ByteString
的序列化定义的一部分。由于您在调用TE.encodeUtf8
后已经有一个字节字符串,我建议您只使用putByteString
来避免长度字段(如果您要导入惰性文本编码模块,则使用putLazyByteString
)。
答案 1 :(得分:2)
正如托马斯所说,ByteStrings put
预先编码了编码长度。显示
下面是实际的实例:
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