difftreelog
refactor(versioning) remove multiversion
in: master
1 file changed
crates/struct-versioning/src/lib.rsdiffbeforeafterboth3use syn::{3use syn::{4 parse::{Parse, ParseStream},4 parse::{Parse, ParseStream},5 Token, LitInt, parse_macro_input, ItemStruct, Error, Fields, Result, Field,5 Token, LitInt, parse_macro_input, ItemStruct, Error, Fields, Result, Field, Expr,6 punctuated::Punctuated, Expr, parenthesized,6 parenthesized,7};7};8use quote::quote;8use quote::quote;9918 current_version: u32,18 current_version: u32,19 first_version: u32,19 first_version: u32,20 upper: bool,20 upper: bool,21 versions: bool,22}21}232224/// #[versioned(version = 2)]23/// #[versioned(version = 2)]27 let mut current_version = None::<u32>;26 let mut current_version = None::<u32>;28 let mut first_version = None::<u32>;27 let mut first_version = None::<u32>;29 let mut upper = false;28 let mut upper = false;30 let mut versions = false;312932 loop {30 loop {33 if input.is_empty() {31 if input.is_empty() {53 } else if lookahead.peek(kw::upper) {51 } else if lookahead.peek(kw::upper) {54 input.parse::<kw::upper>()?;52 input.parse::<kw::upper>()?;55 upper = true;53 upper = true;56 } else if lookahead.peek(kw::versions) {54 } else {57 input.parse::<kw::version>()?;58 versions = true;59 } else {60 return Err(lookahead.error())55 return Err(lookahead.error());61 }56 }625763 if input.is_empty() {58 if input.is_empty() {64 break59 break;65 } else if input.peek(Token![,]) {60 } else if input.peek(Token![,]) {66 input.parse::<Token![,]>()?;61 input.parse::<Token![,]>()?;67 continue62 continue;68 } else {63 } else {69 return Err(input.error("unexpected token"))64 return Err(input.error("unexpected token"));70 }65 }71 }66 }72 let first_version = first_version.unwrap_or(1);67 let first_version = first_version.unwrap_or(1);73 let current_version = current_version.unwrap_or(first_version);68 let current_version = current_version.unwrap_or(first_version);746975 if current_version == 0 || first_version == 0 || first_version > current_version {70 if current_version == 0 || first_version == 0 || first_version > current_version {76 return Err(Error::new(input.span(), "1 <= first_version <= version"))71 return Err(Error::new(input.span(), "1 <= first_version <= version"));77 }72 }787379 Ok(Self {74 Ok(Self {80 current_version,75 current_version,81 first_version,76 first_version,82 upper,77 upper,83 versions,84 })78 })85 }79 }86}80}225 quote! {#ty}226 ))223 }227 }224 _ => {},228 _ => {}225 }229 }226 }230 }227 }231 }236 .filter(|(v, _)| !v.exists_on(version - 1) && v.exists_on(version))242 .filter(|(v, _)| !v.exists_on(version - 1) && v.exists_on(version))237 .map(|(v, f)| {243 .map(|(v, f)| {238 let name = f.ident.as_ref().unwrap();244 let name = f.ident.as_ref().unwrap();239 let value = v.upper.clone().unwrap_or_else(|| Expr::Verbatim(Error::new_spanned(f, "missing upper declaration").to_compile_error()));245 let value = v.upper.clone().unwrap_or_else(|| {246 Expr::Verbatim(247 Error::new_spanned(f, "missing upper declaration").to_compile_error(),248 )249 });240 quote! { #name: #value }250 quote! { #name: #value }241 });251 });242 let passed_fields = fields.iter()252 let passed_fields = fields275 let ident = &input.ident;288 let ident = &input.ident;276 let last_version = format_ident!("{}Version{}", input.ident, attr.current_version);289 let last_version = format_ident!("{}Version{}", input.ident, attr.current_version);277278 let versions = if attr.versions {279 let name = format_ident!("{}Versions", input.ident);280 let versions = (attr.first_version..=attr.current_version).map(|v| {281 let var_name = format_ident!("V{}", v);282 let var_type = format_ident!("{}Version{}", input.ident, v);283 quote! {284 #var_name(#var_type),285 }286 });287 let versions = (attr.first_version..=attr.current_version).map(|this_version| {288 let var_name = format_ident!("V{}", this_version);289 let stages = (this_version+1..=attr.current_version).map(|v| {290 let var_type = format_ident!("{}Version{}", input.ident, v);291 quote! {292 let v = #var_type::from(v);293 }294 });295 quote! {296 #var_name(v) => {297 #(#stages)*298 v299 }300 }301 }).collect::<Vec<_>>();302 quote! {303 #vis enum #name {304 #(#versions)*305 }306 impl struct_versioning::Versions for #name {307 type Last = #last_version;308 fn up(self) -> Self::Last {309 match self {310 #(#versions)*311 }312 }313 }314 }315 } else {quote!{}};316290317 quote! {291 quote! {318 #(#out)*292 #(#out)*319293320 #vis type #ident #ty_generics = #last_version #ty_generics;294 #vis type #ident #ty_generics = #last_version #ty_generics;321322 #versions323 }295 }324 .into()296 .into()325}297}