为什么字节字符串的Data.Binary实例添加字节字符串的长度作为前缀



查看各种ByteString类型的put实例,我们发现在写入字节串之前,字节串的长度总是以二进制文件为前缀https://hackage.haskell.org/package/binary-0.8.8.0/docs/src/Data.Binary.Class.html#put

以为例

instance Binary B.ByteString where
put bs = put (B.length bs) -- Why this??
<> putByteString bs
get    = get >>= getByteString

这样做有什么特别的原因吗?在不加前缀的情况下编写Bytestring的唯一方法是创建我们自己的newtype包装器并为Binary创建一个实例吗?

这样做有什么特殊的原因吗?

getput的思想是可以组合多个对象。例如,你可以写:

write_func :: ByteString -> Char -> Put
write_func some_bytestring some_char = do
put some_bytestring
put some_char

然后你想定义一个可以读回数据的函数,显然你想让这两个函数一起作为一个身份函数:如果作者写了一个特定的ByteString和一个特定Char,那么你想让读函数读相同的ByteString和字符。

阅读器功能应类似于:

read_fun :: Get (ByteString, Char)
read_fun = do
bs <- get
c <- get
return (bs, c)

但问题是,ByteString什么时候结束?'A'字符也可以是ByteString的一部分。因此,您需要以某种方式指示ByteString的结束位置。这可以通过保存长度或末尾的一些标记来完成。在标记的情况下,您将需要";逃逸;字节字符串,这样它就不能包含标记本身。

但是,您需要一些机制来指定ByteString何时结束。

在不加前缀的情况下编写Bytestring的唯一方法是创建我们自己的newtype包装器并为Binary创建一个实例吗?

不,事实上它已经在instance定义中了。如果你想写一个没有长度的ByteString,那么你可以使用putByteString :: ByteString -> Put:

write_func :: ByteString -> Char -> Put
write_func some_bytestring some_char = do
putByteStringsome_bytestring
put some_char

但是当读取ByteString时,您需要计算出必须读取的字节数。

最新更新