erfars/
lib.rs

1#![warn(missing_docs)]
2#![allow(clippy::needless_return)]
3#![deny(clippy::implicit_return)]
4//! A Rust crate that provides safe Rust bindings to the Essential Routines for Fundamental Astronomy ([ERFA](https://github.com/liberfa/erfa))
5//! C library, which is based on the Standards of Fundamental Astronomy ([SOFA](https://www.iausofa.org/index.html)) library published by
6//! the International Astronomical Union (IAU).
7//!
8//! ## Usage
9//! With this crate, functions in ERFA can be called safely in Rust:
10//! ```rust
11//! use erfars::calendar::Cal2jd;
12//!
13//! fn main() {
14//!     let ((jd0, jd1), _) = Cal2jd(2025, 1, 22).unwrap();
15//!     assert_eq!(jd0+jd1, 2460697.5)
16//! }
17//! ```
18//!
19//! ### A note on array arguments in functions
20//! Many of the ERFA C functions pass data in the form of multidimensional arrays. For example, a `double[3][3]`
21//! represents a 3x3 matrix of double-precision floating-point values. However, Rust does not have
22//! an equivalent and clean way of representing this in code. A `double[3][3]` is stored in row-major order,
23//! so the Rust equivalent in memory is simply an array `[f64; 9]`. More specifically, the following
24//! variable declarations are equivalent:
25//!
26//! In C:
27//! ```c
28//! double xyz[3][3] = { {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0} };
29//! ```
30//!
31//! In Rust:
32//! ```rust
33//! let xyz: [f64; 9] = [0.0; 9];
34//! ```
35//!
36//! Where the first three elements of the Rust array are the first row of the C array, and the second group
37//! of three elements in the Rust array are the second row of the C array, and so on.
38//!
39//! For the user, this means that wherever you see something like a `double[2][3]` or a `double[3][3]` in
40//! the ERFA C API, you can safely pass a `[f64; 6]` or a `[f64; 9]` Rust value.
41//!
42//! ### A note on return values for some ERFA functions
43//! Some of the safe Rust ERFA functions return a [`ERFAResult`], which encapsulates both warnings and errors returned from ERFA.
44//! The [`Ok`] value of this result contains both the actual
45//! result and the warning code as a tuple. The warning code is equal to zero if all is ok.
46//! Warning codes from ERFA are always greater than zero, which means you can handle errors using something like:
47//!
48//! ```rust
49//! use erfars::calendar::Jdcalf;
50//!
51//! fn main() {
52//!     // Panics on error
53//!     // If a warning is raised, `warn` is > 0
54//!     let (res, warn) = Jdcalf(2460697.0, 0.5, 2).unwrap();
55//!     if warn > 0 {
56//!         // Do something
57//!     }
58//! }
59
60//! ```
61//!
62//! The meaning of the warning/error codes can be found in the ERFA docs for the relevant function.
63
64// Stop the linter from complaining about the ERFA function names
65#![allow(non_snake_case)]
66
67pub mod astrometry;
68pub mod calendar;
69pub mod eclipticcoordinates;
70pub mod ephemerides;
71pub mod fundamentalargs;
72pub mod galacticcoordinates;
73pub mod geodeticgeocentric;
74pub mod gnomonic;
75pub mod horizonequatorial;
76pub mod precnutpolar;
77pub mod rotationtime;
78pub mod spacemotion;
79pub mod starcatalogs;
80pub mod timescales;
81
82pub mod constants;
83pub mod raw;
84
85mod structs;
86pub use structs::{Astrom, LDBody};
87
88/// A return type for ERFA functions which contains both a warning code and an error code.
89pub type ERFAResult<T> = Result<(T, i32), i32>;
90
91macro_rules! unexpected_val_err {
92    ($fname:ident) => {
93        panic!(concat!("Unexpected value received from ERFA function", stringify!($fname)))
94    };
95}
96pub(crate) use unexpected_val_err;