How to parse Vec<T> type variable inside of Struct

How to parse the storage type Vec as main type and picked generic type.
i.e, Vec and String.
That's because I want to make a function call like this
storage = Vec::new(String::from("xxx"))

main.rs

Struct example {
  storage: Vec<String>
}

I’m not entirely understanding your question here, in particular what you mean by parsing in this context, but taking your code example, it seems like you’re trying to initialize the field storage in a struct with a value of Vec<String> type. The right syntax for creating a vector with one or a handful of elements is to use the vec![...] macro. To give a code example:

struct Example {
    storage: Vec<String>,
}

fn main() {
    let ex = Example {
        storage: vec!["xxx".to_string()],
    };
}

I'd like to parse the type using syn::parse_str() function and in this case, I get the whole type: Vec<String> for the data variable. I want to make it in two streams like Vec and String so that I can play with two different types.

The syn crate is (AFAIK) mostly meant for writing procedural macros. I’m not entirely sure of what’s your use case here. What are you trying to achieve? Do you have some kind of textual input data you’re trying to turn into a Rust data structure? If yes, what format is it in?

you're right. i am making a new macro and this is to define a Default impl for the macro.

Oh, wait, are you saying you’re trying to parse the type, i.e. “Vec<String>” itself?

Here's what I am doing now. And I want to get separated types from ty in default_generator function
src/derived_simple/libs.rs

#[proc_macro_derive(Simple)]

pub fn derived_simple(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);
    let name = input.ident;
    let generics = add_trait_bounds(input.generics);
    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
    let defaults = default_generator(&input.data);
    let gen = quote! {
        impl #impl_generics Default for #name #ty_generics #where_clause {
            fn default() -> Self {
                #name {
                    #defaults
                }
            }
        }
    };
    gen.into()
}
fn add_trait_bounds(mut generics: Generics) -> Generics {
    for param in &mut generics.params {
        if let GenericParam::Type(ref mut type_param) = *param {
            type_param.bounds.push(parse_quote!(simple::Simple));
        }
    }
    generics
}
fn default_generator(data: &Data) -> proc_macro2::TokenStream {
    match *data {
        Data::Struct(ref data) => {
            match data.fields {
                Fields::Named(ref fields) => {
                    let recurse = fields.named.iter().map(|f| {
                        let name = &f.ident;
                        let ty = &f.ty;  // ty => Vec<String>, I want to make it separated into Vec and String
                        quote_spanned! {f.span() => #name: #ty,}
                    });
                    quote! {#(#recurse)*}
                }
                Fields::Unnamed(ref fields) => {
                    quote! {0}
                }
                Fields::Unit => {
                    quote! {0}
                }
            }
        }
        Data::Enum(_) | Data::Union(_) => unimplemented!(),
    }
}

src/main.rs

#[derive(Simple)]
struct Storage {
   data: Vec<String>
}

yes

I haven’t written any procedural macros myself yet, but looking at the syn crate docs, it seems to me like a simple type such as Vec<String> should be represented as a Type::Path containing a TypePath with qself: None. And the path field containing a Path with a single segment. Finally, the PathSegment type gives you an ident which is going to be “Vec” and arguments that are in angled brackets. Ultimately then AngleBracketedGenericArguments has an args field that is going to be containing the GenericArgument::Type flavor of generic arguments. In case of Vec<String> I’d expect a single such GenericArgument::Type(...) element in that list that’s going to be your “String” type.

Of course, to be more general, you’ll maybe want to support longer paths, too. E.g. if someone writes std::vec::Vec<String> then it will be a path with 3 segments, “std”, “vec”, and “Vec<String>”; both std and vec are probably going to be PathSegments with arguments: PathArguments::None.

Thanks, let me try

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.