unic_langid_macros_impl/
lib.rs

1extern crate proc_macro;
2
3use proc_macro::TokenStream;
4
5use proc_macro_hack::proc_macro_hack;
6use quote::quote;
7use syn::{parse_macro_input, LitStr};
8
9use unic_langid_impl::{subtags, LanguageIdentifier};
10
11#[proc_macro_hack]
12pub fn lang(input: TokenStream) -> TokenStream {
13    let id = parse_macro_input!(input as LitStr);
14    let parsed: subtags::Language = id.value().parse().expect("Malformed Language Subtag");
15
16    let lang: Option<u64> = parsed.into();
17    let lang = if let Some(lang) = lang {
18        quote!(unsafe { $crate::subtags::Language::from_raw_unchecked(#lang) })
19    } else {
20        quote!(None)
21    };
22
23    TokenStream::from(quote! {
24        #lang
25    })
26}
27
28#[proc_macro_hack]
29pub fn script(input: TokenStream) -> TokenStream {
30    let id = parse_macro_input!(input as LitStr);
31    let parsed: subtags::Script = id.value().parse().expect("Malformed Script Subtag");
32
33    let script: u32 = parsed.into();
34
35    TokenStream::from(quote! {
36        unsafe { $crate::subtags::Script::from_raw_unchecked(#script) }
37    })
38}
39
40#[proc_macro_hack]
41pub fn region(input: TokenStream) -> TokenStream {
42    let id = parse_macro_input!(input as LitStr);
43    let parsed: subtags::Region = id.value().parse().expect("Malformed Region Subtag");
44
45    let region: u32 = parsed.into();
46
47    TokenStream::from(quote! {
48        unsafe { $crate::subtags::Region::from_raw_unchecked(#region) }
49    })
50}
51
52#[proc_macro_hack]
53pub fn variant_fn(input: TokenStream) -> TokenStream {
54    let id = parse_macro_input!(input as LitStr);
55    let parsed: subtags::Variant = id.value().parse().expect("Malformed Variant Subtag");
56
57    let variant: u64 = parsed.into();
58
59    TokenStream::from(quote! {
60        unsafe { $crate::subtags::Variant::from_raw_unchecked(#variant) }
61    })
62}
63
64#[proc_macro_hack]
65pub fn langid(input: TokenStream) -> TokenStream {
66    let id = parse_macro_input!(input as LitStr);
67    let parsed: LanguageIdentifier = id.value().parse().expect("Malformed Language Identifier");
68
69    let (lang, script, region, variants) = parsed.into_parts();
70
71    let lang: Option<u64> = lang.into();
72    let lang = if let Some(lang) = lang {
73        quote!(unsafe { $crate::subtags::Language::from_raw_unchecked(#lang) })
74    } else {
75        quote!($crate::subtags::Language::default())
76    };
77
78    let script = if let Some(script) = script {
79        let script: u32 = script.into();
80        quote!(Some(unsafe { $crate::subtags::Script::from_raw_unchecked(#script) }))
81    } else {
82        quote!(None)
83    };
84
85    let region = if let Some(region) = region {
86        let region: u32 = region.into();
87        quote!(Some(unsafe { $crate::subtags::Region::from_raw_unchecked(#region) }))
88    } else {
89        quote!(None)
90    };
91
92    let variants = if !variants.is_empty() {
93        let v: Vec<_> = variants
94            .iter()
95            .map(|v| {
96                let variant: u64 = v.into();
97                quote!(unsafe { $crate::subtags::Variant::from_raw_unchecked(#variant) })
98            })
99            .collect();
100        quote!(Some(Box::new([#(#v,)*])))
101    } else {
102        quote!(None)
103    };
104
105    TokenStream::from(quote! {
106        unsafe { $crate::LanguageIdentifier::from_raw_parts_unchecked(#lang, #script, #region, #variants) }
107    })
108}