我试图根据参数实现不同的Display
格式。比如print_json()
和print_pretty()
。当然,我可以将其实现为返回字符串print_json(&self)->String
的函数,但我想知道是否可以让print_json(&self,f: &mut Formatter<'_>) -> std::fmt::Result
和print_pretty(&self,f: &mut Formatter<'_>) -> std::fmt::Result
代替。然后,我可以根据用例调用这些函数中的任何一个。但是如何直接获得Formatter
的实例呢?理想情况下,我想做这样的事情
let mut string = String::new();
my_object.print_pretty(&mut string);
return string;
发布于 2021-06-05 12:01:38
但是如何直接获得
Formatter
的实例呢?
据我所知,获得格式化程序的唯一方法是通过实现Display
或其他格式化特性来接收格式化程序。
基于以下核心特性,我实现了自己的方案来添加更多的格式化选项:
/// Objects for which alternate textual representations can be generated.
/// These are analogous to [`Display`] and [`Debug`], but have additional options.
pub trait CustomFormat<F: Copy> {
/// Wrap this value so that when formatted with [`Debug`] or [`Display`] it uses
/// the given custom format instead.
fn custom_format(&self, format_type: F) -> CustomFormatWrapper<'_, F, Self> {
CustomFormatWrapper(format_type, self)
}
/// Implement this to provide custom formatting for this type.
fn fmt(&self, fmt: &mut fmt::Formatter<'_>, format_type: F) -> fmt::Result;
}
希望支持其他格式的类型实现CustomFormat<F>
,其中F
是特定的格式类型或格式选项;对于您的用例,它们可以是struct Json;
和struct Pretty;
。或者,你可以有两个不同的特征--我刚刚发现,拥有一个通用的特性可以减少代码的重复。
作为实现示例,这里我定义了std::time::Duration
的自定义格式。它看起来就像一个Debug
或Display
实现,只不过它需要一个额外的格式-选项参数(它会忽略这个参数,因为StatusText
没有带任何额外的选项):
impl CustomFormat<StatusText> for Duration {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>, _: StatusText) -> fmt::Result {
write!(fmt, "{:5.2?} ms", (self.as_micros() as f32) / 1000.0)
}
}
使用这些工具的代码示例如下:
let mut string = String::new();
write!(string, "{}", my_object.custom_format(Pretty)).unwrap();
return string;
"{}"
格式字符串不再控制格式;它只是一个占位符,完全可以通过实现Display
(以及Debug
)的CustomFormatWrapper
调用格式机制来调用自定义格式:
pub struct CustomFormatWrapper<'a, F: Copy, T: CustomFormat<F> + ?Sized>(F, &'a T);
impl<'a, F: Copy, T: CustomFormat<F>> Debug for CustomFormatWrapper<'a, F, T> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
<T as CustomFormat<F>>::fmt(self.1, fmt, self.0)
}
}
impl<'a, F: Copy, T: CustomFormat<F>> Display for CustomFormatWrapper<'a, F, T> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
<T as CustomFormat<F>>::fmt(self.1, fmt, self.0)
}
}
这可能是一个过度设计的解决方案,为您的目的。所需的关键元素是包装器类型,它包含对要格式化的值的引用,并且它具有一些标准的格式化特征,如Display
,以转发到您的自定义格式特征(或者,如果您只想自定义一种类型,那么只需要该对象上的方法)。
https://stackoverflow.com/questions/67852867
复制相似问题