Skip to content

Commit

Permalink
rustfmt
Browse files Browse the repository at this point in the history
  • Loading branch information
Quba1 committed Jul 25, 2024
1 parent 3d9820e commit 06e45f1
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 71 deletions.
5 changes: 4 additions & 1 deletion benches/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ pub fn key_reading(c: &mut Criterion) {
});

c.bench_function("missing nul-byte termination reading", |b| {
b.iter(|| msg.read_key_dynamic(black_box("experimentVersionNumber")).unwrap())
b.iter(|| {
msg.read_key_dynamic(black_box("experimentVersionNumber"))
.unwrap()
})
});

c.bench_function("problematic key reading", |b| {
Expand Down
4 changes: 2 additions & 2 deletions src/codes_nearest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ impl KeyedMessage {
/// Creates a new instance of [`CodesNearest`] for the `KeyedMessage`.
/// [`CodesNearest`] can be used to find nearest gridpoints for given coordinates in the `KeyedMessage`
/// by calling [`find_nearest()`](crate::CodesNearest::find_nearest).
///
///
/// # Errors
///
///
/// This function returns [`CodesInternal`](crate::errors::CodesInternal) when
/// internal nearest handle cannot be created.
pub fn codes_nearest(&self) -> Result<CodesNearest, CodesError> {
Expand Down
15 changes: 12 additions & 3 deletions src/intermediate_bindings/codes_get.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,10 @@ pub unsafe fn codes_get_long_array(
Ok(key_values)
}

pub unsafe fn codes_get_length(handle: *const codes_handle, key: &str) -> Result<usize, CodesError> {
pub unsafe fn codes_get_length(
handle: *const codes_handle,
key: &str,
) -> Result<usize, CodesError> {
pointer_guard::non_null!(handle);

let key = CString::new(key).unwrap();
Expand All @@ -149,7 +152,10 @@ pub unsafe fn codes_get_length(handle: *const codes_handle, key: &str) -> Result
Ok(key_length)
}

pub unsafe fn codes_get_string(handle: *const codes_handle, key: &str) -> Result<String, CodesError> {
pub unsafe fn codes_get_string(
handle: *const codes_handle,
key: &str,
) -> Result<String, CodesError> {
pointer_guard::non_null!(handle);

let mut key_length = codes_get_length(handle, key)?;
Expand Down Expand Up @@ -184,7 +190,10 @@ pub unsafe fn codes_get_string(handle: *const codes_handle, key: &str) -> Result
Ok(key_message_string)
}

pub unsafe fn codes_get_bytes(handle: *const codes_handle, key: &str) -> Result<Vec<u8>, CodesError> {
pub unsafe fn codes_get_bytes(
handle: *const codes_handle,
key: &str,
) -> Result<Vec<u8>, CodesError> {
pointer_guard::non_null!(handle);

let mut key_size = codes_get_length(handle, key)?;
Expand Down
32 changes: 16 additions & 16 deletions src/keyed_message/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ pub struct KeyedMessage {
pub trait KeyRead<T> {
/// Tries to read a key of given name from [`KeyedMessage`]. This function checks if key native type
/// matches the requested type (ie. you cannot read integer as string, or array as a number).
///
///
/// # Example
///
/// ```
Expand All @@ -76,25 +76,25 @@ pub trait KeyRead<T> {
/// # Ok(())
/// # }
/// ```
///
///
/// # Errors
///
///
/// Returns [`WrongRequestedKeySize`](CodesError::WrongRequestedKeyType) when trying to read key in non-native type (use [`unchecked`](KeyRead::read_key_unchecked) instead).
///
///
/// Returns [`WrongRequestedKeySize`](CodesError::WrongRequestedKeySize) when trying to read array as integer.
///
///
/// Returns [`IncorrectKeySize`](CodesError::IncorrectKeySize) when key size is 0. This can indicate corrupted data.
///
///
/// This function will return [`CodesInternal`](crate::errors::CodesInternal) if ecCodes fails to read the key.
fn read_key(&self, name: &str) -> Result<T, CodesError>;

/// Skips all the checks provided by [`read_key`](KeyRead::read_key) and directly calls ecCodes, ensuring only memory and type safety.
///
///
/// This function has better perfomance than [`read_key`](KeyRead::read_key) but all error handling and (possible)
/// type conversions are performed directly by ecCodes.
///
///
/// This function is also useful for (not usually used) keys that return incorrect native type.
///
///
/// # Example
///
/// ```
Expand All @@ -115,18 +115,18 @@ pub trait KeyRead<T> {
/// # Ok(())
/// # }
/// ```
///
///
/// # Errors
///
///
/// This function will return [`CodesInternal`](crate::errors::CodesInternal) if ecCodes fails to read the key.
fn read_key_unchecked(&self, name: &str) -> Result<T, CodesError>;
}

/// Provides GRIB key writing capabilites. Implemented by [`KeyedMessage`] for all possible key types.
pub trait KeyWrite<T> {
/// Writes key with given name and value to [`KeyedMessage`] overwriting existing value, unless
/// Writes key with given name and value to [`KeyedMessage`] overwriting existing value, unless
/// the key is read-only. This function directly calls ecCodes ensuring only type and memory safety.
///
///
/// # Example
///
/// ```
Expand All @@ -140,17 +140,17 @@ pub trait KeyWrite<T> {
/// # let product_kind = ProductKind::GRIB;
/// #
/// let mut handle = CodesHandle::new_from_file(file_path, product_kind)?;
///
///
/// // CodesHandle iterator returns immutable messages.
/// // To edit a message it must be cloned.
/// let mut message = handle.next()?.context("no message")?.try_clone()?;
/// message.write_key("level", 1)?;
/// # Ok(())
/// # }
/// ```
///
///
/// # Errors
///
///
/// This function will return [`CodesInternal`](crate::errors::CodesInternal) if ecCodes fails to write the key.
fn write_key(&mut self, name: &str, value: T) -> Result<(), CodesError>;
}
Expand Down
6 changes: 3 additions & 3 deletions src/keyed_message/read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,11 @@ impl KeyRead<Vec<u8>> for KeyedMessage {
impl KeyedMessage {
/// Method to get a value of given key with [`DynamicKeyType`] from the `KeyedMessage`, if it exists.
///
/// In most cases you should use [`read_key()`](KeyRead::read_key) due to more predictive behaviour
/// In most cases you should use [`read_key()`](KeyRead::read_key) due to more predictive behaviour
/// and simpler interface.
///
///
/// This function exists for backwards compatibility and user convienience.
///
///
/// This function checks the type of requested key and tries to read it as the native type.
/// That flow adds performance overhead, but makes the function highly unlikely to fail.
///
Expand Down
92 changes: 46 additions & 46 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,119 +5,119 @@
#![cfg_attr(docsrs, feature(doc_cfg))]

//! # Unofficial high-level safe Rust bindings to ecCodes library
//!
//!
//! [![Github Repository](https://img.shields.io/badge/Github-Repository-blue?style=flat-square&logo=github&color=blue)](https://github.com/ScaleWeather/eccodes)
//! [![Crates.io](https://img.shields.io/crates/v/eccodes?style=flat-square)](https://crates.io/crates/eccodes)
//! [![License](https://img.shields.io/github/license/ScaleWeather/eccodes?style=flat-square)](https://choosealicense.com/licenses/apache-2.0/) \
//! [![dependency status](https://deps.rs/repo/github/ScaleWeather/eccodes/status.svg?style=flat-square)](https://deps.rs/repo/github/ScaleWeather/eccodes)
//! ![Crates.io MSRV](https://img.shields.io/crates/msrv/eccodes?style=flat-square)
//! ![ecCodes version](https://img.shields.io/badge/ecCodes-%E2%89%A52.24.0-blue?style=flat-square&color=blue)
//!
//!
//! This crate contains (mostly) safe high-level bindings for ecCodes library.
//! Bindings can be considered safe mainly because all crate structures
//! will take ownership of the data in memory before passing the raw pointer to ecCodes.
//!
//!
//! **Currently only reading of GRIB files is supported.**
//!
//!
//! Because of the ecCodes library API characteristics theses bindings are
//! rather thick wrapper to make this crate safe and convenient to use.
//!
//!
//! This crate officially supports mainly Linux platforms same as the ecCodes library.
//! But it is possible to install ecCodes on `MacOS` and this crate successfully compiles and all tests pass.
//!
//!
//! If you want to see more features released quicker do not hesitate
//! to contribute and check out [Github repository](https://github.com/ScaleWeather/eccodes).
//!
//!
//! [ecCodes](https://confluence.ecmwf.int/display/ECC/ecCodes+Home) is an open-source library
//! for reading and writing GRIB and BUFR files developed by [European Centre for Medium-Range Weather Forecasts](https://www.ecmwf.int/).
//!
//!
//! ## Errors and panics
//!
//!
//! This crate aims to return error whenever possible, even if the error is caused by implementation bug.
//! As ecCodes is often used in scientific applications with long and extensive jobs,
//! this allows the user to handle the error in the way that suits them best and not risk crashes.
//!
//!
//! All error descriptions are provided in the [`errors`] module.
//! Destructors, which cannot panic, report errors through the `log` crate.
//!
//!
//! None of the functions in this crate explicitly panics.
//! However, users should be aware that dependencies might panic in some edge cases.
//!
//!
//! ## Safety
//!
//!
//! This crate aims to be as safe as possible and a lot of effort has been put into testing its safety.
//! Moreover, pointers are always checked for null before being dereferenced.
//!
//!
//! That said, neither main developer nor contributors have expertise in unsafe Rust and bugs might have
//! slipped through. We are also not responsible for bugs in the ecCodes library.
//!
//!
//! If you find a bug or have a suggestion, feel free to discuss it on Github.
//!
//!
//! ## Features
//!
//!
//! - `message_ndarray` - enables support for converting [`KeyedMessage`] to [`ndarray::Array`].
//! This feature is enabled by default. It is currently tested only with simple lat-lon grids.
//!
//!
//! - `experimental_index` - enables support for creating and using index files for GRIB files.
//! **This feature is experimental** and disabled by default. If you want to use it, please read
//! the information provided in [`codes_index`] documentation.
//!
//!
//! - `docs` - builds the crate without linking ecCodes, particularly useful when building the documentation
//! on [docs.rs](https://docs.rs/). For more details check documentation of [eccodes-sys](https://crates.io/crates/eccodes-sys).
//!
//!
//! To build your own crate with this crate as dependency on docs.rs without linking ecCodes add following lines to your `Cargo.toml`
//!
//!
//! ```text
//! [package.metadata.docs.rs]
//! features = ["eccodes/docs"]
//! ```
//!
//!
//! ## Usage
//!
//!
//! To access a GRIB file you need to create [`CodesHandle`] with one of provided constructors.
//!
//!
//! GRIB files consist of messages which represent data fields at specific time and level.
//! Messages are represented by the [`KeyedMessage`] structure.
//!
//!
//! [`CodesHandle`] implements [`FallibleStreamingIterator`](CodesHandle#impl-FallibleStreamingIterator-for-CodesHandle<GribFile>)
//! which allows you to iterate over messages in the file. The iterator returns `&KeyedMessage` which valid is until next iteration.
//! `KeyedMessage` implements several methods to access the data as needed, most of those can be called directly on `&KeyedMessage`.
//! You can also use [`try_clone()`](KeyedMessage::try_clone) to clone the message and prolong its lifetime.
//!
//! Data contained by `KeyedMessage` is represented as *keys* (like in dictionary).
//!
//! Data contained by `KeyedMessage` is represented as *keys* (like in dictionary).
//! Keys can be read with static types using [`read_key()`](KeyedMessage::read_key) or with [dynamic types](`DynamicKeyType`)
//! using [`read_key_dynamic()`](KeyedMessage::read_key_dynamic). To discover what keys are present in a message use [`KeysIterator`](KeyedMessage).
//!
//!
//! You can use [`CodesNearest`] to get the data values of four nearest gridpoints for given coordinates.
//!
//! You can also modify the message with [`write_key()`](KeyedMessage::write_key) and write
//!
//! You can also modify the message with [`write_key()`](KeyedMessage::write_key) and write
//! it to a new file with [`write_to_file()`](KeyedMessage::write_to_file).
//!
//!
//! #### Example 1 - Reading GRIB file
//!
//!
//! ```
//! // We are reading the mean sea level pressure for 4 gridpoints
//! // nearest to Reykjavik (64.13N, -21.89E) for 1st June 2021 00:00 UTC
//! // from ERA5 Climate Reanalysis
//!
//!
//! use eccodes::{ProductKind, CodesHandle, KeyRead};
//! # use std::path::Path;
//! use eccodes::FallibleStreamingIterator;
//! #
//! # fn main() -> anyhow::Result<()> {
//!
//!
//! // Open the GRIB file and create the CodesHandle
//! let file_path = Path::new("./data/iceland.grib");
//! let product_kind = ProductKind::GRIB;
//! let mut handle = CodesHandle::new_from_file(file_path, product_kind)?;
//!
//!
//! // Use iterator to find a message with shortName "msl" and typeOfLevel "surface"
//! // We can use while let or for_each() to iterate over the messages
//! while let Some(msg) = handle.next()? {
//! // We need to specify the type of key we read
//! let short_name: String = msg.read_key("shortName")?;
//! let type_of_level: String = msg.read_key("typeOfLevel")?;
//!
//!
//! if short_name == "msl" && type_of_level == "surface" {
//! // Create CodesNearest for given message
//! let nearest_gridpoints = msg.codes_nearest()?
Expand All @@ -133,18 +133,18 @@
//! # Ok(())
//! # }
//! ```
//!
//!
//! #### Example 2 - Writing GRIB files
//!
//!
//! ```rust
//! // The crate provides basic support for setting `KeyedMessage` keys
//! // and writing GRIB files. The easiests (and safest) way to create a
//! // new custom message is to copy exisitng one from other GRIB file,
//! // modify the keys and write to new file.
//!
//!
//! // Here we are computing the temperature at 850hPa as an average
//! // of 900hPa and 800hPa and writing it to a new file.
//!
//!
//! use eccodes::FallibleStreamingIterator;
//! use eccodes::{CodesHandle, KeyRead, KeyWrite, ProductKind};
//! # use std::{fs::remove_file, path::Path};
Expand All @@ -154,7 +154,7 @@
//! let file_path = Path::new("./data/iceland-levels.grib");
//! let mut handle = CodesHandle::new_from_file(file_path, ProductKind::GRIB)?;
//!
//! // We need a message to edit, in this case we can use
//! // We need a message to edit, in this case we can use
//! // temperature at 700hPa, which is similar to our result
//! let mut new_msg = vec![];
//!
Expand All @@ -165,10 +165,10 @@
//! // Iterate over the messages and collect the data to defined vectors
//! while let Some(msg) = handle.next()? {
//! let short_name: String = msg.read_key("shortName")?;
//!
//!
//! if short_name == "t" {
//! let level: i64 = msg.read_key("level")?;
//!
//!
//! if level == 700 {
//! // To use message outside of the iterator we need to clone it
//! new_msg.push(msg.try_clone()?);
Expand Down Expand Up @@ -205,8 +205,8 @@
//! # Ok(())
//! # }
//! ```
//!
//!

pub mod codes_handle;
#[cfg(feature = "experimental_index")]
#[cfg_attr(docsrs, doc(cfg(feature = "experimental_index")))]
Expand All @@ -229,5 +229,5 @@ pub use codes_nearest::{CodesNearest, NearestGridpoint};
pub use errors::CodesError;
pub use fallible_iterator::{FallibleIterator, IntoFallibleIterator};
pub use fallible_streaming_iterator::FallibleStreamingIterator;
pub use keyed_message::{DynamicKeyType, KeyedMessage, KeyRead, KeyWrite};
pub use keyed_message::{DynamicKeyType, KeyRead, KeyWrite, KeyedMessage};
pub use keys_iterator::{KeysIterator, KeysIteratorFlags};

0 comments on commit 06e45f1

Please sign in to comment.