自定义数据格式 - `Deserializer::deserialize_str` 实现
Custom data format - `Deserializer::deserialize_str` implementation
Link 去游乐场
我正在尝试使用 serde
实现自定义数据格式,我一直在努力使用 deserialize_str
方法
pub struct Deserializer<R> {
rdr: R,
}
impl<'de, 'a, R: io::Read + 'de> de::Deserializer<'de> for &'a mut Deserializer<R> {
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
let len = self.read_i16()?; // implemention below
if len == 0 || len == -1 {
return visitor.visit_borrowed_str("");
}
let len = len as usize;
let buf = self.read_exact(len)?; // implemention below
let out_str = std::str::from_utf8(&buf)?;
// visitor.visit_borrowed_str(out_str) doesn't compile
visitor.visit_str(out_str) // compiles but errors
}
}
impl<R: io::Read> Deserializer<R> {
fn read_exact(&mut self, len: usize) -> Result<Vec<u8>> {
let mut buf = vec![0; len];
self.rdr.read_exact(&mut buf)?;
Ok(buf)
}
fn read_i16(&mut self) -> io::Result<i8> {
self.rdr.read_i16::<byteorder::NetworkEndian>()
}
}
使用visitor.visit_borrowed_str(out_str)
时,出现错误
|
94 | impl<'de, 'a, R: io::Read + 'de> de::Deserializer<'de> for &'a mut Deserializer<R> {
| --- lifetime `'de` defined here
...
149 | let out_str = std::str::from_utf8(&buf)?;
| ^^^^ borrowed value does not live long enough
150 |
151 | visitor.visit_borrowed_str(out_str)
| ----------------------------------- argument requires that `buf` is borrowed for `'de`
152 | }
| - `buf` dropped here while still borrowed
我知道 out_str
需要以某种方式比它的范围更长寿,但我找不到解决它的方法。
要使用 visit_borrowed_str
,您需要向它传递一个与您的反序列化器一样长寿的东西的引用。使用 read_exact
创建一个新的临时 Vec
是行不通的,您需要访问底层切片,例如std::str::from_utf8(self.rdr.get_ref()[self.rdr.position()..][..len])
或类似的。如果你想让 R
保持通用 std::io::Read
,我认为你不能使用 visit_borrowed_str
。 serde_json
例如通过有一个特殊的 Read
来处理这个问题,returns 对基础数据的引用 if it can, and then only uses visit_borrowed_str
if it does have a reference 对基础数据的引用。
此外,如果您要求反序列化器反序列化为借用的字符串,而它不能反序列化,则它必然会出错。 holds true 也适用于 serde_json
。所以来自 visit_str
的错误不是你的反序列化器实现中的错误,而是你如何使用反序列化器的错误。您应该要求反序列化为 String
或 Cow<str>
(并不是说您的序列化程序可以给您 Cow::Borrowed
,但要求 &str
并不是对于任何解串器来说都是个好主意,通常建议使用 Cow<str>
。
Link 去游乐场
我正在尝试使用 serde
实现自定义数据格式,我一直在努力使用 deserialize_str
方法
pub struct Deserializer<R> {
rdr: R,
}
impl<'de, 'a, R: io::Read + 'de> de::Deserializer<'de> for &'a mut Deserializer<R> {
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
let len = self.read_i16()?; // implemention below
if len == 0 || len == -1 {
return visitor.visit_borrowed_str("");
}
let len = len as usize;
let buf = self.read_exact(len)?; // implemention below
let out_str = std::str::from_utf8(&buf)?;
// visitor.visit_borrowed_str(out_str) doesn't compile
visitor.visit_str(out_str) // compiles but errors
}
}
impl<R: io::Read> Deserializer<R> {
fn read_exact(&mut self, len: usize) -> Result<Vec<u8>> {
let mut buf = vec![0; len];
self.rdr.read_exact(&mut buf)?;
Ok(buf)
}
fn read_i16(&mut self) -> io::Result<i8> {
self.rdr.read_i16::<byteorder::NetworkEndian>()
}
}
使用visitor.visit_borrowed_str(out_str)
时,出现错误
|
94 | impl<'de, 'a, R: io::Read + 'de> de::Deserializer<'de> for &'a mut Deserializer<R> {
| --- lifetime `'de` defined here
...
149 | let out_str = std::str::from_utf8(&buf)?;
| ^^^^ borrowed value does not live long enough
150 |
151 | visitor.visit_borrowed_str(out_str)
| ----------------------------------- argument requires that `buf` is borrowed for `'de`
152 | }
| - `buf` dropped here while still borrowed
我知道 out_str
需要以某种方式比它的范围更长寿,但我找不到解决它的方法。
要使用 visit_borrowed_str
,您需要向它传递一个与您的反序列化器一样长寿的东西的引用。使用 read_exact
创建一个新的临时 Vec
是行不通的,您需要访问底层切片,例如std::str::from_utf8(self.rdr.get_ref()[self.rdr.position()..][..len])
或类似的。如果你想让 R
保持通用 std::io::Read
,我认为你不能使用 visit_borrowed_str
。 serde_json
例如通过有一个特殊的 Read
来处理这个问题,returns 对基础数据的引用 if it can, and then only uses visit_borrowed_str
if it does have a reference 对基础数据的引用。
此外,如果您要求反序列化器反序列化为借用的字符串,而它不能反序列化,则它必然会出错。 holds true 也适用于 serde_json
。所以来自 visit_str
的错误不是你的反序列化器实现中的错误,而是你如何使用反序列化器的错误。您应该要求反序列化为 String
或 Cow<str>
(并不是说您的序列化程序可以给您 Cow::Borrowed
,但要求 &str
并不是对于任何解串器来说都是个好主意,通常建议使用 Cow<str>
。