Rust 直接调用 fmt 函数
Rust calling fmt function directly
我正在尝试根据参数实现不同的 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;
But how do I obtain instance of Formatter
directly?
据我所知,获得 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
实现,除了它需要一个额外的 format-options 参数(它忽略了因为 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
转发给您的自定义格式化特征(或者,如果您只想自定义格式化一种类型,只需自定义该对象上的方法)。
我正在尝试根据参数实现不同的 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;
But how do I obtain instance of
Formatter
directly?
据我所知,获得 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
实现,除了它需要一个额外的 format-options 参数(它忽略了因为 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
转发给您的自定义格式化特征(或者,如果您只想自定义格式化一种类型,只需自定义该对象上的方法)。