使用借用的结构字段派生“反序列化”
Derive `Deserialize` with borrowed struct field
我正在尝试在借用内容的结构上派生 Deserialize
:
#[macro_use]
extern crate serde_derive;
use std::net::SocketAddr;
#[derive(Hash, Eq, PartialEq, Debug, Clone, Serialize, Deserialize)]
pub struct MyS<'a> {
pub addr: &'a SocketAddr,
}
我得到以下编译错误:
error[E0277]: the trait bound `&'a std::net::SocketAddr: _::_serde::Deserialize<'_>` is not satisfied
--> src/lib.rs:7:5
|
7 | pub addr: &'a SocketAddr,
| ^^^ the trait `_::_serde::Deserialize<'_>` is not implemented for `&'a std::net::SocketAddr`
|
= help: the following implementations were found:
<std::net::SocketAddr as _::_serde::Deserialize<'de>>
= note: required by `_::_serde::de::SeqAccess::next_element`
我可以通过哪些不同的方式让这个结构实现 Deserialize
一段时间?
注意:我实际上并不要求反序列化是零拷贝,这只是一个很好的选择
你不能这样做,原因如下:
Serde 允许 zero-copy 某些类型的反序列化。在这种情况下,数据是从 Deserializer
借用的,后者又借用或拥有某种缓冲区。由于 &[u8]
和 &str
从根本上讲都是字节流,因此可以将它们反序列化为缓冲区中的引用。 serde docs 中解释了这是如何工作的,但它从根本上要求 Rust 类型的布局与您正在反序列化的缓冲区中存在的数据完全相同。
但是,在您的情况下,您想要反序列化 SocketAddr
。问题是缓冲区中的数据与您要借用的数据的形式不同。 Serde 通过 Display
将 SocketAddr
s 序列化为字符串,例如 this implemention for SocketAddrV4
。但是 SocketAddr
本身存储为一个 32 位整数和一个 16 位整数。你不能把一个当作另一个来借;需要进行某种解析,然后有人需要拥有结果数据。 Serde 逻辑上让您的结构拥有该数据。即使在二进制序列化中,也不能保证序列化数据的布局与结构的布局匹配,因此需要进行解析。
这是通过 Deserialize
serde 提供的实现在类型系统中编码的。 This page 有完整列表。您可以看到 &'a str
的实现,其中 Deserializer
('de
) 的生命周期超过 'a
。没有实现对大多数其他类型的引用,包括 &SocketAddr
.
这个 serde 问题 linked by PitaJ 显示了一个很好的最小代码示例。
我正在尝试在借用内容的结构上派生 Deserialize
:
#[macro_use]
extern crate serde_derive;
use std::net::SocketAddr;
#[derive(Hash, Eq, PartialEq, Debug, Clone, Serialize, Deserialize)]
pub struct MyS<'a> {
pub addr: &'a SocketAddr,
}
我得到以下编译错误:
error[E0277]: the trait bound `&'a std::net::SocketAddr: _::_serde::Deserialize<'_>` is not satisfied
--> src/lib.rs:7:5
|
7 | pub addr: &'a SocketAddr,
| ^^^ the trait `_::_serde::Deserialize<'_>` is not implemented for `&'a std::net::SocketAddr`
|
= help: the following implementations were found:
<std::net::SocketAddr as _::_serde::Deserialize<'de>>
= note: required by `_::_serde::de::SeqAccess::next_element`
我可以通过哪些不同的方式让这个结构实现 Deserialize
一段时间?
注意:我实际上并不要求反序列化是零拷贝,这只是一个很好的选择
你不能这样做,原因如下:
Serde 允许 zero-copy 某些类型的反序列化。在这种情况下,数据是从 Deserializer
借用的,后者又借用或拥有某种缓冲区。由于 &[u8]
和 &str
从根本上讲都是字节流,因此可以将它们反序列化为缓冲区中的引用。 serde docs 中解释了这是如何工作的,但它从根本上要求 Rust 类型的布局与您正在反序列化的缓冲区中存在的数据完全相同。
但是,在您的情况下,您想要反序列化 SocketAddr
。问题是缓冲区中的数据与您要借用的数据的形式不同。 Serde 通过 Display
将 SocketAddr
s 序列化为字符串,例如 this implemention for SocketAddrV4
。但是 SocketAddr
本身存储为一个 32 位整数和一个 16 位整数。你不能把一个当作另一个来借;需要进行某种解析,然后有人需要拥有结果数据。 Serde 逻辑上让您的结构拥有该数据。即使在二进制序列化中,也不能保证序列化数据的布局与结构的布局匹配,因此需要进行解析。
这是通过 Deserialize
serde 提供的实现在类型系统中编码的。 This page 有完整列表。您可以看到 &'a str
的实现,其中 Deserializer
('de
) 的生命周期超过 'a
。没有实现对大多数其他类型的引用,包括 &SocketAddr
.
这个 serde 问题 linked by PitaJ 显示了一个很好的最小代码示例。