{"id":15066821,"url":"https://github.com/savannstm/marshal-rs","last_synced_at":"2025-07-16T18:04:15.656Z","repository":{"id":253805734,"uuid":"844619611","full_name":"savannstm/marshal-rs","owner":"savannstm","description":"Blazingly fast Ruby-lang's Marshal implementation in Rust.","archived":false,"fork":false,"pushed_at":"2025-07-11T09:01:39.000Z","size":149,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-07-11T10:52:52.243Z","etag":null,"topics":["deserialize","marshal","ruby","serialize"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/marshal-rs","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"wtfpl","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/savannstm.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-08-19T16:20:36.000Z","updated_at":"2025-07-11T09:00:18.000Z","dependencies_parsed_at":"2024-08-19T17:30:55.567Z","dependency_job_id":"38741157-1f89-45f4-b0d1-5d7d001937b7","html_url":"https://github.com/savannstm/marshal-rs","commit_stats":null,"previous_names":["savannstm/marshal-rs"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/savannstm/marshal-rs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/savannstm%2Fmarshal-rs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/savannstm%2Fmarshal-rs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/savannstm%2Fmarshal-rs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/savannstm%2Fmarshal-rs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/savannstm","download_url":"https://codeload.github.com/savannstm/marshal-rs/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/savannstm%2Fmarshal-rs/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264951727,"owners_count":23687983,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deserialize","marshal","ruby","serialize"],"created_at":"2024-09-25T01:12:47.238Z","updated_at":"2025-07-16T18:04:15.651Z","avatar_url":"https://github.com/savannstm.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# marshal-rs\n\n**`marshal-rs` is a complete Rust implementation of Ruby-lang's `Marshal`.**\n\nIt is capable of :fire: **_BLAZINGLY FAST_** loading data from dumped Ruby Marshal files, as well as :fire: **_BLAZINGLY FAST_** dumping it back to Marshal format.\n\n## Installation\n\n`cargo add marshal-rs`\n\n## Overview\n\nThis crate has two main structs, `Loader` and `Dumper`, along with helper functions that use them internally. There's three load functions: `load()`, `load_utf8()`, `load_binary()`, and a single dump function: `dump()`.\n\n`load()` takes a `\u0026[u8]`, consisting of Marshal data bytes (that can be read using `std::fs::read()`) as its only argument, and outputs `Value`.\n\n`dump()`, in turn, takes `marshal_rs::Value` as its only argument and serializes it back to `Vec\u003cu8\u003e` Marshal byte stream. It does not preserve strings' initial encoding, writing all strings as UTF-8 encoded.\n\nBy default, in `load()` function, Ruby strings, that include encoding instance variable, are serialized to JSON strings, and those which don't, serialized to byte arrays.\n\n`load_utf8()` function tries to convert arrays without instance variable to string, and produces string if array is valid UTF-8, and object otherwise.\n\n`load_binary()` function converts all strings to objects.\n\nThis behavior also can be controlled in `Loader` by calling `set_string_mode()`.\n\nYou can manage the prefix of instance variables using `instance_var_prefix` argument in `load()` and `dump()`, or by using `set_instance_var_prefix()` function in `Loader` or `Dumper`. Passed string replaces \"@\" instance variables' prefixes.\n\nTo avoid loss of precision, floats are stored as strings.\n\nIf Marshal file contains any extra float mantissa bits, `marshal-rs` discards them. They aren't written by latest 4.8 version of Marshal, but it still preserves them, if encounters any. `marshal-rs` does not.\n\nThe reason this crate wraps around `serde_json::Value`, is because it needs to cleanly track unique object instances and object metadata.\n\nThe table shows, how `marshal-rs` serializes Ruby types to Value:\n\n| Ruby object                                | Serialized to Value                       |\n| ------------------------------------------ | ----------------------------------------- |\n| `nil`                                      | `null`                                    |\n| `true`, `false`                            | `true`, `false`                           |\n| `1337` (Integer)                           | `1337`                                    |\n| `36893488147419103232` (Big Integer)       | `\"36893488147419103232\"`                  |\n| `13.37` (Float)                            | `\"13.37\"`                                 |\n| `\"ligma\"` (String, with instance variable) | `\"ligma\"`                                 |\n| `:ligma` (Symbol)                          | `\"ligma\"`                                 |\n| `/lgma/i` (Regex)                          | `\"/lgma/i\"`                               |\n| `[ ... ]` (Array)                          | `[ ... ]`                                 |\n| `Hash`, `Struct`                           | `IndexMap\u003cValue, Value\u003e`                  |\n| `Object.new`                               | `IndexMap\u003cString, Value\u003e`                 |\n| `Class`, `Module`                          | `null` (Doesn't dump any data to Marshal) |\n\nValue can be stringified and written to JSON using `serde_json::to_string` function. That will wrap each value in an object, that holds its metadata as object keys. For example, `null` will become\n\n```json\n{\n    \"__id\": number,\n    \"__class\": \"\",\n    \"__type\": 0,\n    \"__value\": null,\n    \"__extensions\": [],\n    \"__flags\": 0\n}\n```\n\nobject.\n\nPossible `__type` values are defined in `src/types.rs`:\n\n```rust\npub enum ValueType {\n    #[default]\n    Null = 0,\n    Bool(bool) = 1,\n    Integer(i32) = 2,\n    Float(String) = 3,\n    Bigint(String) = 4,\n    String(String) = 5,\n    Bytes(Vec\u003cu8\u003e) = 6,\n    Symbol(String) = 7,\n    Regexp(String) = 8,\n    Array(Vec\u003cValue\u003e) = 9,\n    Object(ObjectMap) = 10,\n    Class = 11,\n    Module = 12,\n    HashMap(HashMap) = 13,\n    Struct(HashMap) = 14,\n}\n```\n\nPossible `__flags` values are defined in `src/types.rs`:\n\n```rust\nstruct ValueFlags: u8 {\n    const None = 0;\n    const OldModule = 1;\n    const UserClass = 2;\n    const Data = 4;\n    const UserDefined = 8;\n    const UserMarshal = 16;\n}\n```\n\nKeep in mind `__flags` also could be a combination of some flags.\n\n### Unsafe code\n\nIn this crate, unsafe code provides the ability to replicate Marshal's behavior. It shouldn't ever cause problems.\n\n## Test coverage\n\nCurrently, tests feature dumping/loading the following values: nil, bool, positive/negative fixnum, positive/negative bignum, float (including inf, nan and negative), utf-8/non-utf-8 strings, object links, array, hashes, structs, objects (including extended with modules, with custom marshal\\_ methods, with custom \\_load/\\_dump methods), regexps, built-in class subclasses.\n\nAlso tests include loading/dumping RPG Maker game's files and battle-testing them.\n\nIf something is missing in the tests, open an issue or submit a pull request.\n\n## Example\n\n```rust\nuse std::fs::read;\nuse marshal_rs::{load, dump, Value};\n\n// Note: Value supports indexing by `\u0026str` if it's an object,\n// and by `\u0026Value` if it's a hashmap, but to use that you need\n// to import `Get` trait.\n// use marshal_rs::Get;\n\nfn main() {\n    // Read marshal data from file\n    // let marshal_data: Vec\u003cu8\u003e = read(\"./Map001.rvdata2\").unwrap();\n    // For this example, we'll just take pre-defined marshal data\n    let marshal_data = [0x04, 0x08, 0x30];\n\n    // Serializing to json\n    // `load()` takes a `\u0026[u8]` as argument, so `Vec\u003cu8\u003e` must be borrowed\n    let serialized_to_json: Value = load(\u0026marshal_data, None).unwrap();\n\n    // Here you may stringify Value using `serde_json::to_string()`, and\n    // `std::fs::write()` it to file\n\n    // Serializing back to marshal\n    // `dump()` requires owned Value as argument\n    let serialized_to_marshal: Vec\u003cu8\u003e = dump(serialized_to_json, None);\n\n    // Here you may `std::fs::write()` serialized Marshal data to file\n}\n```\n\n## MSRV\n\nMinimum supported Rust version is 1.63.0.\n\n## References\n\n-   [marshal.c](https://github.com/ruby/ruby/blob/master/marshal.c) (Had to compile Ruby manually, and add debug prints to marshal.c, to even figure out what's going on)\n-   [TypeScript implementation of Marshal](https://github.com/hyrious/marshal) (This project inspired me to start working on this)\n-   [Official documentation for Marshal format](https://docs.ruby-lang.org/en/master/marshal_rdoc.html) (Mostly useless)\n\n## License\n\nProject is licensed under WTFPL.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsavannstm%2Fmarshal-rs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsavannstm%2Fmarshal-rs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsavannstm%2Fmarshal-rs/lists"}