1pub mod cell;
2pub mod common;
3pub mod coordinates;
4pub mod data;
5pub mod error;
6pub mod gf;
7pub mod spk;
8pub mod string;
9pub mod time;
10pub mod vector;
11
12use crate::error::set_error_defaults;
13pub use crate::error::Error;
14use crate::string::SpiceString;
15use parking_lot::{ReentrantMutex, ReentrantMutexGuard};
16use std::cell::RefCell;
17use std::fmt::Debug;
18use std::ops::Deref;
19use thiserror::Error;
20
21static SPICE_LOCK: ReentrantMutex<RefCell<bool>> = ReentrantMutex::new(RefCell::new(false));
23
24pub(crate) fn with_spice_lock_or_panic<R, F>(f: F) -> R
25where
26 F: FnOnce() -> R,
27{
28 match try_with_spice_lock(f) {
29 Ok(k) => k,
30 Err(e) => {
31 panic!("{e}")
32 }
33 }
34}
35
36pub fn try_with_spice_lock<R, F>(f: F) -> Result<R, SpiceLockError>
40where
41 F: FnOnce() -> R,
42{
43 let guard = SPICE_LOCK.try_lock().ok_or(SpiceLockError)?;
44 initialise_library(&guard);
45 Ok(f())
46}
47
48pub fn with_spice_lock<R, F>(f: F) -> R
53where
54 F: FnOnce() -> R,
55{
56 let guard = SPICE_LOCK.lock();
57 initialise_library(&guard);
58 f()
59}
60
61fn initialise_library(guard: &ReentrantMutexGuard<'static, RefCell<bool>>) {
62 if !guard.borrow().deref() {
63 *guard.borrow_mut() = true;
64 set_error_defaults();
65 }
66}
67
68#[derive(Debug)]
69pub struct SpiceLock(ReentrantMutexGuard<'static, RefCell<bool>>);
70
71#[derive(Debug, Clone, Error)]
73#[cfg_attr(not(test), error("SPICE is already in use by another thread. If multi-threaded use is intentional wrap the call using `with_spice_lock()`."))]
74#[cfg_attr(test, error("SPICE is already in use by another thread. When running unit tests you will likely need to use the `--test-threads=1` argument."))]
75pub struct SpiceLockError;
76
77#[cfg(test)]
78mod tests {
79 use crate::data::furnish;
80 use std::path::PathBuf;
81 use std::sync::Once;
82
83 pub fn load_test_data() {
85 static SPICE_INIT: Once = Once::new();
86 SPICE_INIT.call_once(|| {
87 let data_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("test_data");
88 furnish(data_dir.join("testkernel.txt").to_string_lossy()).unwrap();
89 });
90 }
91}