我正在编写一个派生过程宏,其中所有值都转换为Options
. 问题是结构中的任何Option
字段都可以包含在这些Option
类型中。就其本身而言,在我开始使用 serde 序列化数据之前,这并不是什么大问题。我希望能够跳过任何值为 的值None
,但在某些情况下它会变成类似Some(None)
or的值Some(CustomOption::None)
。这两种情况都比简单的没有任何意义None
,但我不能只写#[serde(skip_serializing_if = "Option::is_none")]
派生字段。当然,它们会输出null
JSON 格式的值。
基本上,我希望能够使用 syn 库来检查派生字段的内部值的类型是否将是 anOption
并将其展平为Option<T>
派生结构中的单数而不是Option<Option<T>>
类型。我希望 Rust 在泛型上有基于类型的模式匹配,但这并不是真的。
我可以想到这个问题的两种解决方案,但我真的想不出如何实现它们。第一个是遍历所有字段并找到Option
s,然后打开这些选项并重新包装它们,以便它们Option
在外面只有一个。此解决方案的一个潜在问题是,我可能必须Option
在进行计算后将它们重新包装到另一个中。第二种解决方案是找到Option
并相应地修改生成的代码,以便如果内部选项包含None
整个内容,则变为None
; 基本上只有一个辅助函数,如果字段是Option
. 关于如何实施这些或更好的解决方案的任何想法?
这是一个代码示例:
#[derive(Macro)]
struct X {
a: usize,
b: SomeType<String>,
c: Option<String>,
}
struct GeneratedX {
a: Option<usize>,
b: Option<SomeType<String>>,
c: Option<Option<String>>,
}
使用这样的函数来包装选项中的所有值:
pub fn wrap_typ_in_options(&self) -> TokenStream {
// self is a struct with the type Type in it along with some other items.
let typ: syn::Type = self.typ();
// attribute to check if should ignore a field.
if self.should_ignore() {
quote! { Option<#typ> }
} else {
quote! { Option<<#typ as module::Trait>::Type> }
}
}