1extern crate proc_macro;
4use proc_macro::TokenStream;
5use std::{collections::HashSet, error::Error};
6
7mod generate_impl;
8mod type_parser;
9use generate_impl::{escape, size_of};
10use syn::{parse_macro_input, LitStr};
11
12use type_parser::{one, GVariantType};
13
14#[proc_macro]
15pub fn gv_type(input: TokenStream) -> TokenStream {
16 let typestr = parse_macro_input!(input as LitStr).value();
17 type_for_typestr(typestr.as_ref()).unwrap().parse().unwrap()
18}
19
20#[proc_macro]
21pub fn define_gv(input: TokenStream) -> TokenStream {
22 let typestr = parse_macro_input!(input as LitStr).value();
23 let mut defined_types: HashSet<GVariantType> = HashSet::new();
24 generate_impl::generate_types(&one(typestr.as_ref()).unwrap(), &mut defined_types)
25 .unwrap()
26 .parse()
27 .unwrap()
28}
29
30fn type_for_typestr(gv_typestr: &[u8]) -> Result<String, Box<dyn Error>> {
31 let spec = type_parser::one(gv_typestr)?;
32 Ok(marker_type(&spec))
33}
34
35pub(crate) fn marker_type(t: &GVariantType) -> String {
36 match t {
37 GVariantType::B => "Bool".to_string(),
38 GVariantType::Y => "u8".to_string(),
39 GVariantType::N => "i16".to_string(),
40 GVariantType::Q => "u16".to_string(),
41 GVariantType::I => "i32".to_string(),
42 GVariantType::U => "u32".to_string(),
43 GVariantType::X => "i64".to_string(),
44 GVariantType::T => "u64".to_string(),
45 GVariantType::D => "f64".to_string(),
46 GVariantType::S => "Str".to_string(),
47 GVariantType::O => "Str".to_string(),
48 GVariantType::G => "Str".to_string(),
49 GVariantType::V => "Variant".to_string(),
50 GVariantType::A(t) => match size_of(t) {
51 None => format!("NonFixedWidthArray::<{}>", marker_type(t)),
52 Some(_) => format!("[{}]", marker_type(t)),
53 },
54 GVariantType::M(t) => match size_of(t) {
55 None => format!("MaybeNonFixedSize::<{}>", marker_type(t)),
56 Some(_) => format!("MaybeFixedSize::<{}>", marker_type(t)),
57 },
58 GVariantType::Tuple(_) | GVariantType::DictItem(_) => {
59 format!("Structure{name}", name = escape(t.to_string()))
60 }
61 }
62}