但是我如何直接获取Formatter
实例?
据我所知,获得Formatter
的唯一方法是通过实现Display
或其他格式化特性之一来接收它。
我已经根据这个核心特性实现了自己的方案,以添加更多的格式化选项:
pub trait CustomFormat<F: Copy> {
fn custom_format(&self, format_type: F) -> CustomFormatWrapper<'_, F, Self> {
CustomFormatWrapper(format_type, self)
}
fn fmt(&self, fmt: &mut fmt::Formatter<'_>, format_type: F) -> fmt::Result;
}
希望支持额外格式类型的类型需要实现 CustomFormat<F>
,其中F
是特定的格式类型或格式选项;在您的用例中,它们可以是struct Json;
和struct Pretty;
。或者,您可以有两个不同的 traits —— 我发现一个通用 trait 可以减少代码重复。
作为一个实现示例,在这里我定义了一个 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
),以转发到你自定义的格式化特性(或者如果你只想自定义格式化一种类型,则只需要该对象上的方法)。
完整源代码链接