1use proc_macro::TokenStream;
21use proc_macro2::Span;
22use proc_macro_error::{abort, proc_macro_error};
23use quote::quote_spanned;
24use semver::Version;
25use syn::{parse_macro_input, LitStr};
26
27#[proc_macro_error]
39#[proc_macro]
40pub fn version(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
41 let input = parse_macro_input!(input as LitStr);
42 let span = input.span();
43
44 parse_and_emit(&input.value(), span)
45}
46
47#[proc_macro_error]
59#[proc_macro]
60pub fn env_version(input: proc_macro::TokenStream) -> TokenStream {
61 let input = parse_macro_input!(input as LitStr);
62 let span = input.span();
63
64 let input = std::env::var(input.value()).unwrap_or_else(|e| abort!(span, "{}", e));
65
66 parse_and_emit(&input, span)
67}
68
69fn parse_and_emit(input: &str, span: Span) -> TokenStream {
70 let version: Version = input.parse().unwrap_or_else(|e| abort!(span, "{}", e));
71
72 if !version.pre.is_empty() {
73 abort!(span, "Version can't have a pre-release identifier.");
74 }
75 if !version.build.is_empty() {
76 abort!(span, "Version can't have a build metadata identifier.");
77 }
78
79 emit(&version, span)
80}
81
82fn emit(version: &Version, span: Span) -> TokenStream {
83 let major = version.major;
84 let minor = version.minor;
85 let patch = version.patch;
86
87 quote_spanned! {
88 span =>
89 ::semver::Version {
90 major: #major,
91 minor: #minor,
92 patch: #patch,
93 pre: ::semver::Prerelease::EMPTY,
94 build: ::semver::BuildMetadata::EMPTY,
95 }
96 }
97 .into()
98}