byte_strings_proc_macro/
identity_non_null.rs1::cfg_if::cfg_if![ if #[cfg(feature = "proc-macro-hygiene")]
2{
3 #[cfg(any())]
4 mod objective {
5 macro_rules! identity_non_null {(
6 $input_bytestr_literal:expr
7 ) => (
8 if $input_bytestr_literal.contains(&0) {
9 compile_error!("input contains a null byte")
10 } else {
11 $input_bytestr_literal
12 }
13 )}
14 }
15
16 #[doc(hidden)]
17 #[proc_macro]
18 pub fn identity_non_null (
19 input: proc_macro::TokenStream,
20 ) -> proc_macro::TokenStream
21 {
22 let input_expr = syn::parse_macro_input!(input as syn::Expr);
23
24 match input_expr {
25 syn::Expr::Lit(
28 syn::ExprLit {
29 lit: syn::Lit::ByteStr(ref bytes),
30 ..
31 }
32 ) => {
33 if bytes.value().contains(&0) {
34 throw!(input_expr.span()=>
35 "input contains a null byte"
36 );
37 } else {
38 proc_macro::TokenStream::from(quote::quote! {
39 input_expr
40 })
41 }
42 },
43
44 _ => throw!(input_expr.span()=>
46 "expected a byte string literal"
47 ),
48 }
49 }
50}
51else
52{
53 #[cfg(any())]
54 mod objective {
55 macro_rules! const_identity_non_null {(
56 const $const_literal_name:ident = identity_non_null!(
57 $input_bytestr_literal:expr
58 );
59 ) => (
60 const $const_literal_name: &[u8; _] = b"_";
61 )}
62 }
63
64 struct ConstIdentityNonNull {
65 const_literal_name: syn::Ident,
66 input_bytestr_literal: syn::Expr,
67 }
68
69 impl Parse for ConstIdentityNonNull
70 {
71 fn parse (input: syn::parse::ParseStream) -> syn::parse::Result<Self>
72 {
73 macro_rules! parse_token {[$tt:tt] => (
74 input.parse::<syn::Token![$tt]>()?
75 )}
76
77 parse_token![ const ];
78 let const_literal_name: syn::Ident = input.parse()?;
79 parse_token![ = ];
80 input.parse::<kw::identity_non_null>()?;
81 parse_token![ ! ];
82
83 let input_bytestr_literal: syn::Expr = syn::group::
84 parse_parens(&input)?
85 .content
86 .parse()?
87 ;
88 parse_token![ ; ];
89 Ok(ConstIdentityNonNull {
90 const_literal_name,
91 input_bytestr_literal,
92 })
93 }
94 }
95
96 #[proc_macro]
97 pub fn const_identity_non_null (
98 input: proc_macro::TokenStream,
99 ) -> proc_macro::TokenStream
100 {
101 let ConstIdentityNonNull {
102 const_literal_name,
103 input_bytestr_literal: input_expr,
104 } = syn::parse_macro_input!(input);
105
106 match input_expr {
107 syn::Expr::Lit(
110 syn::ExprLit {
111 lit: syn::Lit::ByteStr(ref bytes),
112 ..
113 }
114 ) => {
115 if bytes.value().contains(&0) {
116 throw!(input_expr.span()=>
117 "input contains a null byte"
118 );
119 } else {
120 let len = syn::Expr::
121 Lit(syn::ExprLit {
122 attrs: vec![],
123
124 lit: syn::Lit::Int(syn::LitInt::new(
125 bytes.value().len() as u64,
127
128 syn::IntSuffix::Usize,
130
131 input_expr.span().clone(),
133 ))
134 })
135 ;
136
137 proc_macro::TokenStream::from(quote::quote! {
138 const #const_literal_name
139 : &'static [u8; #len]
140 = #input_expr
141 ;
142 })
143 }
144 },
145
146 _ => throw!(input_expr.span()=>
148 "expected a byte string literal"
149 ),
150 }
151 }
152}];