pub(super) enum SharedInitState<T, C> {
Uninitialized,
Initialized(T),
Failed(C),
}
pub(super) type InitializerResult<T, C, E> = Result<T, (C, E)>;
pub(super) fn get_or_try_init_shared<T, C, E, Init, CachedError>(
state: &mut SharedInitState<T, C>,
init: Init,
cached_error: CachedError,
) -> Result<T, E>
where
T: Copy,
Init: FnOnce() -> InitializerResult<T, C, E>,
CachedError: FnOnce(&C) -> E,
{
match state {
SharedInitState::Initialized(value) => Ok(*value),
SharedInitState::Failed(cached) => Err(cached_error(cached)),
SharedInitState::Uninitialized => match init() {
Ok(value) => {
*state = SharedInitState::Initialized(value);
Ok(value)
}
Err((cached, err)) => {
*state = SharedInitState::Failed(cached);
Err(err)
}
},
}
}