npyz 0.9.0

NumPy file format (de-)serialization. Fork of outdated npy-rs.
Documentation
use std::io;
use std::fs::File;

use serde_pickle;

// test-data/pickle.npy is generated by this Python code:
//
// import numpy as np
// a = np.array([
//     [1, 3.5, "number"],
//     [{}, {}, None],
// ], dtype=object)
// np.save('test-data/pickle.npy', a)

fn main() -> io::Result<()> {
    read_example()?;
    write_example()?;
    Ok(())
}

// Example of reading a pickled ndarray's header.
fn read_example() -> Result<(), io::Error> {
    let file = io::BufReader::new(File::open("test-data/pickle.npy")?);
    let npy = npyz::NpyFile::new(file)?;

    assert_eq!(npy.shape(), &[2, 3]);
    println!("DType: {}", npy.dtype().descr());
    println!("Shape: {:?}", npy.shape());
    println!("Strides: {:?}", npy.strides());

    // When an array involves objects, the **entire** array is written in a single pickle.
    // npyz can't help us any further here.
    let file = npy.into_inner();
    let de_options = Default::default();
    let value = serde_pickle::value_from_reader(file, de_options).map_err(pickle_err_to_io_err)?;

    // The pickled value begins with a bunch of array metadata that's tough to make sense of,
    // but at the end you will see the data, a flat list of the objects written by the python
    // snippet at the top of this file.
    println!("Pickled value: {:?}", value);

    Ok(())
}

// Example of writing a pickled ndarray's header.
fn write_example() -> Result<(), io::Error> {
    use npyz::WriterBuilder;

    let type_str = "|O".parse().unwrap();
    let dtype = npyz::DType::new_scalar(type_str);

    let mut file = io::BufWriter::new(File::create("examples/output/pickle-corrupt.npy")?);

    // With npyz it is possible to write the *header*...
    npyz::WriteOptions::new_header_only()
        .dtype(dtype)
        .shape(&[2, 3])
        .writer(&mut file)
        .write_header_only()?;

    // And beyond that I have positively no idea what you should do to write the payload.
    // Have fun!

    Ok(())
}

fn pickle_err_to_io_err(error: serde_pickle::Error) -> io::Error {
    match error {
        serde_pickle::Error::Io(e) => e,
        error => io::Error::new(io::ErrorKind::Other, error.to_string()),
    }
}