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