首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >直接调用fmt函数

直接调用fmt函数
EN

Stack Overflow用户
提问于 2021-06-05 18:43:30
回答 1查看 802关注 0票数 3

我试图根据参数实现不同的Display格式。比如print_json()print_pretty()。当然,我可以将其实现为返回字符串print_json(&self)->String的函数,但我想知道是否可以让print_json(&self,f: &mut Formatter<'_>) -> std::fmt::Resultprint_pretty(&self,f: &mut Formatter<'_>) -> std::fmt::Result代替。然后,我可以根据用例调用这些函数中的任何一个。但是如何直接获得Formatter的实例呢?理想情况下,我想做这样的事情

代码语言:javascript
复制
let mut string = String::new();
my_object.print_pretty(&mut string);
return string;
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-06-05 20:01:38

但是如何直接获得Formatter的实例呢?

据我所知,获得格式化程序的唯一方法是通过实现Display或其他格式化特性来接收格式化程序。

基于以下核心特性,我实现了自己的方案来添加更多的格式化选项:

代码语言:javascript
复制
/// 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的自定义格式。它看起来就像一个DebugDisplay实现,只不过它需要一个额外的格式-选项参数(它会忽略这个参数,因为StatusText没有带任何额外的选项):

代码语言:javascript
复制
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)
    }
}

使用这些工具的代码示例如下:

代码语言:javascript
复制
let mut string = String::new();
write!(string, "{}", my_object.custom_format(Pretty)).unwrap();
return string;

"{}"格式字符串不再控制格式;它只是一个占位符,完全可以通过实现Display (以及Debug)的CustomFormatWrapper调用格式机制来调用自定义格式:

代码语言:javascript
复制
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,以转发到您的自定义格式特征(或者,如果您只想自定义一种类型,那么只需要该对象上的方法)。

链接到上下文中的完整源代码

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67852867

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档