Skip to content

A deserialization library for Ruby's marshalling format.

License

BSD-2-Clause, MIT licenses found

Licenses found

BSD-2-Clause
LICENSE.BSD-2-Clause
MIT
LICENSE.MIT
Notifications You must be signed in to change notification settings

Nnubes256/ruby-marshal

Repository files navigation

ruby-marshal

A deserialization library for Ruby's marshalling format.

⚠️ WARNING ⚠️

This crate is really experimental. Not intended for production applications.

It does not support the entiretly of Ruby Marshal (yet), it contains a bunch of footguns, testing coverage is not really the best and, overall, this crate is Serde but worse. One could call it "bootleg homebrew Serde for Ruby Marshal".

This was ultimately intended to be a learning/experimentation project that ultimately got a bit overblown. Use at your own risk!

Getting started

If you want to get deserializing right away, make sure your target Rust types implement FromRubyMarshal and use the convenience method from_bytes to get started.

For simple cases can use the provided derive macro (#[derive(FromRubyMarshal)) to quickly implement FromRubyMarshal on your types:

use ruby_marshal::{self, FromRubyMarshal};

#[derive(Debug, FromRubyMarshal)]
struct Test {
    thing1: i32,
    thing2: Option<String>,
    thing3: Vec<i32>,
}

// ruby: Marshal.dump({:thing1 => 1, :thing2 => "hello", :thing3 => [1,2,3]})
let input: &[u8] = &[
    0x04, 0x08, 0x7b, 0x08, 0x3a, 0x0b, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x31, 0x69, 0x06, 0x3a,
    0x0b, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x32, 0x49, 0x22, 0x0a, 0x68, 0x65, 0x6c, 0x6c, 0x6f,
    0x06, 0x3a, 0x0d, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x22, 0x0e, 0x53, 0x68,
    0x69, 0x66, 0x74, 0x5f, 0x4a, 0x49, 0x53, 0x3a, 0x0b, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x33,
    0x5b, 0x08, 0x69, 0x06, 0x69, 0x07, 0x69, 0x08,
];
let out = ruby_marshal::from_bytes::<Test>(input).expect("parsing failed");
assert_eq!(out.thing1, 1);
assert_eq!(out.thing2, Some("hello".to_string()));
assert_eq!(out.thing3, vec![1, 2, 3]);

FromRubyMarshal can also be implemented manually.

Features

  • Deserialize binary Ruby Marshal objects into:
  • A derive macro to automatically implement FromRubyMarshal, Serde style.
    • Allows deserialization of named structs (e.g. Point { x: 1, y: 2 }) from Ruby hashes and IVAR objects (normal objects soon to follow).
    • Field renaming support.
    • Borrowed data support on types that use the 'de lifetime.

Roadmap

  • Full Ruby Marshal 4.8 support:
    • nil
    • Booleans (true, false).
    • Integers (0, 320).
    • Floating-point numbers (0.2, Math::PI).
    • Symbols (:foo), with support for resolving symlinks.
    • Arrays ([1, 2, 3]).
    • Hashes ({:a => 1, :b => 2}).
    • Byte arrays.
    • IVAR-wrapped objects.
      • Strings with encoding.
      • Regular expressions (not yet stable).
    • Class and module references.
    • Objects, with support for resolving object links.
    • Bignums (numbers outside of the [-230, 230 - 1] range).
    • Custom marshalled objects:
      • _dump, _load
      • marshal_dump, marshal_load
    • Additional low-level format tags:
      • TYPE_EXTENDED (e)
      • TYPE_UCLASS (C)
      • TYPE_DATA (d)
      • TYPE_USRMARSHAL (U)
      • TYPE_HASH_DEF (})
      • TYPE_MODULE_OLD (M)
  • A derive macro that doesn't suck.
    • Rust type system support.
      • Named structures (struct Point { x: 1, y: 2 }).
      • Enums (enum Variant { A, B }).
      • Borrowed data support (<'de>).
      • Generics (struct Container<T: FromRubyMarshal> { /* ... */ }).
    • Rust types support.
      • Any user type that implements FromRubyMarshal.
      • bool
      • Unsigned integers: u8, u16, u32, u64, u128, usize.
      • Signed integers: i8, i16, i32, i64, i128, isize.
      • Floating-point numbers: f32, f64.
      • Borrowed byte slices: &'de [u8].
      • String, Cow<'de, str>.
      • Box<T>.
      • Option<T>.
      • Vec<T> (arrays), Vec<(T, U)> (hashes).
      • HashMap<K, V>
        • Requires K: Eq + Hash.
        • Any BuildHasher that implements Default is supported.
      • BTreeMap<K, V>
        • Requires K: Ord.
      • ...some other types not yet considered...
    • Marshal format support.
      • Hashes ({:a => 1, :b => 2}).
      • IVAR objects.
      • Objects.
    • Annotation-based functionality.
      • Field renaming (#[marshal(rename = "foo")).
      • Selecting where to deserialize the boxed data of an IVAR object (#[marshal(ivar_data)]).
      • Pluggable logic to deserialize from custom marshalled objects.
      • ...etc...

About

A deserialization library for Ruby's marshalling format.

Resources

License

BSD-2-Clause, MIT licenses found

Licenses found

BSD-2-Clause
LICENSE.BSD-2-Clause
MIT
LICENSE.MIT

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published