byte_strings_proc_macros/
mod.rs1#![allow(nonstandard_style, unused_imports)]
5
6use ::core::{
7 mem,
8 ops::Not as _,
9};
10use ::proc_macro::{
11 TokenStream,
12};
13use ::proc_macro2::{
14 Span,
15 TokenStream as TokenStream2,
16 TokenTree as TT,
17};
18use ::quote::{
19 format_ident,
20 quote,
21 quote_spanned,
22 ToTokens,
23};
24use ::syn::{*,
25 parse::{Parse, Parser, ParseStream},
26 punctuated::Punctuated,
27 Result, spanned::Spanned,
29};
30
31use input_bytes::Input;
32mod input_bytes;
33
34#[proc_macro] pub
35fn concat_bytes (
36 input: TokenStream,
37) -> TokenStream
38{
39 concat_bytes_impl(input.into())
40 .unwrap_or_else(|err| {
42 let mut errors =
43 err .into_iter()
44 .map(|err| Error::new(
45 err.span(),
46 format_args!("`#[byte_strings::concat_bytes]`: {}", err),
47 ))
48 ;
49 let mut err = errors.next().unwrap();
50 errors.for_each(|cur| err.combine(cur));
51 err.to_compile_error()
52 })
53 .into()
54}
55
56fn concat_bytes_impl (
57 input: TokenStream2,
58) -> Result<TokenStream2>
59{
60 let Input(_, ref mut bytes) = parse2(input)?;
61 let byte_string_literal = LitByteStr::new(bytes, Span::call_site());
62 Ok(byte_string_literal.into_token_stream())
63}
64
65#[proc_macro] pub
66fn c_str (
67 input: TokenStream,
68) -> TokenStream
69{
70 c_str_impl(input.into())
71 .unwrap_or_else(|err| {
73 let mut errors =
74 err .into_iter()
75 .map(|err| Error::new(
76 err.span(),
77 format_args!("`#[byte_strings::c_str]`: {}", err),
78 ))
79 ;
80 let mut err = errors.next().unwrap();
81 errors.for_each(|cur| err.combine(cur));
82 err.to_compile_error()
83 })
84 .into()
85}
86
87fn c_str_impl (
88 input: TokenStream2,
89) -> Result<TokenStream2>
90{
91 let Input(ref crate_, ref mut bytes) = parse2(input)?;
92 match bytes.iter().position(|&b| b == b'\0') {
93 | Some(i) if i < bytes.len() - 1 => {
94 return Err(Error::new(
96 Span::call_site(),
97 format!("Inner null byte at index {}", i),
98 ));
99 },
100 | None => {
101 bytes.reserve_exact(1);
103 bytes.push(b'\0');
104 },
105 | Some(_last_byte) => {
106 },
108 }
109 let byte_string_literal = LitByteStr::new(bytes, Span::call_site());
110 Ok(quote!(
111 {
112 #[allow(unused_unsafe)] {
113 unsafe {
114 #crate_::__::core::ffi::CStr::from_bytes_with_nul_unchecked(
115 #byte_string_literal
116 )
117 }
118 }
119 }
120 ))
121}