Crate zalgo_codec

source ·
Expand description

This is a crate implementing the zalgo encoding and decoding functions originally written in Python by Scott Conner and extends them to Rust using a procedural macro.

With the functions defined in this crate you can transform an ASCII string into a unicode string that is a single “character” wide. While the encoding is reversible the encoded string will be larger than the original in terms of bytes.

The crate also provides the zalgo_embed! macro that can be used to embed encoded source code and pass the results on to the compiler. Imagine the code clarity!

Additionally the crate provides functions to encode Python code and wrap the result in a decoder that decodes and executes the encoded string.

Can not encode carriage returns, so files written on non-unix operating systems might not work. The file encoding functions will attempt to encode files anyway by ignoring carriage returns, but the string encoding functions will return an error.

Example

We can execute arbitrary encoded code with the macro:

// This expands to the code
// `fn add(x: i32, y: i32) -> i32 {x + y}`

zalgo_embed!("E͎͉͙͉̞͉͙͆̀́̈́̈́̈̀̓̒̌̀̀̓̒̉̀̍̀̓̒̀͛̀̋̀͘̚̚͘͝");

// The `add` function is now available
assert_eq!(add(10, 20), 30);

Explanation

Characters U+0300–U+036F are the combining characters for unicode Latin. The fun thing about combining characters is that you can add as many of these characters as you like to the original character and it does not create any new symbols, it only adds symbols on top of the character. It’s supposed to be used in order to create characters such as á by taking a normal a and adding another character to give it the mark (U+301, in this case). Fun fact, Unicode doesn’t specify any limit on the number of these characters. Conveniently, this gives us 112 different characters we can map to, which nicely maps to the ASCII character range 0x20 -> 0x7F, aka all the non-control characters. The only issue is that we can’t have new lines in this system, so to fix that, we can simply map 0x7F (DEL) to 0x0A (LF). This can be represented as (CHARACTER - 11) % 133 - 21, and decoded with (CHARACTER + 22) % 133 + 10.

Notes

The original post where the Python code was first presented together with the above explanation.

Macros

This macro decodes a Unicode string that has been encoded with zalgo_encode and passes the results on to the compiler.

Structs

The error returned by the encoding functions if they encounter a character they can not encode. Contains a string that references which type of character and which line caused the error.

Functions

Decodes the contents of a file that has been encoded with encode_file and stores the result in another file.
Encodes the contents of the file and stores the result in another file. If carriage return characters are found it will print a message and attempt to encode the file anyway by ignoring them.
Encodes the contents of the given file and stores the result wrapped in a decoder in another file. This file will still work the same as the original python code. If the source file contains carriage return characters this function will print a message and then attempt to encode the file anyway by ignoring them.
Takes in a string that was compressed by zalgo_encode and decompresses it to an ASCII string.
Takes in an ASCII string and “compresses” it to zalgo text using a reversible encoding scheme. The resulting string should only take up a single character space horizontally when displayed (though this can vary between platforms depending on how they deal with unicode). The resulting string will be larger than the original in terms of bytes, but it can be decompressed to recover the original string using zalgo_decode.
zalgo-encodes an ASCII string containing python code and wraps it in a decoder that decodes and executes it.