Crate jaded

Source
Expand description

§Java Deserializer for Rust

Java has a much maligned but still widely used Serialization mechanism. The serial stream produced follows the specification available from Oracle here (link is to Java 17 (latest LTS version at time of writing) but protocol hasn’t changed since 1.7).

This library enables that serial stream to be read in Rust applications.

§Example

A simple bean type Java class can be serialized using the builtin tools

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Demo implements Serializable {
    private static final long serialVersionUID = 1L;
    private String message;
    private int i;
    public Demo(String message, int count) {
        this.message = message;
        this.i = count;
    }
    public static void main(String[] args) throws Exception {
        Demo d = new Demo("helloWorld", 42);
        try (FileOutputStream fos = new FileOutputStream("demo.obj", false);
                ObjectOutputStream oos = new ObjectOutputStream(fos);) {
            oos.writeObject(d);
        }
    }
}

We can read in the demo.obj file written as a rust struct

// Open the file written in Java
let sample = File::open("demo.obj").expect("File missing");
// Create a new parser to wrap the file
let mut parser = Parser::new(sample)?;
// read an object from the stream
let content = parser.read()?;
// the content read was a value (instead of raw data) and the value
// was an instance of an object. These methods would return `None` if the content
// was of a different type.
let demo = content.value().unwrap().object_data().unwrap();
assert_eq!("Demo", demo.class_name());
assert_eq!(Some(JavaString("helloWorld".to_string())).as_ref(), demo.get_field("message"));
assert_eq!(Some(Primitive(Int(42))).as_ref(), demo.get_field("i"));

Reading into the raw data format is not often very user friendly so rust types can be read directly from the stream if they implement FromJava.

This is implemented for the primitive types and common types (boxed primitives, arrays, String). Custom types can use these to implement FromJava themselves.

For example to read a string from an object stream

let mut parser = Parser::new(sample)?;
let string: String = parser.read_as()?;

Implemententing FromJava for custom types is very repetitive so a derive macro is provided with the derive feature to automatically generate implementations. Using the same Demo class from above this gives us

#[derive(Debug, FromJava)]
struct Demo {
    message: String,
    i: i32,
}

let mut parser = Parser::new(sample)?;
let demo: Demo = parser.read_as()?;
println!("{:#?}", demo);

// Output
// Demo {
//     message: "helloWorld",
//     i: 42,
// }

Structs§

AnnotationIter
Utility for reading things from annotations
ObjectData
Object data representing serialized Java object
Parser
The main parser class

Enums§

Content
The content read from a stream.
ConversionError
Things that can go wrong when converting deserialized java objects into Rust entities
JavaError
Overall error type for everything that can go wrong with Java deserialization
PrimitiveType
Java’s primitive value types in Rust form
StreamError
Error for things that can go wrong with deserialization
Value
The possible values written by Java’s serialization

Traits§

FromJava
Trait for structs that can be converted from a deserialized Java Value

Type Aliases§

ConversionResult
Result type for conversion process
ReadResult
Result type for deserialization process
Result
Result type for all deserialization operations