提问人:Richard Neumann 提问时间:11/8/2023 更新时间:11/8/2023 访问量:44
如何实现 serde::ser::Error 的调试
How to implement Debug for serde::ser::Error
问:
我正在为 serde 编写一个自定义序列化程序。
为此,我还需要一个自定义错误类型。
Serde 要求我为此实现。 反过来,要求我实现一个方法,其中参数仅受特征边界的限制。
所以我想出了这个:serde::ser::Error
serde::ser::Error
custom()
std::fmt::Display
use std::fmt::{Debug, Display, Formatter};
#[derive(Debug)]
pub enum Error {
Custom(Box<dyn Display>),
CannotSerializeMap,
}
impl Display for Error {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::Custom(error) => Display::fmt(error, f),
Self::CannotSerializeMap => write!(f, "cannot serialize map"),
}
}
}
impl std::error::Error for Error {}
impl serde::ser::Error for Error {
fn custom<T>(msg: T) -> Self
where
T: Display,
{
Self::Custom(Box::new(msg))
}
}
但是,我不能推导出 ,这是必需的,而 又是必需的,因为不实现 。
我无法实现它,因为特征本身都不在我的板条箱中。
我也无法为 in 添加适当的约束,因为它会破坏特征的契约。Debug
std::error::Error
serde::ser::Error
Box<dyn Display>
Debug
Debug
Box
Debug
T
custom()
我该如何解决这个问题?
答:
2赞
Cerberus
11/8/2023
#1
你可以根据两个事实使用一个小技巧:
- 实现的所有内容也实现
ToString
(通过将值格式化为空字符串)。Display
Display
- 可以使用
From
实现创建 from。Box<dyn Error>
String
因此,每当你有一些 ,你可以得到一个 ,而不是像这样(playground):T: Display
Box<dyn Display>
Box<dyn Error>
use std::fmt::{Debug, Display, Formatter};
#[derive(Debug)]
pub enum Error {
Custom(Box<dyn std::error::Error>),
CannotSerializeMap,
}
impl serde::ser::Error for Error {
fn custom<T>(msg: T) -> Self
where
T: Display,
{
Self::Custom(msg.to_string().into())
}
}
然后开箱即用(双关语),因为是.#[derive(Debug)]
dyn Error
Debug
评论
1赞
Chayim Friedman
11/9/2023
在这一点上,为什么不直接存储呢?它既便宜又允许更多功能。当然,您可能希望使用原始类型,但无论如何,这个技巧都不起作用。String
评论
Debug for Error