encrust_macros/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg))]
2
3//! Crate implementing macros for `encrust`. See the main crate for documentation.
4
5mod derive;
6mod generator;
7mod parser;
8
9use proc_macro::TokenStream;
10use syn::parse_macro_input;
11
12use crate::{
13    generator::{BytesFileReader, StringFileReader, ToEncrustedTokenStream},
14    parser::{FilePath, Literal, LiteralVec, ToHashBytes, ToHashString},
15};
16
17/// Encrust a literal value so the actual data is obfuscated before being included in the binary.
18/// Currently integers, strings and arrays of (arrays of) integers and strings are accepted.
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().as_str());
30/// let mut array = encrust!([1i32, 2i32, 3i32]);
31/// assert_eq!(&[1i32, 2i32, 3i32], array.decrust().as_slice());
32/// ```
33#[proc_macro]
34pub fn encrust(input: TokenStream) -> TokenStream {
35    parse_macro_input!(input as Literal).generate_output_tokens()
36}
37
38/// Encrust a vec of literals. This works similarly to [`encrust!`] and supports the same data
39/// types, but puts the data in a `vec`.
40///
41/// # Example
42/// ```
43/// # extern crate encrust_core as encrust;
44/// # use encrust_macros::encrust_vec;
45/// let mut a_vec = encrust_vec![1i32, 2i32, 3i32];
46/// assert_eq!(
47///     vec![1i32, 2i32, 3i32].as_slice(),
48///     a_vec.decrust().as_slice()
49/// );
50/// ```
51#[proc_macro]
52pub fn encrust_vec(input: TokenStream) -> TokenStream {
53    parse_macro_input!(input as LiteralVec).generate_output_tokens()
54}
55
56/// Read the contents of a file into a string and encrust it so the actual file contents is
57/// obfuscated before being included in the binary.
58///
59/// Unless an absolute path is given, the file is read relative to the `CARGO_MANIFEST_DIR`
60/// environment variable, which is set to the directory containing the crate's `Cargo.toml` file.
61/// *Note* that this is not identical to `include_str!`'s behavior, which reads relative to the file
62/// using the macro.
63///
64/// # Example
65/// ```
66/// # extern crate encrust_core as encrust;
67/// # use encrust_macros::encrust_file_string;
68/// let mut cargo_toml = encrust_file_string!("Cargo.toml");
69/// ```
70#[proc_macro]
71pub fn encrust_file_string(input: TokenStream) -> TokenStream {
72    StringFileReader::from(parse_macro_input!(input as FilePath)).generate_output_tokens()
73}
74
75/// Read the contents of a file into a `u8` array and encrust it so the actual file contents is
76/// obfuscated before being included in the binary.
77///
78/// Unless an absolute path is given, the file is read relative to the `CARGO_MANIFEST_DIR`
79/// environment variable, which is set to the directory containing the crate's `Cargo.toml` file.
80/// *Note* that this is not identical to `include_bytes!`'s behavior, which reads relative to the
81/// file using the macro.
82///
83/// # Example
84/// ```
85/// # extern crate encrust_core as encrust;
86/// # use encrust_macros::encrust_file_bytes;
87/// let mut cargo_toml = encrust_file_bytes!("Cargo.toml");
88/// ```
89#[proc_macro]
90pub fn encrust_file_bytes(input: TokenStream) -> TokenStream {
91    BytesFileReader::from(parse_macro_input!(input as FilePath)).generate_output_tokens()
92}
93
94/// Hash a string so that it can be searched for in the resulting executable without including the
95/// actual string. This macro creates a case sensitive `encrust::Hashstring`.
96///
97/// # Example
98/// ```
99/// # extern crate encrust_core as encrust;
100/// # use encrust_macros::hashstring;
101/// let look_for_me = hashstring!("Find me!");
102/// assert!(look_for_me == "Find me!");
103/// assert!(look_for_me != "fInD Me!");
104/// ```
105#[proc_macro]
106#[cfg(feature = "hashstrings")]
107pub fn hashstring(input: TokenStream) -> TokenStream {
108    parse_macro_input!(input as ToHashString).generate_output_tokens_case_sensitive()
109}
110
111/// Similar to the [`hashstring!`] macro, but with a case insensitive `encrust::Hashstring`.
112///
113/// # Example
114/// ```
115/// # extern crate encrust_core as encrust;
116/// # use encrust_macros::hashstring_ci;
117/// let look_for_me = hashstring_ci!("Find me!");
118/// assert!(look_for_me == "Find me!");
119/// assert!(look_for_me == "fInD Me!");
120/// ```
121#[proc_macro]
122#[cfg(feature = "hashstrings")]
123pub fn hashstring_ci(input: TokenStream) -> TokenStream {
124    parse_macro_input!(input as ToHashString).generate_output_tokens_case_insensitive()
125}
126
127/// Hash an array of bytes so that the byte pattern can be searched for without including the bytes
128/// themselves in the executable.
129///
130/// # Example
131/// ```
132/// # extern crate encrust_core as encrust;
133/// # use encrust_macros::hashbytes;
134/// let look_for_me = hashbytes!([0, 1, 2, 3]);
135/// assert!(look_for_me == &[0, 1, 2, 3]);
136/// ```
137#[proc_macro]
138#[cfg(feature = "hashstrings")]
139pub fn hashbytes(input: TokenStream) -> TokenStream {
140    parse_macro_input!(input as ToHashBytes).generate_output_tokens()
141}
142
143/// Derive macro to allow custom `struct`s and `enum`s to be encrusted.
144///
145/// This requires that all fields are `Encrustable`. Currently, no other options are available.
146#[proc_macro_derive(Encrustable)]
147pub fn derive_encrustable_macro(input: TokenStream) -> TokenStream {
148    derive::derive_encrustable(parse_macro_input!(input as syn::DeriveInput))
149}