grib_tables 0.1.1

Retrieve details of each GRIB parameter from the parameter abbreviation or from the numeric identifier
Documentation
## grib_tables
Retrieve details of each GRIB parameter from the parameter abbreviation (e.g. "TMP") or from the numeric identifier.

`grib_tables` loads the [GDAL CSV files](https://github.com/OSGeo/gdal/tree/master/frmts/grib/data) into memory and allows the user to:
- Map from parameter abbreviation strings to the numerical representation of that parameter, and the full parameter name and unit.
- Map from the numerical representation of each parameter to the parameter name, abbreviation, and unit.

[Documentation](https://docs.rs/grib_tables/latest/grib_tables/).

## Example

```rust
use grib_tables::{Abbrev, MASTER_TABLE_VERSION, NumericId, Parameter, ParameterDatabase};
# fn main() -> anyhow::Result<()> {

// Get a ParameterDatabase populated with the GRIB tables stored in the included CSV files:
let param_db = ParameterDatabase::new().populate()?;

// Get the numeric IDs and params associated with the abbreviation "TMP":
let abbrev = Abbrev::from("TMP");
let params: Vec<(&NumericId, &Parameter)> = param_db.abbrev_to_parameter(&abbrev);
// `params` is a `Vec` because some abbreviations are associated with multiple parameters.
// (The type of `params` can be deduced by the compiler. The type is written out in
// this example to make it easier to follow the documentation!)

// "TMP" is associated with exactly one parameter:
assert_eq!(params.len(), 1);

// Let's get the `&NumericId` and `&Parameter` associated with the "TMP" abbreviation:
let (temperature_numeric_id, temperature_param) = params.first().as_ref().unwrap();

// Let's get the `name` and `unit` of the `Parameter`:
assert_eq!(temperature_param.name(), "Temperature");
assert_eq!(temperature_param.unit(), "K");

// Let's investigate the `NumericId` associated with "TMP":
assert_eq!(temperature_numeric_id.product_discipline(), 0);
assert_eq!(temperature_numeric_id.parameter_category(), 0);
assert_eq!(temperature_numeric_id.parameter_number(), 0);
assert_eq!(
    temperature_numeric_id.master_table_version(),
    MASTER_TABLE_VERSION
);

// `MAX` values indicate missing values in the GRIB spec.
// "TMP" is part of the GRIB master tables, and so is not
// from a local originating center:
assert_eq!(temperature_numeric_id.originating_center(), u16::MAX);
assert_eq!(temperature_numeric_id.subcenter(), u8::MAX);
assert_eq!(temperature_numeric_id.local_table_version(), u8::MAX);
# Ok(())
# }
```

## Why does `grib_tables` exist?
To build [`hypergrib`](https://github.com/jackkelly/hypergrib), we need to be able to decode GRIB `.idx` files.

We're aware of two awesome existing GRIB readers implemented in Rust ([`gribberish`](https://crates.io/crates/gribberish) and [`grib-rs`](https://crates.io/crates/grib)) but, at the time of writing, neither can decode `.idx` files.

Hence `grib_tables` exists to enable `hypergrib` to decode GRIB `.idx` files.

## Related

- [GRIB tables represented as `.csv` files in GDAL]https://github.com/OSGeo/gdal/tree/master/frmts/grib/data. See [the README for that directory]https://github.com/OSGeo/gdal/blob/master/frmts/grib/degrib/README.TXT.
- [Gribberish discussion]https://github.com/mpiannucci/gribberish/issues/41#issuecomment-2404916278.
- [Post to the gdal-dev mailing list]https://lists.osgeo.org/pipermail/gdal-dev/2024-October/059612.html about splitting the CSVs and/or copying the CSVs.) 
- [A previous design sketch]https://github.com/JackKelly/rust-playground/tree/main/grib_tables
  where we try to faithfully capture the GRIB tables hierarchy (Discipline > Category > Parameter).
  But this feels overkill. It might be _slightly_ faster because we can create a perfect hash at compile time.
  But we only need to look things up in the GRIB table whilst indexing a new GRIB dataset.
  When "normal users" use the dataset, they can just read the metadata that we create for the dataset.