1#![feature(proc_macro_diagnostic)]
2
3use proc_macro::TokenStream;
4use quote::quote;
5use syn::{parse_macro_input, LitStr};
6
7const fn is_non_control_ascii_char(byte: u8) -> bool {
8 byte > 0x1f && byte < 0x80
9}
10
11#[proc_macro]
12pub fn fix_str(ts: TokenStream) -> TokenStream {
13 let input = parse_macro_input!(ts as LitStr);
14
15 input.value();
16
17 for (i, c) in input.value().bytes().enumerate() {
18 if !is_non_control_ascii_char(c) {
19 input
20 .span()
21 .unwrap()
22 .error(format!("wrong byte found at position {i}"))
23 .emit();
24 return TokenStream::new();
25 }
26 }
27
28 quote! {
29 unsafe { FixStr::from_ascii_unchecked(#input.as_bytes()) }
30 }
31 .into()
32}