Expand description
Reikland parses and deserializes Ruby’s Marshal format with serde compatibility.
If you don’t need serde compatibility you may prefer alox-48, which inspired this crate.
§Quick start
use serde::Deserialize;
use reikland::{from_bytes, Transparent};
#[derive(Deserialize)]
struct Player<'a> {
#[serde(rename = "@name")]
name: &'a str,
#[serde(rename = "@level")]
level: i32,
}
let data: &[u8] = todo!("read a .rxdata / Marshal.dump file");
let player: Transparent<Player> = from_bytes(data).unwrap(); // details on that `Transparent` type below
println!("{}", player.name);§Wrapper types
I found the marshal format to have a good degree of desync between the “intended” and “literal” ways to deserialize a value in Rust. For example: An instance variable is basically just a (T, HashMap<Symbol, Value>) but in many cases you (the lovely person reading this) just want T. However if I just made instance variables deserialize to T we are losing information so I made the executive decision to provide a collection of helpful wrappers to get at T with less pain.
-
Transparent<T>- deserializesT, unwrapping instance variable / sequence layers automatically. -
TransparentOpt<T, O>- likeTransparentbut also captures the second element of a sequence if present. -
Ivar<T, O>- deserializes an instance variable as its inner value plus the ivar map. -
RbObject<T, N>/RbStruct- deserializes a Ruby Object or Struct as its class name and field map. -
RbRegex<P>- deserializes a Ruby Regex as its pattern and flags byte. -
Encoding- extracts the Ruby encoding from an ivar. -
WithEncoding<T>is an alias forIvar<T, Encoding>. -
RbHashDefault<T, D>- deserializes a Hash-with-default as the hash and its default value. -
MixedKey/MixedKeyRef- represent hash keys that can be either integer or string. -
DualKeyMap/DualKeyVec/ etc… - thedual_key_mapmodule exports various ways to access maps that have both integer and string keys
All wrapper structs implement Deref/DerefMut to their primary field so they can be used without unwrapping in most cases. Or you can destructure them as the fields are public.
§Using the parser directly
If the serde implementation doesn’t work for you, the raw parser is exposed via marshal::parse.
It produces a flat marshal::MarshalData with no recursive types, which the serde implementation also uses internally.
Re-exports§
pub use deserializer::from_bytes;pub use deserializer::from_marshal_data;pub use deserializer_types::Encoding;pub use deserializer_types::Ignored;pub use deserializer_types::Ivar;pub use deserializer_types::MixedKey;pub use deserializer_types::MixedKeyRef;pub use deserializer_types::RbHashDefault;pub use deserializer_types::RbObject;pub use deserializer_types::RbRegex;pub use deserializer_types::RbStruct;pub use deserializer_types::Transparent;pub use deserializer_types::TransparentOpt;pub use deserializer_types::WithEncoding;pub use deserializer_types::dual_key_map::DualKeyMap;pub use deserializer_types::dual_key_map::DualKeyVec;pub use types::encoding::RubyEncoding;pub use types::regex::RbRegexStr;pub use types::string::RbStr;pub use types::string::RbString;pub use types::value::MarshalValue;
Modules§
- cursor
- deserializer
- deserializer_
types - This module has a collection of types you may run into with your marshal data, with some reasonable Deserialize and Serialize implementations for them.
- marshal
- types
- version_
number