diff --git a/.gitignore b/.gitignore index 0b188bc..c45565d 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,4 @@ target/ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ +.idea/ diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..88fe10c --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,256 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aes-gcm" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + +[[package]] +name = "bf-macro" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "cfg-if" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "rand_core", + "typenum", +] + +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "ghash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" +dependencies = [ + "opaque-debug", + "polyval", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "generic-array", +] + +[[package]] +name = "libc" +version = "0.2.175" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "polyval" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "reverse-engineer-is-stupid" +version = "0.1.0" +dependencies = [ + "aes-gcm", + "bf-macro", + "hex", + "smallvec", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "typenum" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..da28dca --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,21 @@ +[workspace] +resolver = "3" +members = ["bf-macro"] + +[package] +name = "reverse-engineer-is-stupid" +version = "0.1.0" +edition = "2024" + +[dependencies] +smallvec = { version = "1.15", features = ["union", "const_generics", "const_new"] } +bf-macro = { path = "./bf-macro" } +hex = "0.4" +aes-gcm = "0.10" + +[profile.release] +lto = true +opt-level = 3 +codegen-units = 1 +panic = "abort" +debug = false \ No newline at end of file diff --git a/bf-macro/Cargo.toml b/bf-macro/Cargo.toml new file mode 100644 index 0000000..26e5990 --- /dev/null +++ b/bf-macro/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "bf-macro" +version = "0.1.0" +edition = "2024" + +[lib] +proc-macro = true + +[dependencies] +proc-macro2 = "1" +quote = "1" +syn = { version = "2", features = ["full"] } \ No newline at end of file diff --git a/bf-macro/src/lib.rs b/bf-macro/src/lib.rs new file mode 100644 index 0000000..617dbef --- /dev/null +++ b/bf-macro/src/lib.rs @@ -0,0 +1,39 @@ +use proc_macro::TokenStream; +use quote::quote; +use syn::{parse_macro_input, LitStr}; + +/// Usage: brainfuck!("++>-[].,") +#[proc_macro] +pub fn brainfuck(input: TokenStream) -> TokenStream { + let lit = parse_macro_input!(input as LitStr); + let s = lit.value(); + + // Map characters -> OpCode tokens + let mut ops = Vec::new(); + for ch in s.chars() { + let token = match ch { + '>' => Some(quote! { OpCode::IncrementPointer }), + '<' => Some(quote! { OpCode::DecrementPointer }), + '+' => Some(quote! { OpCode::Increment }), + '-' => Some(quote! { OpCode::Decrement }), + '.' => Some(quote! { OpCode::Write }), + ',' => Some(quote! { OpCode::Read }), + '[' => Some(quote! { OpCode::LoopBegin }), + ']' => Some(quote! { OpCode::LoopEnd }), + _ => None, // ignore comments/whitespace + }; + if let Some(t) = token { + ops.push(t); + } + } + + let n = ops.len(); + // Expand to a const array; the caller gets a [OpCode; N] + let expanded = quote! { + { + const __BF_OPS: [OpCode; #n] = [ #(#ops),* ]; + __BF_OPS + } + }; + expanded.into() +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..cacdc86 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,36 @@ +use aes_gcm::aead::{Aead, OsRng}; +use aes_gcm::{AeadCore, Aes256Gcm, KeyInit}; +use smallvec::SmallVec; + +mod vm; + +const RANDOM_ARRAY: [u8; 32] = [ + 93, 138, 183, 130, 184, 174, 181, 180, 177, 40, 8, 118, 67, 100, 224, 1, 63, 249, 113, 89, 117, + 86, 254, 40, 44, 89, 105, 185, 183, 115, 179, 177, +]; + +fn main() { + let Some(input) = std::env::args().nth(1) else { + eprintln!("Need a input"); + return; + }; + + let mut tape = SmallVec::<[u8; 32]>::from_slice(&RANDOM_ARRAY); + let mut ptr = 0; + vm::run(&vm::parse(vm::KEY), &mut tape, &mut ptr); + let tape_slice = &tape[0..32]; + let encrypted = encrypt(tape_slice, &input); + println!("{}", encrypted); +} + +fn encrypt(key: &[u8], plaintext: &str) -> String { + let cipher = Aes256Gcm::new_from_slice(key).expect("Invalid key"); + let iv = Aes256Gcm::generate_nonce(&mut OsRng); + let ct = cipher + .encrypt(&iv, plaintext.as_bytes()) + .expect("Invalid plaintext"); + let mut out = SmallVec::<[u8; 16]>::with_capacity(iv.len() + ct.len()); + out.extend_from_slice(&iv); + out.extend_from_slice(&ct); + hex::encode(out) +} diff --git a/src/vm.rs b/src/vm.rs new file mode 100644 index 0000000..f72f02f --- /dev/null +++ b/src/vm.rs @@ -0,0 +1,263 @@ +use bf_macro::brainfuck; +use smallvec::SmallVec; +use std::io::Read; + +#[allow(dead_code)] +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum OpCode { + IncrementPointer, + DecrementPointer, + Increment, + Decrement, + Write, + Read, + LoopBegin, + LoopEnd, +} + +#[allow(dead_code)] +#[derive(Clone)] +pub enum Instruction { + IncrementPointer, + DecrementPointer, + Increment, + Decrement, + Write, + Read, + Loop(Vec), +} + +pub fn parse(opcodes: &[OpCode]) -> SmallVec<[Instruction; 16]> { + let mut program: SmallVec<[Instruction; 16]> = SmallVec::new(); + let mut loop_stack = 0; + let mut loop_start = 0; + + for (i, op) in opcodes.iter().enumerate() { + if loop_stack == 0 { + let instr = match op { + OpCode::IncrementPointer => Some(Instruction::IncrementPointer), + OpCode::DecrementPointer => Some(Instruction::DecrementPointer), + OpCode::Increment => Some(Instruction::Increment), + OpCode::Decrement => Some(Instruction::Decrement), + OpCode::Write => Some(Instruction::Write), + OpCode::Read => Some(Instruction::Read), + + OpCode::LoopBegin => { + loop_start = i; + loop_stack += 1; + None + } + + OpCode::LoopEnd => panic!("failed to parse"), + }; + + match instr { + Some(instr) => program.push(instr), + None => (), + } + } else { + match op { + OpCode::LoopBegin => { + loop_stack += 1; + } + OpCode::LoopEnd => { + loop_stack -= 1; + + if loop_stack == 0 { + program.push(Instruction::Loop( + parse(&opcodes[loop_start + 1..i]).to_vec(), + )) + } + } + _ => (), + } + } + } + + if loop_stack != 0 { + panic!("failed to parse"); + } + + program +} + +pub fn run(instructions: &[Instruction], tape: &mut SmallVec<[u8; N]>, ptr: &mut usize) { + for instr in instructions { + match instr { + Instruction::IncrementPointer => { + *ptr += 1; + if *ptr >= tape.len() { + tape.push(0); + } + } + Instruction::DecrementPointer => *ptr -= 1, + Instruction::Increment => { + let added = tape[*ptr].checked_add(1).unwrap_or(0); + tape[*ptr] = added; + } + Instruction::Decrement => { + let subtracted = tape[*ptr].checked_sub(1).unwrap_or(0); + tape[*ptr] = subtracted; + } + Instruction::Write => {} + Instruction::Read => { + let mut input: [u8; 1] = [0; 1]; + std::io::stdin() + .read_exact(&mut input) + .expect("failed to read stdin"); + tape[*ptr] = input[0]; + } + Instruction::Loop(nested_instructions) => { + while tape[*ptr] != 0 { + run(&nested_instructions, tape, ptr) + } + } + } + } +} + +pub const KEY: &[OpCode] = &brainfuck!( + r#" +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + >[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< +++++++++ >[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++ >[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< +++ +>[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++ +>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +"# +); + +#[cfg(test)] +mod tests { + use crate::RANDOM_ARRAY; + use crate::vm::{KEY, OpCode, parse, run}; + use bf_macro::brainfuck; + use smallvec::SmallVec; + + const H: &[OpCode] = &brainfuck!( + "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" + ); + + #[test] + fn test_h() { + let mut tape = SmallVec::<[u8; 173]>::from_slice(&[0; 17]); + let mut ptr = 0; + run(&parse(H), &mut tape, &mut ptr); + assert_eq!(tape[0], 97); + } + + #[test] + fn test_real_key() { + let mut tape = SmallVec::<[u8; 173]>::from_slice(&RANDOM_ARRAY); + let mut ptr = 0; + run(&parse(KEY), &mut tape, &mut ptr); + let key = &tape[0..32]; + let encoded_tape = hex::encode(key); + println!("{:?}", encoded_tape); + } +}