use std::cell::RefCell;
use crate::generator::GenerationMode;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct NexgenConfig {
pub mode: GenerationMode,
pub system_nexus: bool,
}
impl Default for NexgenConfig {
fn default() -> Self {
Self {
mode: GenerationMode::DefinitionsOnly,
system_nexus: false,
}
}
}
thread_local! {
static CONFIGS: RefCell<Vec<NexgenConfig>> = RefCell::new(Vec::new());
}
pub fn current() -> NexgenConfig {
CONFIGS.with(|configs| configs.borrow().last().copied().unwrap_or_default())
}
pub fn scope(config: NexgenConfig) -> NexgenConfigScope {
CONFIGS.with(|configs| configs.borrow_mut().push(config));
NexgenConfigScope
}
pub struct NexgenConfigScope;
impl Drop for NexgenConfigScope {
fn drop(&mut self) {
CONFIGS.with(|configs| {
configs
.borrow_mut()
.pop()
.expect("NexGen configuration scope must be present");
});
}
}
#[cfg(test)]
mod tests {
use super::{NexgenConfig, current, scope};
use crate::generator::GenerationMode;
#[test]
fn restores_nested_configuration_after_unwinding() {
let outer = NexgenConfig {
mode: GenerationMode::DefinitionsOnly,
system_nexus: true,
};
{
let _outer_scope = scope(outer);
assert_eq!(current(), outer);
let result = std::panic::catch_unwind(|| {
let _inner_scope = scope(NexgenConfig::default());
panic!("test unwind");
});
assert!(result.is_err());
assert_eq!(current(), outer);
}
assert_eq!(current(), NexgenConfig::default());
}
#[test]
fn is_isolated_per_thread() {
let config = NexgenConfig {
mode: GenerationMode::DefinitionsOnly,
system_nexus: true,
};
{
let _scope = scope(config);
assert_eq!(current(), config);
assert_eq!(
std::thread::spawn(current).join().unwrap(),
NexgenConfig::default()
);
}
}
}