Skip to main content

encrust_macros/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![doc = include_str!("../README.md")]
3
4mod generator;
5mod parser;
6
7use proc_macro::TokenStream;
8use syn::parse_macro_input;
9
10use crate::generator::{
11    BytesFileReader, CStringFileReader, StringFileReader, ToEncrustedTokenStream,
12};
13use crate::parser::{FilePath, LiteralNode, ToHashBytes, ToHashString};
14
15/// Encrust a literal value before it is included in the binary.
16///
17/// Currently integers, strings and arrays of integers are accepted. Arrays can be
18/// nested arbitrarily deep.
19///
20/// Integers require their data type suffixed (`-1i8`, `127u16` etc).
21///
22/// # Examples
23/// ```
24/// # extern crate encrust_core as encrust;
25/// # use encrust_macros::encrust;
26/// let mut num = encrust!(0u8);
27/// assert_eq!(0u8, *num.decrust());
28/// let mut string = encrust!("This is a string");
29/// assert_eq!("This is a string", &*string.decrust());
30/// let mut array = encrust!([1i32, 2i32, 3i32]);
31/// assert_eq!(&[1i32, 2i32, 3i32], &*array.decrust());
32/// ```
33#[proc_macro]
34pub fn encrust(input: TokenStream) -> TokenStream {
35    parse_macro_input!(input as LiteralNode)
36        .kind
37        .generate_output_tokens()
38}
39
40/// Read the contents of a file into a string and encrust it before it is included in the binary.
41///
42/// Unless an absolute path is given, the file is read relative to the `CARGO_MANIFEST_DIR`
43/// environment variable, which is set to the directory containing the crate's `Cargo.toml` file.
44/// *Note* that this is not identical to `include_str!`'s behavior, which reads relative to the file
45/// using the macro.
46///
47/// # Example
48/// ```
49/// # extern crate encrust_core as encrust;
50/// # use encrust_macros::encrust_file_string;
51/// let mut cargo_toml = encrust_file_string!("Cargo.toml");
52/// ```
53#[proc_macro]
54pub fn encrust_file_string(input: TokenStream) -> TokenStream {
55    StringFileReader::from(parse_macro_input!(input as FilePath)).generate_output_tokens()
56}
57
58/// Read the contents of a file into a `CString` and encrust it before it is included in the binary.
59///
60/// Unless an absolute path is given, the file is read relative to the `CARGO_MANIFEST_DIR`
61/// environment variable, which is set to the directory containing the crate's `Cargo.toml` file.
62/// *Note* that this is not identical to `include_str!`'s behavior, which reads relative to the file
63/// using the macro.
64///
65/// # Example
66/// ```
67/// # extern crate encrust_core as encrust;
68/// # use encrust_macros::encrust_file_cstring;
69/// let mut cargo_toml = encrust_file_cstring!("Cargo.toml");
70/// ```
71#[proc_macro]
72pub fn encrust_file_cstring(input: TokenStream) -> TokenStream {
73    CStringFileReader::from(parse_macro_input!(input as FilePath)).generate_output_tokens()
74}
75
76/// Read the contents of a file into a `u8` array and encrust it before it is included in the
77/// binary.
78///
79/// Unless an absolute path is given, the file is read relative to the `CARGO_MANIFEST_DIR`
80/// environment variable, which is set to the directory containing the crate's `Cargo.toml` file.
81/// *Note* that this is not identical to `include_bytes!`'s behavior, which reads relative to the
82/// file using the macro.
83///
84/// # Example
85/// ```
86/// # extern crate encrust_core as encrust;
87/// # use encrust_macros::encrust_file_bytes;
88/// let mut cargo_toml = encrust_file_bytes!("Cargo.toml");
89/// ```
90#[proc_macro]
91pub fn encrust_file_bytes(input: TokenStream) -> TokenStream {
92    BytesFileReader::from(parse_macro_input!(input as FilePath)).generate_output_tokens()
93}
94
95/// Hash a string so that it can be searched for in the resulting executable without including the
96/// actual string. This macro creates a case sensitive `encrust::Hashstring`.
97///
98/// # Example
99/// ```
100/// # extern crate encrust_core as encrust;
101/// # use encrust_macros::hashstring;
102/// let look_for_me = hashstring!("Find me!");
103/// assert!(look_for_me == "Find me!");
104/// assert!(look_for_me != "fInD Me!");
105/// ```
106#[proc_macro]
107#[cfg(feature = "hashstrings")]
108pub fn hashstring(input: TokenStream) -> TokenStream {
109    parse_macro_input!(input as ToHashString).generate_output_tokens_case_sensitive()
110}
111
112/// Similar to the [`hashstring!`] macro, but with a case insensitive `encrust::Hashstring`.
113///
114/// # Example
115/// ```
116/// # extern crate encrust_core as encrust;
117/// # use encrust_macros::hashstring_ci;
118/// let look_for_me = hashstring_ci!("Find me!");
119/// assert!(look_for_me == "Find me!");
120/// assert!(look_for_me == "fInD Me!");
121/// ```
122#[proc_macro]
123#[cfg(feature = "hashstrings")]
124pub fn hashstring_ci(input: TokenStream) -> TokenStream {
125    parse_macro_input!(input as ToHashString).generate_output_tokens_case_insensitive()
126}
127
128/// Hash an array of bytes so that the byte pattern can be searched for without including the bytes
129/// themselves in the executable.
130///
131/// # Example
132/// ```
133/// # extern crate encrust_core as encrust;
134/// # use encrust_macros::hashbytes;
135/// let look_for_me = hashbytes!([0, 1, 2, 3]);
136/// assert!(look_for_me == &[0, 1, 2, 3]);
137/// ```
138#[proc_macro]
139#[cfg(feature = "hashstrings")]
140pub fn hashbytes(input: TokenStream) -> TokenStream {
141    parse_macro_input!(input as ToHashBytes).generate_output_tokens()
142}