use crate::host::elaboration::{
LEAN_DIAGNOSTIC_BYTE_LIMIT_DEFAULT, LEAN_DIAGNOSTIC_BYTE_LIMIT_MAX, LEAN_HEARTBEAT_LIMIT_DEFAULT,
LEAN_HEARTBEAT_LIMIT_MAX,
};
use lean_rs::error::bound_message;
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
#[non_exhaustive]
pub enum LeanMetaTransparency {
#[default]
Default,
Reducible,
Instances,
All,
}
impl LeanMetaTransparency {
#[must_use]
pub fn as_byte(self) -> u8 {
match self {
Self::Default => 0,
Self::Reducible => 1,
Self::Instances => 2,
Self::All => 3,
}
}
}
#[derive(Clone, Debug)]
pub struct LeanMetaOptions {
namespace_context: String,
heartbeat_limit: u64,
diagnostic_byte_limit: usize,
transparency: LeanMetaTransparency,
}
impl LeanMetaOptions {
#[must_use]
pub fn new() -> Self {
Self {
namespace_context: String::new(),
heartbeat_limit: LEAN_HEARTBEAT_LIMIT_DEFAULT,
diagnostic_byte_limit: LEAN_DIAGNOSTIC_BYTE_LIMIT_DEFAULT,
transparency: LeanMetaTransparency::Default,
}
}
#[must_use]
pub fn heartbeat_limit(mut self, heartbeats: u64) -> Self {
self.heartbeat_limit = heartbeats.min(LEAN_HEARTBEAT_LIMIT_MAX);
self
}
#[must_use]
pub fn diagnostic_byte_limit(mut self, bytes: usize) -> Self {
self.diagnostic_byte_limit = bytes.min(LEAN_DIAGNOSTIC_BYTE_LIMIT_MAX);
self
}
#[must_use]
pub fn namespace_context(mut self, ns: &str) -> Self {
self.namespace_context = bound_message(ns.to_owned());
self
}
#[must_use]
pub fn transparency(mut self, transparency: LeanMetaTransparency) -> Self {
self.transparency = transparency;
self
}
#[allow(
dead_code,
reason = "first caller lands with the run_meta dispatch in the same prompt"
)]
pub(crate) fn namespace_context_str(&self) -> &str {
&self.namespace_context
}
pub(crate) fn heartbeats(&self) -> u64 {
self.heartbeat_limit
}
pub(crate) fn diagnostic_byte_limit_usize(&self) -> usize {
self.diagnostic_byte_limit
}
pub(crate) fn transparency_byte(&self) -> u8 {
self.transparency.as_byte()
}
}
impl Default for LeanMetaOptions {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
use lean_rs::error::LEAN_ERROR_MESSAGE_LIMIT;
#[test]
fn defaults_match_published_constants() {
let opts = LeanMetaOptions::new();
assert_eq!(opts.heartbeats(), LEAN_HEARTBEAT_LIMIT_DEFAULT);
assert_eq!(opts.diagnostic_byte_limit_usize(), LEAN_DIAGNOSTIC_BYTE_LIMIT_DEFAULT);
assert_eq!(opts.namespace_context_str(), "");
assert_eq!(opts.transparency_byte(), 0);
}
#[test]
fn heartbeat_setter_saturates_at_max() {
let opts = LeanMetaOptions::new().heartbeat_limit(u64::MAX);
assert_eq!(opts.heartbeats(), LEAN_HEARTBEAT_LIMIT_MAX);
}
#[test]
fn diagnostic_byte_limit_setter_saturates_at_max() {
let opts = LeanMetaOptions::new().diagnostic_byte_limit(usize::MAX);
assert_eq!(opts.diagnostic_byte_limit_usize(), LEAN_DIAGNOSTIC_BYTE_LIMIT_MAX);
}
#[test]
fn namespace_context_bounded() {
let long = "x".repeat(LEAN_ERROR_MESSAGE_LIMIT * 2);
let opts = LeanMetaOptions::new().namespace_context(&long);
assert!(opts.namespace_context_str().len() <= LEAN_ERROR_MESSAGE_LIMIT);
}
#[test]
fn transparency_byte_matches_lean_constructor_order() {
assert_eq!(LeanMetaTransparency::Default.as_byte(), 0);
assert_eq!(LeanMetaTransparency::Reducible.as_byte(), 1);
assert_eq!(LeanMetaTransparency::Instances.as_byte(), 2);
assert_eq!(LeanMetaTransparency::All.as_byte(), 3);
}
}