#![allow(unsafe_code)]
use lean_rs_sys::object::{lean_is_scalar, lean_obj_tag};
use lean_rs_sys::scalar::{lean_int64_to_int, lean_scalar_to_int64};
use crate::abi::traits::conversion_error;
use crate::error::{LeanError, LeanResult};
use crate::runtime::LeanRuntime;
use crate::runtime::obj::Obj;
#[must_use]
pub(crate) fn from_i64(runtime: &LeanRuntime, n: i64) -> Obj<'_> {
unsafe { Obj::from_owned_raw(runtime, lean_int64_to_int(n)) }
}
#[must_use]
pub(crate) fn from_isize(runtime: &LeanRuntime, n: isize) -> Obj<'_> {
from_i64(runtime, n as i64)
}
#[allow(
clippy::needless_pass_by_value,
reason = "Obj is consumed by Drop on return; that releases the refcount"
)]
pub(crate) fn try_to_i64(obj: Obj<'_>) -> LeanResult<i64> {
let ptr = obj.as_raw_borrowed();
if unsafe { lean_is_scalar(ptr) } {
Ok(unsafe { lean_scalar_to_int64(ptr) })
} else {
let found_tag = unsafe { lean_obj_tag(ptr) };
Err(bignum_int(found_tag))
}
}
pub(crate) fn try_to_isize(obj: Obj<'_>) -> LeanResult<isize> {
let value = try_to_i64(obj)?;
isize::try_from(value).map_err(|_| out_of_range_isize())
}
fn bignum_int(found_tag: u32) -> LeanError {
conversion_error(format!(
"expected Lean Int (scalar-fitting), found object with tag {found_tag}"
))
}
fn out_of_range_isize() -> LeanError {
conversion_error("Lean Int value does not fit Rust isize")
}