hematite
                                
                                
                                
                                    hematite copied to clipboard
                            
                            
                            
                        JSON file processing (MC assets)
There's three big blobs (one on block_state.rs, two on model.rs) which could be a lot simpler if we used the auto-derive capabilities of json::decode.
Example:
extern crate "rustc-serialize" as rustc_serialize;
use std::collections::BTreeMap;
use std::io::File;
use std::io::fs::walk_dir;
use rustc_serialize::Decodable;
use rustc_serialize::json::{self, Json};
#[derive(RustcDecodable, PartialEq, Show)]
struct FaceInfo {
    cullface: Option<String>,
    rotation: Option<i64>,
    texture: String,
    tintindex: Option<i64>,
    uv: Option<Vec<f64>>,
}
#[derive(RustcDecodable, PartialEq, Show)]
struct Faces {
    down: Option<FaceInfo>,
    east: Option<FaceInfo>,
    north: Option<FaceInfo>,
    south: Option<FaceInfo>,
    up: Option<FaceInfo>,
    west: Option<FaceInfo>,
}
#[derive(RustcDecodable, PartialEq, Show)]
struct Rotation {
    angle: f64,
    axis: String,
    origin: Vec<f64>,
    rescale: Option<bool>,
}
#[derive(RustcDecodable, PartialEq, Show)]
struct Element {
    from: Vec<f64>,
    to: Vec<f64>,
    rotation: Option<Rotation>,
    shade: Option<bool>,
    faces: Faces,
}
#[derive(RustcDecodable, PartialEq, Show)]
struct BlockModel {
    parent : Option<String>,
    ambientocclusion: Option<bool>,
    textures: Option<BTreeMap<String, String>>,
    elements: Option<Vec<Element>>,
}
fn main() {
    let path = Path::new("src/bin/block");
    let mut n = 0;
    for p in walk_dir(&path).unwrap() {
        let mut file = File::open(&p).unwrap();
        let body = Json::from_reader(&mut file).unwrap();
        let mut dec = json::Decoder::new(body);
        let bm: BlockModel = Decodable::decode(&mut dec).unwrap();
        // Use bm here
        n += 1;
    }
    println!("Read {} files.", n);
}
This thing, seems huge but it's mostly struct definitions, with optional fields mostly. It reads all files inside assets/minecraft/models/block (assuming they are inside src/bin/block and counts them.
Of course it lacks the real logic so it's not usable with the graphics code but still it's way easier to understand. Here is the real thing.
Let me know what you think.
I'm pretty sure Option only works with null turning into None, not missing fields (which I handle in NBT, differently than JSON).
@eddyb Option does work with missing fields, 100% sure.
@toqueteos that must've changed since when I've written this. I'll merge any cleanup based on this (awesome!) face - I think I never ended up using the NBT decoder - but that's mostly because there's a lot of bulk data which would be inefficiently treated by the decoder model (it's not streaming q_q).
@eddyb I have already "ported" 2 of 3 JSON reader code sections.
EDIT: https://gist.github.com/toqueteos/caab6c807b558bbc2d7b
Also why it works now:
https://github.com/rust-lang/rust/issues/12794 https://github.com/rust-lang/rust/pull/16971
There's also this RFC, still pending, which provides same thing for streams which would be AWESOME: https://github.com/rust-lang/rfcs/pull/22