eccodes 0.14.0

Unofficial high-level Rust bindings of the latest ecCodes release
Documentation
use std::{path::Path, thread};

use anyhow::{Context, Result};
use eccodes::{CodesFile, FallibleIterator, ProductKind, codes_message::DynamicKeyType};

#[test]
fn thread_safety() {
    // errors are fine, segfaults are not
    thread_safety_core().unwrap_or(());
}

fn thread_safety_core() -> Result<()> {
    thread::spawn(|| -> anyhow::Result<()> {
        loop {
            let file_path = Path::new("./data/iceland.grib");

            let mut handle = CodesFile::new_from_file(file_path, ProductKind::GRIB)?;
            let current_message = handle
                .ref_message_iter()
                .next()?
                .context("Message not some")?;

            for _ in 0..100 {
                let _ = current_message.read_key_dynamic("name")?;

                let str_key = current_message.read_key_dynamic("name")?;

                match str_key {
                    DynamicKeyType::Str(_) => {}
                    _ => panic!("Incorrect variant of string key"),
                }
            }
        }
    });

    for _ in 0..1000 {
        let file_path = Path::new("./data/iceland.grib");

        let mut handle = CodesFile::new_from_file(file_path, ProductKind::GRIB)?;
        let current_message = handle
            .ref_message_iter()
            .next()?
            .context("Message not some")?;

        let long_key = current_message.read_key_dynamic("numberOfPointsAlongAParallel")?;

        match long_key {
            DynamicKeyType::Int(_) => {}
            _ => panic!("Incorrect variant of long key"),
        }
    }

    Ok(())
}