1#![feature(proc_macro_hygiene)]
6
7pub use xorstring_procmacro;
12
13#[derive(PartialEq, Eq, Debug, Hash, Clone)]
16pub struct XorString<'a> {
17 encrypted: &'a [u8],
19}
20
21impl<'a> XorString<'a> {
22 pub const fn new(encrypted: &'a [u8]) -> Self {
27 XorString { encrypted }
28 }
29
30 pub fn decrypt(&self) -> String {
34 let mut string = String::with_capacity(self.encrypted.len());
35 let key = xorstring_procmacro::xorstring!();
36
37 for (i, c) in self.encrypted.iter().enumerate() {
38 string.push((c ^ (key as usize + i) as u8) as char);
39 }
40
41 string
42 }
43}
44
45#[macro_export]
50macro_rules! xorstring {
51 ($str:literal) => {
52 $crate::XorString::new($crate::xorstring_procmacro::xorstring!($str)).decrypt()
53 };
54}
55
56#[cfg(test)]
57mod tests {
58 #[test]
59 fn test_simple() {
60 let xorred = super::xorstring_procmacro::xorstring!(b"abc");
61 assert_ne!(xorred, b"abc");
62
63 let decrypted = super::XorString::new(xorred);
64 let decrypted: String = decrypted.decrypt();
65 let decrypted = decrypted.as_bytes();
66
67 assert_eq!(decrypted, b"abc");
68 }
69
70 #[test]
71 fn test_macro() {
72 assert_eq!(
73 super::xorstring!(b"Hello, World!"),
74 String::from("Hello, World!"),
75 );
76 assert_ne!(
77 super::xorstring_procmacro::xorstring!(b"Hello, World!"),
78 super::xorstring!(b"Hello, World!").as_bytes(),
79 );
80 }
81}