lean_rs_host/host/meta/
options.rs1use crate::host::elaboration::{
16 LEAN_DIAGNOSTIC_BYTE_LIMIT_DEFAULT, LEAN_DIAGNOSTIC_BYTE_LIMIT_MAX, LEAN_HEARTBEAT_LIMIT_DEFAULT,
17 LEAN_HEARTBEAT_LIMIT_MAX,
18};
19use lean_rs::abi::traits::{IntoLean, TryFromLean, conversion_error};
20use lean_rs::error::{LeanResult, bound_message};
21use lean_rs::{LeanRuntime, Obj};
22
23#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
30pub enum LeanMetaTransparency {
31 #[default]
34 Default,
35 Reducible,
39 Instances,
41 All,
44}
45
46impl LeanMetaTransparency {
47 #[must_use]
49 pub fn as_byte(self) -> u8 {
50 match self {
51 Self::Default => 0,
52 Self::Reducible => 1,
53 Self::Instances => 2,
54 Self::All => 3,
55 }
56 }
57
58 fn from_byte(byte: u8) -> LeanResult<Self> {
59 match byte {
60 0 => Ok(Self::Default),
61 1 => Ok(Self::Reducible),
62 2 => Ok(Self::Instances),
63 3 => Ok(Self::All),
64 other => Err(conversion_error(format!(
65 "expected LeanMetaTransparency byte 0..=3, found {other}"
66 ))),
67 }
68 }
69}
70
71impl<'lean> IntoLean<'lean> for LeanMetaTransparency {
72 fn into_lean(self, runtime: &'lean LeanRuntime) -> Obj<'lean> {
73 self.as_byte().into_lean(runtime)
74 }
75}
76
77impl<'lean> TryFromLean<'lean> for LeanMetaTransparency {
78 fn try_from_lean(obj: Obj<'lean>) -> LeanResult<Self> {
79 Self::from_byte(u8::try_from_lean(obj)?)
80 }
81}
82
83#[derive(Clone, Debug)]
96pub struct LeanMetaOptions {
97 namespace_context: String,
98 heartbeat_limit: u64,
99 diagnostic_byte_limit: usize,
100 transparency: LeanMetaTransparency,
101}
102
103impl LeanMetaOptions {
104 #[must_use]
109 pub fn new() -> Self {
110 Self {
111 namespace_context: String::new(),
112 heartbeat_limit: LEAN_HEARTBEAT_LIMIT_DEFAULT,
113 diagnostic_byte_limit: LEAN_DIAGNOSTIC_BYTE_LIMIT_DEFAULT,
114 transparency: LeanMetaTransparency::Default,
115 }
116 }
117
118 #[must_use]
121 pub fn heartbeat_limit(mut self, heartbeats: u64) -> Self {
122 self.heartbeat_limit = heartbeats.min(LEAN_HEARTBEAT_LIMIT_MAX);
123 self
124 }
125
126 #[must_use]
134 pub fn diagnostic_byte_limit(mut self, bytes: usize) -> Self {
135 self.diagnostic_byte_limit = bytes.min(LEAN_DIAGNOSTIC_BYTE_LIMIT_MAX);
136 self
137 }
138
139 #[must_use]
144 pub fn namespace_context(mut self, ns: &str) -> Self {
145 self.namespace_context = bound_message(ns.to_owned());
146 self
147 }
148
149 #[must_use]
153 pub fn transparency(mut self, transparency: LeanMetaTransparency) -> Self {
154 self.transparency = transparency;
155 self
156 }
157
158 #[allow(
161 dead_code,
162 reason = "first caller lands with the run_meta dispatch in the same prompt"
163 )]
164 pub(crate) fn namespace_context_str(&self) -> &str {
165 &self.namespace_context
166 }
167
168 pub(crate) fn heartbeats(&self) -> u64 {
169 self.heartbeat_limit
170 }
171
172 pub(crate) fn diagnostic_byte_limit_usize(&self) -> usize {
173 self.diagnostic_byte_limit
174 }
175
176 pub(crate) fn transparency_byte(&self) -> u8 {
177 self.transparency.as_byte()
178 }
179}
180
181impl Default for LeanMetaOptions {
182 fn default() -> Self {
183 Self::new()
184 }
185}
186
187#[cfg(test)]
188mod tests {
189 use super::*;
190 use lean_rs::error::LEAN_ERROR_MESSAGE_LIMIT;
191
192 #[test]
193 fn defaults_match_published_constants() {
194 let opts = LeanMetaOptions::new();
195 assert_eq!(opts.heartbeats(), LEAN_HEARTBEAT_LIMIT_DEFAULT);
196 assert_eq!(opts.diagnostic_byte_limit_usize(), LEAN_DIAGNOSTIC_BYTE_LIMIT_DEFAULT);
197 assert_eq!(opts.namespace_context_str(), "");
198 assert_eq!(opts.transparency_byte(), 0);
199 }
200
201 #[test]
202 fn heartbeat_setter_saturates_at_max() {
203 let opts = LeanMetaOptions::new().heartbeat_limit(u64::MAX);
204 assert_eq!(opts.heartbeats(), LEAN_HEARTBEAT_LIMIT_MAX);
205 }
206
207 #[test]
208 fn diagnostic_byte_limit_setter_saturates_at_max() {
209 let opts = LeanMetaOptions::new().diagnostic_byte_limit(usize::MAX);
210 assert_eq!(opts.diagnostic_byte_limit_usize(), LEAN_DIAGNOSTIC_BYTE_LIMIT_MAX);
211 }
212
213 #[test]
214 fn namespace_context_bounded() {
215 let long = "x".repeat(LEAN_ERROR_MESSAGE_LIMIT * 2);
216 let opts = LeanMetaOptions::new().namespace_context(&long);
217 assert!(opts.namespace_context_str().len() <= LEAN_ERROR_MESSAGE_LIMIT);
218 }
219
220 #[test]
221 fn transparency_byte_matches_lean_constructor_order() {
222 assert_eq!(LeanMetaTransparency::Default.as_byte(), 0);
223 assert_eq!(LeanMetaTransparency::Reducible.as_byte(), 1);
224 assert_eq!(LeanMetaTransparency::Instances.as_byte(), 2);
225 assert_eq!(LeanMetaTransparency::All.as_byte(), 3);
226 }
227}