verty 0.1.0

procedural macro to generate different versions of a type
Documentation
use std::collections::HashMap;

use proc_macro2::{Ident, Span};

use crate::parse::args::{MacroArg, RenameSource};
use crate::util::error_sink::ErrorSink;

mod pseudo_macros;
pub mod type_;
pub mod impl_;

fn versioned_ident(ident: &Ident, version: usize) -> Ident {
	quote::format_ident!("{}V{}", ident, version)
}

#[derive(Default, Debug)]
pub struct Args {
	pub start: usize,
	pub end: Option<usize>,
	base: bool,
	enum_: bool,
	pub rename: HashMap<RenameSource, Ident>,
}

impl Args {
	pub fn from_raw(raw: Vec<(Span, MacroArg)>, errs: &mut ErrorSink) -> Self {
		let mut res = Self::default();

		let mut start_span = None::<(Span, bool)>;
		let mut end_span = None::<(Span, bool)>;
		let mut base_span = None::<(Span, bool)>;
		let mut enum_span = None::<(Span, bool)>;
		let mut rename_spans = HashMap::<RenameSource, (Span, bool)>::new();

		for (span, arg) in raw {
			match arg {
				MacroArg::Start(start) => {
					if let Some((fspan, errored)) = &mut start_span {
						if !*errored {
							errs.push(syn::Error::new(
								*fspan,
								"`start` can't be specified multiple times",
							));
							*errored = true;
						}
						errs.push(syn::Error::new(
							span,
							"`start` can't be specified multiple times",
						));
					} else {
						res.start = start;
						start_span = Some((span, false));
					}
				}
				MacroArg::End(end) => {
					if let Some((fspan, errored)) = &mut end_span {
						if !*errored {
							errs.push(syn::Error::new(
								*fspan,
								"`end` can't be specified multiple times",
							));
							*errored = true;
						}
						errs.push(syn::Error::new(
							span,
							"`end` can't be specified multiple times",
						));
					} else {
						res.end = Some(end);
						start_span = Some((span, false));
					}
				}
				MacroArg::Enum => {
					if let Some((fspan, errored)) = &mut enum_span {
						if !*errored {
							errs.push(syn::Error::new(
								*fspan,
								"`enum` can't be specified multiple times",
							));
							*errored = true;
						}
						errs.push(syn::Error::new(
							span,
							"`enum` can't be specified multiple times",
						));
					} else {
						// TODO: remove when implemented
						errs.push(syn::Error::new(span, "`enum` isn't implemented yet."));
						res.enum_ = true;
						enum_span = Some((span, false));
					}
				}
				MacroArg::Base => {
					if let Some((fspan, errored)) = &mut base_span {
						if !*errored {
							errs.push(syn::Error::new(
								*fspan,
								"`base` can't be specified multiple times",
							));
							*errored = true;
						}
						errs.push(syn::Error::new(
							span,
							"`base` can't be specified multiple times",
						));
					} else {
						// TODO: remove when implemented
						errs.push(syn::Error::new(span, "`base` isn't implemented yet."));
						res.base = true;
						base_span = Some((span, false));
					}
				}
				MacroArg::Rename(src, ident) => {
					if let Some((fspan, errored)) = rename_spans.get_mut(&src) {
						if !*errored {
							errs.push(syn::Error::new(
								*fspan,
								"`rename` can't be specified multiple times for the same source",
							));
							*errored = true;
						}
						errs.push(syn::Error::new(
							span,
							"`rename` can't be specified multiple times for the same source",
						));
					} else {
						res.rename.insert(src, ident);
						rename_spans.insert(src, (span, false));
					}
				}
			}
		}

		res
	}
}