| 1 | extern crate proc_macro; |
| 2 | |
| 3 | use proc_macro::TokenStream; |
| 4 | |
| 5 | use proc_macro_hack::proc_macro_hack; |
| 6 | use quote::quote; |
| 7 | use syn::{parse_macro_input, LitStr}; |
| 8 | |
| 9 | use unic_langid_impl::{subtags, LanguageIdentifier}; |
| 10 | |
| 11 | #[proc_macro_hack ] |
| 12 | pub fn lang(input: TokenStream) -> TokenStream { |
| 13 | let id: LitStr = parse_macro_input!(input as LitStr); |
| 14 | let parsed: subtags::Language = id.value().parse().expect(msg:"Malformed Language Subtag" ); |
| 15 | |
| 16 | let lang: Option<u64> = parsed.into(); |
| 17 | let lang: TokenStream = if let Some(lang: u64) = 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 ] |
| 29 | pub fn script(input: TokenStream) -> TokenStream { |
| 30 | let id: LitStr = parse_macro_input!(input as LitStr); |
| 31 | let parsed: subtags::Script = id.value().parse().expect(msg:"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 ] |
| 41 | pub fn region(input: TokenStream) -> TokenStream { |
| 42 | let id: LitStr = parse_macro_input!(input as LitStr); |
| 43 | let parsed: subtags::Region = id.value().parse().expect(msg:"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 ] |
| 53 | pub fn variant_fn(input: TokenStream) -> TokenStream { |
| 54 | let id: LitStr = parse_macro_input!(input as LitStr); |
| 55 | let parsed: subtags::Variant = id.value().parse().expect(msg:"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 ] |
| 65 | pub 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 | } |
| 109 | |