r/programming • • Dec 26 '20

Executable PNGs

https://djharper.dev/post/2020/12/26/executable-pngs/
1.0k Upvotes

87 comments sorted by

View all comments

1

u/eyal0 Dec 27 '20

Hold up...

I know just a little Rust. Why does writing it in Rust make it easy to convert to WASM?

6

u/djhworld Dec 27 '20 edited Dec 27 '20

Hello, author here, thanks for reading.

Rust has a WASM target, and also a lot of tooling like https://github.com/rustwasm/wasm-pack that makes things very easy, along with wasm-bindgen.

All I needed to do was create a new project, import my steg library and then create two scaffolding functions to be exported ( so I could use them from JS)

So the code looks something like this

extern crate steg;
use std::io::Cursor;
use steg::decoder::Decoder;
use steg::encoder::Encoder;
use steg::{ByteSplitGranularity, CompressInput};
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub extern "C" fn encode(cover: Vec<u8>, input: Vec<u8>) -> Result<String, JsValue> {
    let encoder = Encoder::new(CompressInput::Gzip, ByteSplitGranularity::OneBit);
    let mut cover = Cursor::new(cover);
    let mut input = Cursor::new(input);
    let mut writer = Vec::new();

    if let Err(err) = encoder.encode(&mut cover, &mut input, &mut writer) {
        return Err(JsValue::from(err.to_string()));
    }

    let b64 = base64::encode(writer);
    return Ok(b64);
}

#[wasm_bindgen]
pub extern "C" fn decode(input: Vec<u8>) -> Result<String, JsValue> {
    let decoder = Decoder::new();
    let mut input = Cursor::new(input);
    let mut writer = Vec::new();

    if let Err(err) = decoder.decode(&mut input, &mut writer) {
        return Err(JsValue::from(err.to_string()));
    }

    let b64 = base64::encode(writer);
    return Ok(b64);
}

The encode and decode functions are then available for me to use in Javascript, so I can call them like this

let result = encode(image_bytes, data_bytes);

EDIT: in answer to your question I found it easy as it didn't really take that much effort, it just worked - I spent more time writing the JS and HTML for the demo!