grib 0.18.3

GRIB format parser & writer for Rust
Documentation
use std::{env, error::Error, fs::File, io::BufReader, path::Path};

use grib::LatLons;

fn main() -> Result<(), Box<dyn Error>> {
    // This example shows how to decode values inside a layer in a GRIB2
    // message. The example also shows how to obtain the latitude-longitude
    // locations of grid points, which are usually used in conjunction with
    // the grid point values.

    // Take the first argument as an input file path and the second argument as
    // a layer index.
    let mut args = env::args().skip(1);
    if let (Some(file_path), Some(index), Some(subindex)) = (args.next(), args.next(), args.next())
    {
        let index: (usize, usize) = (index.parse()?, subindex.parse()?);
        decode_layer(file_path, index)
    } else {
        panic!("Usage: decode_layer <path> <index>");
    }
}

fn decode_layer<P>(path: P, message_index: (usize, usize)) -> Result<(), Box<dyn Error>>
where
    P: AsRef<Path>,
{
    // Open the input file in a normal way.
    let f = File::open(path)?;
    let f = BufReader::new(f);

    // Read with the reader.
    let grib2 = grib::from_reader(f)?;

    // Find the target submessage.
    let (_index, submessage) = grib2
        .iter()
        .find(|(index, _)| *index == message_index)
        .ok_or("no such index")?;

    // Obtain latitude-longitude locations as an iterator.
    let latlons = submessage.latlons()?;

    // Prepare a decoder.
    let decoder = grib::Grib2SubmessageDecoder::from(submessage)?;

    // Actually dispatch a decoding process and get an iterator of decoded
    // values. There are various methods available for compressing GRIB2
    // data, but some are not yet supported by this library and may return
    // errors.
    let values = decoder.dispatch()?;

    // Iterate over decoded values along with locations.
    for ((lat, lon), value) in latlons.zip(values) {
        println!("{lat} {lon} {value}");
    }

    Ok(())
}