use std::panic::{AssertUnwindSafe, catch_unwind, resume_unwind};
#[derive(Debug)]
struct Failure(String);
pub fn catch<T>(operation: impl FnOnce() -> T) -> Result<T, String> {
match catch_unwind(AssertUnwindSafe(operation)) {
Ok(value) => Ok(value),
Err(payload) => match payload.downcast::<Failure>() {
Ok(error) => Err(error.0),
Err(payload) => resume_unwind(payload),
},
}
}
pub(crate) fn for_trait(sequence: &crate::LazySeq) -> crate::Value {
match sequence.try_realize() {
Ok(value) => value,
Err(crate::ValueError::Cancelled) => crate::parking::resume_cancelled(),
Err(error) => resume_unwind(Box::new(Failure(error.to_string()))),
}
}
#[inline]
pub fn check_stack() {
if let Some(remaining) = cljrs_gc::fiber::native_stack_low() {
stack_exhausted(remaining)
}
}
#[cold]
#[inline(never)]
fn stack_exhausted(remaining: usize) -> ! {
resume_unwind(Box::new(Failure(format!(
"stack overflow in native code: value nested too deeply \
({remaining} bytes of fiber stack remaining)"
))))
}
pub fn is_inert(value: &crate::Value) -> bool {
use crate::Value;
matches!(
value.unwrap_meta(),
Value::Nil
| Value::Bool(_)
| Value::Long(_)
| Value::Double(_)
| Value::Char(_)
| Value::Str(_)
| Value::Keyword(_)
| Value::Symbol(_)
| Value::BigInt(_)
| Value::BigDecimal(_)
| Value::Ratio(_)
| Value::Uuid(_)
| Value::Pattern(_)
)
}