structstruck 0.5.1

Nested struct and enum definitions
Documentation
use proc_macro2::{Group, TokenStream};
use quote::ToTokens;
use venial::{Enum, NamedStructFields, Punctuated, TupleStructFields};

pub(crate) trait UpdateTokens {
    fn update_tokens(&mut self);
}

impl UpdateTokens for NamedStructFields {
    fn update_tokens(&mut self) {
        punctuated_to_group(&self.fields, &mut self.tk_braces);
    }
}

impl UpdateTokens for TupleStructFields {
    fn update_tokens(&mut self) {
        punctuated_to_group(&self.fields, &mut self.tk_parens);
    }
}

impl UpdateTokens for Enum {
    fn update_tokens(&mut self) {
        punctuated_to_group(&self.variants, &mut self.tk_braces);
    }
}

fn punctuated_to_group<T: ToTokens>(from: &venial::Punctuated<T>, to: &mut Group) {
    let mut group = TokenStream::new();
    for (field, punct) in from.iter() {
        field.to_tokens(&mut group);
        punct.to_tokens(&mut group);
    }
    let mut group = Group::new(to.delimiter(), group);
    group.set_span(to.span());
    *to = group;
}

pub(crate) fn modify_punctuated<T: Clone>(modify: &mut Punctuated<T>, mut f: impl FnMut(&mut T)) {
    let mut new: Punctuated<T> = Default::default();
    for (v, p) in modify.iter() {
        let mut v: T = v.clone();
        f(&mut v);
        new.push(v, Some(p.clone()));
    }
    *modify = new;
}