gvariant_macro/
lib.rs

1//! This is an implementation detail of the [gvariant](../gvariant/index.html) crate
2
3extern 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}