gpt4 book ai didi

rust - 使用 syn 时如何从 Option 获取 T?

转载 作者:行者123 更新时间:2023-11-29 08:02:03 25 4
gpt4 key购买 nike

我正在使用 syn解析 Rust 代码。当我使用 field.ty 读取命名字段的类型时, 我得到一个 syn::Type .当我使用 quote!{#ty}.to_string() 打印它时我得到 "Option<String>" .

我怎样才能得到 "String" ?我想用 #tyquote!打印 "String"而不是 "Option<String>" .

我想生成如下代码:

impl Foo {
pub set_bar(&mut self, v: String) {
self.bar = Some(v);
}
}

开始于

struct Foo {
bar: Option<String>
}

我的尝试:

let ast: DeriveInput = parse_macro_input!(input as DeriveInput);

let data: Data = ast.data;

match data {
Data::Struct(ref data) => match data.fields {
Fields::Named(ref fields) => {

fields.named.iter().for_each(|field| {
let name = &field.ident.clone().unwrap();

let ty = &field.ty;
quote!{
impl Foo {
pub set_bar(&mut self, v: #ty) {
self.bar = Some(v);
}
}
};
});
}
_ => {}
},
_ => panic!("You can derive it only from struct"),
}

最佳答案

我的更新版本 the response from @Boiethios ,在公共(public) crate 中测试和使用,支持 Option 的多种语法:

  • 选项
  • std::option::Option
  • ::std::option::Option
  • 核心::选项::选项
  • ::core::option::Option
fn extract_type_from_option(ty: &syn::Type) -> Option<&syn::Type> {
use syn::{GenericArgument, Path, PathArguments, PathSegment};

fn extract_type_path(ty: &syn::Type) -> Option<&Path> {
match *ty {
syn::Type::Path(ref typepath) if typepath.qself.is_none() => Some(&typepath.path),
_ => None,
}
}

// TODO store (with lazy static) the vec of string
// TODO maybe optimization, reverse the order of segments
fn extract_option_segment(path: &Path) -> Option<&PathSegment> {
let idents_of_path = path
.segments
.iter()
.into_iter()
.fold(String::new(), |mut acc, v| {
acc.push_str(&v.ident.to_string());
acc.push('|');
acc
});
vec!["Option|", "std|option|Option|", "core|option|Option|"]
.into_iter()
.find(|s| &idents_of_path == *s)
.and_then(|_| path.segments.last())
}

extract_type_path(ty)
.and_then(|path| extract_option_segment(path))
.and_then(|path_seg| {
let type_params = &path_seg.arguments;
// It should have only on angle-bracketed param ("<String>"):
match *type_params {
PathArguments::AngleBracketed(ref params) => params.args.first(),
_ => None,
}
})
.and_then(|generic_arg| match *generic_arg {
GenericArgument::Type(ref ty) => Some(ty),
_ => None,
})
}

关于rust - 使用 syn 时如何从 Option<T> 获取 T?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55271857/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com