#parse #reconstruct #parser #sketchware #sw

swrs

A simple rust library that reads and parses a sketchware project

1 unstable release

0.1.1 Nov 6, 2022
0.1.0 Nov 6, 2022

#1601 in Parser implementations

MIT license

220KB
5K SLoC

swrs

A rust library that parses and reconstructs sketchware projects

swrs is (my first) rust library that can parse and reconstruct Sketchware projects easily. You can use the provided apis (crate::api) to modify parsed Sketchware projects and convert them back into a raw sketchware project without much hassle!

This library is in alpha, and only supports regular Sketchware projects; this library has not been tested with modded projects (although I do have a plan to support it sometime in the future). This library has been tested with multiple projects off of Sketchub and parsing and reconstruction worked flawlessly.

Structure

It's important to take note that this swrs library is composed of two parts: parser and api.

  • parser is the part where raw sketchware projects are then being parsed into a structure that still retains their raw form but with rust types. It's output is a swrs::parser::SketchwareProject
  • api is the part where the parser models are then read and interpreted in a way in order to provide high level apis of collecting data and modifying the project. It's output is a swrs::api::SketchwareProject

Sketchware projects starts from being parsed by the parser (here) into rust structs and then piped onto api (here) to provide high-level APIs like iterating through blocks, substacks, view tree, etc.

Installation

Add swrs to your dependencies table in Cargo.toml:

[dependencies]
swrs = "0.1.1"

Usage

// First you'll need to make a RawSketchwareProject struct instance
// which contains unencrypted raw data of a Sketchware project
let raw = RawSketchwareProject::from_encrypted(
    std::fs::read(Path::new("path/to/project")),
    std::fs::read(Path::new("path/to/file")),
    ...
);

// Then you'll have to parse it
let parsed = ParserSketchwareProject::parse_from(raw).except("Corrupted sketchware project");

// !! NOTE: ParserSketchwareProject is [`swrs::parser::SketchwareProject`] !!
// it's type aliased because it has the same name as in `swrs::api::SketchwareProject`

// And convert it to an API object so that you can modify it easily
let project = SketchwareProject::try_from(parsed).except("Corrupted sketchware project");

// There you have it!
println!("Screens:");

for screen in &mut project.screens {
    println!(" - {} has {} total events", screen.layout_name, screen.events.len());

    // Add a boolean variable
    screen.variables.insert("hello_world".to_string(), Variable {
        name: "hello_world".to_string(),
        r#type: VariableType::Boolean
    });

    // Add a block on onCreate
    if let Some(on_create) = screen.events.iter_mut().find(|e| e.name == "onCreate") {
        // I might need to make a better api for this lmao
        on_create.code.push_block(Block {
            id: BlockId(0), // id and next_block are set by the function
            next_block: None,
            sub_stack1: None,
            sub_stack2: None,
            color: Color::from_rgb(0xa0, 0x6f, 0x3d), // block color
            op_code: "addSourceDirectly".to_string(),
            content: BlockContent::parse_from(
                "add source directly %s.inputOnly",
                Some(vec!["// Hello asd from swrs!".to_string()]),
                |_| unreachable!()
            ).unwrap(),
            ret_type: Default::default(),
            type_name: Default::default()
        });
    }

    // And a lot more!
}

Dependencies

~3.5–4.5MB
~84K SLoC