#[cfg(test)]
use lean_rs::error::LEAN_ERROR_MESSAGE_LIMIT;
use lean_rs::error::bound_message;
pub const LEAN_HEARTBEAT_LIMIT_DEFAULT: u64 = 200_000;
pub const LEAN_HEARTBEAT_LIMIT_MAX: u64 = 200_000_000;
pub const LEAN_DIAGNOSTIC_BYTE_LIMIT_DEFAULT: usize = 64 * 1024;
pub const LEAN_DIAGNOSTIC_BYTE_LIMIT_MAX: usize = 1024 * 1024;
const DEFAULT_FILE_LABEL: &str = "<elaborate>";
#[derive(Clone, Debug)]
pub struct LeanElabOptions {
namespace_context: String,
file_label: String,
heartbeat_limit: u64,
diagnostic_byte_limit: usize,
}
impl LeanElabOptions {
#[must_use]
pub fn new() -> Self {
Self {
namespace_context: String::new(),
file_label: DEFAULT_FILE_LABEL.to_owned(),
heartbeat_limit: LEAN_HEARTBEAT_LIMIT_DEFAULT,
diagnostic_byte_limit: LEAN_DIAGNOSTIC_BYTE_LIMIT_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 file_label(mut self, label: &str) -> Self {
self.file_label = bound_message(label.to_owned());
self
}
#[allow(
dead_code,
reason = "first caller lands with the session-method dispatch in the same prompt"
)]
pub(crate) fn namespace_context_str(&self) -> &str {
&self.namespace_context
}
#[allow(
dead_code,
reason = "first caller lands with the session-method dispatch in the same prompt"
)]
pub(crate) fn file_label_str(&self) -> &str {
&self.file_label
}
#[allow(
dead_code,
reason = "first caller lands with the session-method dispatch in the same prompt"
)]
pub(crate) fn heartbeats(&self) -> u64 {
self.heartbeat_limit
}
#[allow(
dead_code,
reason = "first caller lands with the session-method dispatch in the same prompt"
)]
pub(crate) fn diagnostic_byte_limit_usize(&self) -> usize {
self.diagnostic_byte_limit
}
}
impl Default for LeanElabOptions {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn defaults_match_published_constants() {
let opts = LeanElabOptions::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.file_label_str(), DEFAULT_FILE_LABEL);
}
#[test]
fn heartbeat_setter_saturates_at_max() {
let opts = LeanElabOptions::new().heartbeat_limit(u64::MAX);
assert_eq!(opts.heartbeats(), LEAN_HEARTBEAT_LIMIT_MAX);
}
#[test]
fn diagnostic_byte_limit_setter_saturates_at_max() {
let opts = LeanElabOptions::new().diagnostic_byte_limit(usize::MAX);
assert_eq!(opts.diagnostic_byte_limit_usize(), LEAN_DIAGNOSTIC_BYTE_LIMIT_MAX);
}
#[test]
fn string_setters_bound_input() {
let long = "x".repeat(LEAN_ERROR_MESSAGE_LIMIT * 2);
let opts = LeanElabOptions::new().namespace_context(&long).file_label(&long);
assert!(opts.namespace_context_str().len() <= LEAN_ERROR_MESSAGE_LIMIT);
assert!(opts.file_label_str().len() <= LEAN_ERROR_MESSAGE_LIMIT);
}
}