Skip to main content

oxilean_kernel/export/
functions.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use crate::reduce::ReducibilityHint;
6use crate::{
7    BinderInfo, Declaration, Environment, Expr, FVarId, Level, LevelMVarId, Literal, Name,
8};
9use std::collections::HashMap;
10
11use super::types::{
12    ConfigNode, ExportedModule, FocusStack, IntegrityCheckResult, LabelSet, ModuleCache,
13    ModuleDependencyGraph, ModuleDiff, ModuleInfo, ModuleRegistry, ModuleVersion, NonEmptyVec,
14    PathBuf, RewriteRule, RewriteRuleSet, SimpleDag, SlidingSum, SmallMap, StatSummary, StringPool,
15    TokenBucket, TransformStat, TransitiveClosure, VersionedRecord, WindowIterator,
16};
17
18/// Export an environment to a module.
19///
20/// Exports all declarations and constant info entries from the environment.
21pub fn export_environment(env: &Environment, module_name: String) -> ExportedModule {
22    let mut module = ExportedModule::new(module_name);
23    for (name, ci) in env.constant_infos() {
24        module.add_constant(name.clone(), ci.clone());
25    }
26    module
27}
28/// Import a module into an environment.
29///
30/// Imports both legacy declarations and constant info entries.
31pub fn import_module(env: &mut Environment, module: &ExportedModule) -> Result<(), String> {
32    for (name, decl) in &module.declarations {
33        env.add(decl.clone()).map_err(|e| {
34            format!(
35                "Failed to import {} from module {}: {}",
36                name, module.name, e
37            )
38        })?;
39    }
40    for (name, ci) in &module.constants {
41        if env.find(name).is_some() {
42            continue;
43        }
44        env.add_constant(ci.clone()).map_err(|e| {
45            format!(
46                "Failed to import constant {} from module {}: {}",
47                name, module.name, e
48            )
49        })?;
50    }
51    Ok(())
52}
53/// Serialization format identifier.
54pub const MAGIC_NUMBER: u32 = 0x4F584C4E;
55/// Module format version.
56pub const FORMAT_VERSION: u32 = 2;
57#[inline]
58fn write_u8(buf: &mut Vec<u8>, v: u8) {
59    buf.push(v);
60}
61#[inline]
62fn write_u32(buf: &mut Vec<u8>, v: u32) {
63    buf.extend_from_slice(&v.to_le_bytes());
64}
65#[inline]
66fn write_u64(buf: &mut Vec<u8>, v: u64) {
67    buf.extend_from_slice(&v.to_le_bytes());
68}
69fn write_str(buf: &mut Vec<u8>, s: &str) {
70    let bytes = s.as_bytes();
71    write_u32(buf, bytes.len() as u32);
72    buf.extend_from_slice(bytes);
73}
74fn write_name(buf: &mut Vec<u8>, name: &Name) {
75    match name {
76        Name::Anonymous => write_u8(buf, 0),
77        Name::Str(parent, s) => {
78            write_u8(buf, 1);
79            write_name(buf, parent);
80            write_str(buf, s);
81        }
82        Name::Num(parent, n) => {
83            write_u8(buf, 2);
84            write_name(buf, parent);
85            write_u64(buf, *n);
86        }
87    }
88}
89fn write_level(buf: &mut Vec<u8>, level: &Level) {
90    match level {
91        Level::Zero => write_u8(buf, 0),
92        Level::Succ(inner) => {
93            write_u8(buf, 1);
94            write_level(buf, inner);
95        }
96        Level::Max(l, r) => {
97            write_u8(buf, 2);
98            write_level(buf, l);
99            write_level(buf, r);
100        }
101        Level::IMax(l, r) => {
102            write_u8(buf, 3);
103            write_level(buf, l);
104            write_level(buf, r);
105        }
106        Level::Param(name) => {
107            write_u8(buf, 4);
108            write_name(buf, name);
109        }
110        Level::MVar(LevelMVarId(id)) => {
111            write_u8(buf, 5);
112            write_u64(buf, *id);
113        }
114    }
115}
116fn write_binder_info(buf: &mut Vec<u8>, bi: BinderInfo) {
117    let tag: u8 = match bi {
118        BinderInfo::Default => 0,
119        BinderInfo::Implicit => 1,
120        BinderInfo::StrictImplicit => 2,
121        BinderInfo::InstImplicit => 3,
122    };
123    write_u8(buf, tag);
124}
125fn write_literal(buf: &mut Vec<u8>, lit: &Literal) {
126    match lit {
127        Literal::Nat(n) => {
128            write_u8(buf, 0);
129            write_u64(buf, *n);
130        }
131        Literal::Str(s) => {
132            write_u8(buf, 1);
133            write_str(buf, s);
134        }
135    }
136}
137fn write_expr(buf: &mut Vec<u8>, expr: &Expr) {
138    match expr {
139        Expr::Sort(level) => {
140            write_u8(buf, 0);
141            write_level(buf, level);
142        }
143        Expr::BVar(idx) => {
144            write_u8(buf, 1);
145            write_u32(buf, *idx);
146        }
147        Expr::FVar(FVarId(id)) => {
148            write_u8(buf, 2);
149            write_u64(buf, *id);
150        }
151        Expr::Const(name, levels) => {
152            write_u8(buf, 3);
153            write_name(buf, name);
154            write_u32(buf, levels.len() as u32);
155            for l in levels {
156                write_level(buf, l);
157            }
158        }
159        Expr::App(f, a) => {
160            write_u8(buf, 4);
161            write_expr(buf, f);
162            write_expr(buf, a);
163        }
164        Expr::Lam(bi, name, ty, body) => {
165            write_u8(buf, 5);
166            write_binder_info(buf, *bi);
167            write_name(buf, name);
168            write_expr(buf, ty);
169            write_expr(buf, body);
170        }
171        Expr::Pi(bi, name, ty, body) => {
172            write_u8(buf, 6);
173            write_binder_info(buf, *bi);
174            write_name(buf, name);
175            write_expr(buf, ty);
176            write_expr(buf, body);
177        }
178        Expr::Let(name, ty, val, body) => {
179            write_u8(buf, 7);
180            write_name(buf, name);
181            write_expr(buf, ty);
182            write_expr(buf, val);
183            write_expr(buf, body);
184        }
185        Expr::Lit(lit) => {
186            write_u8(buf, 8);
187            write_literal(buf, lit);
188        }
189        Expr::Proj(name, idx, inner) => {
190            write_u8(buf, 9);
191            write_name(buf, name);
192            write_u32(buf, *idx);
193            write_expr(buf, inner);
194        }
195    }
196}
197fn write_reducibility_hint(buf: &mut Vec<u8>, hint: ReducibilityHint) {
198    match hint {
199        ReducibilityHint::Opaque => write_u8(buf, 0),
200        ReducibilityHint::Abbrev => write_u8(buf, 1),
201        ReducibilityHint::Regular(h) => {
202            write_u8(buf, 2);
203            write_u32(buf, h);
204        }
205    }
206}
207fn write_names(buf: &mut Vec<u8>, names: &[Name]) {
208    write_u32(buf, names.len() as u32);
209    for n in names {
210        write_name(buf, n);
211    }
212}
213fn write_declaration(buf: &mut Vec<u8>, decl: &Declaration) {
214    match decl {
215        Declaration::Axiom {
216            name,
217            univ_params,
218            ty,
219        } => {
220            write_u8(buf, 0);
221            write_name(buf, name);
222            write_names(buf, univ_params);
223            write_expr(buf, ty);
224        }
225        Declaration::Definition {
226            name,
227            univ_params,
228            ty,
229            val,
230            hint,
231        } => {
232            write_u8(buf, 1);
233            write_name(buf, name);
234            write_names(buf, univ_params);
235            write_expr(buf, ty);
236            write_expr(buf, val);
237            write_reducibility_hint(buf, *hint);
238        }
239        Declaration::Theorem {
240            name,
241            univ_params,
242            ty,
243            val,
244        } => {
245            write_u8(buf, 2);
246            write_name(buf, name);
247            write_names(buf, univ_params);
248            write_expr(buf, ty);
249            write_expr(buf, val);
250        }
251        Declaration::Opaque {
252            name,
253            univ_params,
254            ty,
255            val,
256        } => {
257            write_u8(buf, 3);
258            write_name(buf, name);
259            write_names(buf, univ_params);
260            write_expr(buf, ty);
261            write_expr(buf, val);
262        }
263    }
264}
265type ReadResult<T> = Result<T, String>;
266fn read_u8(bytes: &[u8], pos: &mut usize) -> ReadResult<u8> {
267    if *pos >= bytes.len() {
268        return Err(format!("unexpected end of data at pos {}", *pos));
269    }
270    let v = bytes[*pos];
271    *pos += 1;
272    Ok(v)
273}
274fn read_u32(bytes: &[u8], pos: &mut usize) -> ReadResult<u32> {
275    if *pos + 4 > bytes.len() {
276        return Err(format!("unexpected end of data at pos {}", *pos));
277    }
278    let v = u32::from_le_bytes([
279        bytes[*pos],
280        bytes[*pos + 1],
281        bytes[*pos + 2],
282        bytes[*pos + 3],
283    ]);
284    *pos += 4;
285    Ok(v)
286}
287fn read_u64(bytes: &[u8], pos: &mut usize) -> ReadResult<u64> {
288    if *pos + 8 > bytes.len() {
289        return Err(format!("unexpected end of data at pos {}", *pos));
290    }
291    let v = u64::from_le_bytes([
292        bytes[*pos],
293        bytes[*pos + 1],
294        bytes[*pos + 2],
295        bytes[*pos + 3],
296        bytes[*pos + 4],
297        bytes[*pos + 5],
298        bytes[*pos + 6],
299        bytes[*pos + 7],
300    ]);
301    *pos += 8;
302    Ok(v)
303}
304fn read_str(bytes: &[u8], pos: &mut usize) -> ReadResult<String> {
305    let len = read_u32(bytes, pos)? as usize;
306    if *pos + len > bytes.len() {
307        return Err(format!("string truncated at pos {}", *pos));
308    }
309    let s = std::str::from_utf8(&bytes[*pos..*pos + len])
310        .map_err(|e| format!("invalid UTF-8: {}", e))?
311        .to_owned();
312    *pos += len;
313    Ok(s)
314}
315fn read_name(bytes: &[u8], pos: &mut usize) -> ReadResult<Name> {
316    let tag = read_u8(bytes, pos)?;
317    match tag {
318        0 => Ok(Name::Anonymous),
319        1 => {
320            let parent = read_name(bytes, pos)?;
321            let s = read_str(bytes, pos)?;
322            Ok(Name::Str(Box::new(parent), s))
323        }
324        2 => {
325            let parent = read_name(bytes, pos)?;
326            let n = read_u64(bytes, pos)?;
327            Ok(Name::Num(Box::new(parent), n))
328        }
329        other => Err(format!("unknown Name tag: {}", other)),
330    }
331}
332fn read_level(bytes: &[u8], pos: &mut usize) -> ReadResult<Level> {
333    let tag = read_u8(bytes, pos)?;
334    match tag {
335        0 => Ok(Level::Zero),
336        1 => {
337            let inner = read_level(bytes, pos)?;
338            Ok(Level::Succ(Box::new(inner)))
339        }
340        2 => {
341            let l = read_level(bytes, pos)?;
342            let r = read_level(bytes, pos)?;
343            Ok(Level::Max(Box::new(l), Box::new(r)))
344        }
345        3 => {
346            let l = read_level(bytes, pos)?;
347            let r = read_level(bytes, pos)?;
348            Ok(Level::IMax(Box::new(l), Box::new(r)))
349        }
350        4 => {
351            let name = read_name(bytes, pos)?;
352            Ok(Level::Param(name))
353        }
354        5 => {
355            let id = read_u64(bytes, pos)?;
356            Ok(Level::MVar(LevelMVarId(id)))
357        }
358        other => Err(format!("unknown Level tag: {}", other)),
359    }
360}
361fn read_binder_info(bytes: &[u8], pos: &mut usize) -> ReadResult<BinderInfo> {
362    let tag = read_u8(bytes, pos)?;
363    match tag {
364        0 => Ok(BinderInfo::Default),
365        1 => Ok(BinderInfo::Implicit),
366        2 => Ok(BinderInfo::StrictImplicit),
367        3 => Ok(BinderInfo::InstImplicit),
368        other => Err(format!("unknown BinderInfo tag: {}", other)),
369    }
370}
371fn read_literal(bytes: &[u8], pos: &mut usize) -> ReadResult<Literal> {
372    let tag = read_u8(bytes, pos)?;
373    match tag {
374        0 => Ok(Literal::Nat(read_u64(bytes, pos)?)),
375        1 => Ok(Literal::Str(read_str(bytes, pos)?)),
376        other => Err(format!("unknown Literal tag: {}", other)),
377    }
378}
379fn read_expr(bytes: &[u8], pos: &mut usize) -> ReadResult<Expr> {
380    let tag = read_u8(bytes, pos)?;
381    match tag {
382        0 => Ok(Expr::Sort(read_level(bytes, pos)?)),
383        1 => Ok(Expr::BVar(read_u32(bytes, pos)?)),
384        2 => Ok(Expr::FVar(FVarId(read_u64(bytes, pos)?))),
385        3 => {
386            let name = read_name(bytes, pos)?;
387            let count = read_u32(bytes, pos)? as usize;
388            let mut levels = Vec::with_capacity(count);
389            for _ in 0..count {
390                levels.push(read_level(bytes, pos)?);
391            }
392            Ok(Expr::Const(name, levels))
393        }
394        4 => {
395            let f = read_expr(bytes, pos)?;
396            let a = read_expr(bytes, pos)?;
397            Ok(Expr::App(Box::new(f), Box::new(a)))
398        }
399        5 => {
400            let bi = read_binder_info(bytes, pos)?;
401            let name = read_name(bytes, pos)?;
402            let ty = read_expr(bytes, pos)?;
403            let body = read_expr(bytes, pos)?;
404            Ok(Expr::Lam(bi, name, Box::new(ty), Box::new(body)))
405        }
406        6 => {
407            let bi = read_binder_info(bytes, pos)?;
408            let name = read_name(bytes, pos)?;
409            let ty = read_expr(bytes, pos)?;
410            let body = read_expr(bytes, pos)?;
411            Ok(Expr::Pi(bi, name, Box::new(ty), Box::new(body)))
412        }
413        7 => {
414            let name = read_name(bytes, pos)?;
415            let ty = read_expr(bytes, pos)?;
416            let val = read_expr(bytes, pos)?;
417            let body = read_expr(bytes, pos)?;
418            Ok(Expr::Let(name, Box::new(ty), Box::new(val), Box::new(body)))
419        }
420        8 => Ok(Expr::Lit(read_literal(bytes, pos)?)),
421        9 => {
422            let name = read_name(bytes, pos)?;
423            let idx = read_u32(bytes, pos)?;
424            let inner = read_expr(bytes, pos)?;
425            Ok(Expr::Proj(name, idx, Box::new(inner)))
426        }
427        other => Err(format!("unknown Expr tag: {}", other)),
428    }
429}
430fn read_reducibility_hint(bytes: &[u8], pos: &mut usize) -> ReadResult<ReducibilityHint> {
431    let tag = read_u8(bytes, pos)?;
432    match tag {
433        0 => Ok(ReducibilityHint::Opaque),
434        1 => Ok(ReducibilityHint::Abbrev),
435        2 => Ok(ReducibilityHint::Regular(read_u32(bytes, pos)?)),
436        other => Err(format!("unknown ReducibilityHint tag: {}", other)),
437    }
438}
439fn read_names(bytes: &[u8], pos: &mut usize) -> ReadResult<Vec<Name>> {
440    let count = read_u32(bytes, pos)? as usize;
441    let mut names = Vec::with_capacity(count);
442    for _ in 0..count {
443        names.push(read_name(bytes, pos)?);
444    }
445    Ok(names)
446}
447fn read_declaration(bytes: &[u8], pos: &mut usize) -> ReadResult<Declaration> {
448    let tag = read_u8(bytes, pos)?;
449    match tag {
450        0 => {
451            let name = read_name(bytes, pos)?;
452            let univ_params = read_names(bytes, pos)?;
453            let ty = read_expr(bytes, pos)?;
454            Ok(Declaration::Axiom {
455                name,
456                univ_params,
457                ty,
458            })
459        }
460        1 => {
461            let name = read_name(bytes, pos)?;
462            let univ_params = read_names(bytes, pos)?;
463            let ty = read_expr(bytes, pos)?;
464            let val = read_expr(bytes, pos)?;
465            let hint = read_reducibility_hint(bytes, pos)?;
466            Ok(Declaration::Definition {
467                name,
468                univ_params,
469                ty,
470                val,
471                hint,
472            })
473        }
474        2 => {
475            let name = read_name(bytes, pos)?;
476            let univ_params = read_names(bytes, pos)?;
477            let ty = read_expr(bytes, pos)?;
478            let val = read_expr(bytes, pos)?;
479            Ok(Declaration::Theorem {
480                name,
481                univ_params,
482                ty,
483                val,
484            })
485        }
486        3 => {
487            let name = read_name(bytes, pos)?;
488            let univ_params = read_names(bytes, pos)?;
489            let ty = read_expr(bytes, pos)?;
490            let val = read_expr(bytes, pos)?;
491            Ok(Declaration::Opaque {
492                name,
493                univ_params,
494                ty,
495                val,
496            })
497        }
498        other => Err(format!("unknown Declaration tag: {}", other)),
499    }
500}
501/// Serialize an `ExportedModule` to a compact binary format.
502///
503/// The format is:
504/// - 4-byte magic number (`OXLN`)
505/// - 4-byte format version
506/// - module name (length-prefixed UTF-8)
507/// - version string (length-prefixed UTF-8)
508/// - dependency count + dependency name strings
509/// - declaration count + serialized `Declaration` values
510/// - metadata count + (key, value) string pairs
511pub fn serialize_module(module: &ExportedModule) -> Vec<u8> {
512    let mut buf = Vec::new();
513    write_u32(&mut buf, MAGIC_NUMBER);
514    write_u32(&mut buf, FORMAT_VERSION);
515    write_str(&mut buf, &module.name);
516    write_str(&mut buf, &module.version);
517    write_u32(&mut buf, module.dependencies.len() as u32);
518    for dep in &module.dependencies {
519        write_str(&mut buf, dep);
520    }
521    write_u32(&mut buf, module.declarations.len() as u32);
522    for (_name, decl) in &module.declarations {
523        write_declaration(&mut buf, decl);
524    }
525    write_u32(&mut buf, module.metadata.len() as u32);
526    for (k, v) in &module.metadata {
527        write_str(&mut buf, k);
528        write_str(&mut buf, v);
529    }
530    buf
531}
532/// Deserialize an `ExportedModule` from bytes produced by [`serialize_module`].
533///
534/// Returns an error if the bytes are malformed, truncated, or have an
535/// incompatible format version.
536pub fn deserialize_module(bytes: &[u8]) -> Result<ExportedModule, String> {
537    let mut pos = 0;
538    let magic = read_u32(bytes, &mut pos)?;
539    if magic != MAGIC_NUMBER {
540        return Err(format!("invalid magic number: 0x{:08X}", magic));
541    }
542    let version = read_u32(bytes, &mut pos)?;
543    if version != FORMAT_VERSION {
544        return Err(format!("unsupported format version: {}", version));
545    }
546    let name = read_str(bytes, &mut pos)?;
547    let ver = read_str(bytes, &mut pos)?;
548    let dep_count = read_u32(bytes, &mut pos)? as usize;
549    let mut dependencies = Vec::with_capacity(dep_count);
550    for _ in 0..dep_count {
551        dependencies.push(read_str(bytes, &mut pos)?);
552    }
553    let decl_count = read_u32(bytes, &mut pos)? as usize;
554    let mut declarations = Vec::with_capacity(decl_count);
555    for _ in 0..decl_count {
556        let decl = read_declaration(bytes, &mut pos)?;
557        let decl_name = decl.name().clone();
558        declarations.push((decl_name, decl));
559    }
560    let meta_count = read_u32(bytes, &mut pos)? as usize;
561    let mut metadata = HashMap::new();
562    for _ in 0..meta_count {
563        let k = read_str(bytes, &mut pos)?;
564        let v = read_str(bytes, &mut pos)?;
565        metadata.insert(k, v);
566    }
567    Ok(ExportedModule {
568        name,
569        declarations,
570        constants: Vec::new(),
571        dependencies,
572        version: ver,
573        metadata,
574    })
575}
576/// Deserialize only the module header (name, version, declaration count).
577///
578/// Useful for quickly inspecting module metadata without decoding all declarations.
579pub fn deserialize_module_header(bytes: &[u8]) -> Result<(String, u32, u32), String> {
580    let mut pos = 0;
581    let magic = read_u32(bytes, &mut pos)?;
582    if magic != MAGIC_NUMBER {
583        return Err(format!("Invalid magic number: 0x{:08X}", magic));
584    }
585    let version = read_u32(bytes, &mut pos)?;
586    if version != FORMAT_VERSION {
587        return Err(format!("Unsupported format version: {}", version));
588    }
589    let name = read_str(bytes, &mut pos)?;
590    let _ver_str = read_str(bytes, &mut pos)?;
591    let _dep_count = read_u32(bytes, &mut pos)?;
592    let dep_count = _dep_count as usize;
593    for _ in 0..dep_count {
594        let len = read_u32(bytes, &mut pos)? as usize;
595        if pos + len > bytes.len() {
596            return Err("truncated dependency list".to_string());
597        }
598        pos += len;
599    }
600    let num_entries = read_u32(bytes, &mut pos)?;
601    Ok((name, version, num_entries))
602}
603#[cfg(test)]
604mod tests {
605    use super::*;
606    use crate::{Expr, Level};
607    #[test]
608    fn test_exported_module_create() {
609        let module = ExportedModule::new("test".to_string());
610        assert_eq!(module.name, "test");
611        assert_eq!(module.num_entries(), 0);
612        assert!(module.is_empty());
613    }
614    #[test]
615    fn test_add_declaration() {
616        let mut module = ExportedModule::new("test".to_string());
617        let decl = Declaration::Axiom {
618            name: Name::str("foo"),
619            univ_params: vec![],
620            ty: Expr::Sort(Level::zero()),
621        };
622        module.add_declaration(Name::str("foo"), decl);
623        assert_eq!(module.declarations.len(), 1);
624        assert!(!module.is_empty());
625    }
626    #[test]
627    fn test_add_dependency() {
628        let mut module = ExportedModule::new("test".to_string());
629        module.add_dependency("base".to_string());
630        module.add_dependency("base".to_string());
631        assert_eq!(module.dependencies.len(), 1);
632        assert_eq!(module.dependencies[0], "base");
633    }
634    #[test]
635    fn test_export_environment() {
636        let env = Environment::new();
637        let module = export_environment(&env, "test".to_string());
638        assert_eq!(module.name, "test");
639    }
640    #[test]
641    fn test_import_module() {
642        let mut module = ExportedModule::new("test".to_string());
643        module.add_declaration(
644            Name::str("foo"),
645            Declaration::Axiom {
646                name: Name::str("foo"),
647                univ_params: vec![],
648                ty: Expr::Sort(Level::zero()),
649            },
650        );
651        let mut target_env = Environment::new();
652        assert!(import_module(&mut target_env, &module).is_ok());
653        assert!(target_env.get(&Name::str("foo")).is_some());
654    }
655    #[test]
656    fn test_module_cache() {
657        let mut cache = ModuleCache::new();
658        let module = ExportedModule::new("test".to_string());
659        cache.add(module);
660        assert!(cache.contains("test"));
661        assert_eq!(cache.all_modules().len(), 1);
662        assert_eq!(cache.num_modules(), 1);
663    }
664    #[test]
665    fn test_import_all() {
666        let mut cache = ModuleCache::new();
667        let mut module = ExportedModule::new("mod1".to_string());
668        module.add_declaration(
669            Name::str("foo"),
670            Declaration::Axiom {
671                name: Name::str("foo"),
672                univ_params: vec![],
673                ty: Expr::Sort(Level::zero()),
674            },
675        );
676        cache.add(module);
677        let mut target = Environment::new();
678        assert!(cache.import_all(&mut target).is_ok());
679        assert!(target.get(&Name::str("foo")).is_some());
680    }
681    #[test]
682    fn test_serialize_deserialize_header() {
683        let mut module = ExportedModule::new("test_mod".to_string());
684        module.add_dependency("base".to_string());
685        let bytes = serialize_module(&module);
686        let (name, version, _entries) =
687            deserialize_module_header(&bytes).expect("value should be present");
688        assert_eq!(name, "test_mod");
689        assert_eq!(version, FORMAT_VERSION);
690    }
691    #[test]
692    fn test_serialize_invalid_magic() {
693        let bytes = vec![0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
694        assert!(deserialize_module_header(&bytes).is_err());
695    }
696    #[test]
697    fn test_serialize_deserialize_round_trip() {
698        let mut module = ExportedModule::new("my_module".to_string());
699        module.add_dependency("base".to_string());
700        module.set_metadata("author".to_string(), "alice".to_string());
701        let axiom = Declaration::Axiom {
702            name: Name::str("MyAxiom"),
703            univ_params: vec![Name::str("u")],
704            ty: Expr::Sort(Level::param(Name::str("u"))),
705        };
706        module.add_declaration(Name::str("MyAxiom"), axiom);
707        let def = Declaration::Definition {
708            name: Name::str("myDef"),
709            univ_params: vec![],
710            ty: Expr::Sort(Level::zero()),
711            val: Expr::Lit(Literal::Nat(42)),
712            hint: ReducibilityHint::Regular(1),
713        };
714        module.add_declaration(Name::str("myDef"), def);
715        let thm = Declaration::Theorem {
716            name: Name::str("myThm"),
717            univ_params: vec![],
718            ty: Expr::Pi(
719                BinderInfo::Default,
720                Name::str("x"),
721                Box::new(Expr::Sort(Level::zero())),
722                Box::new(Expr::BVar(0)),
723            ),
724            val: Expr::Lam(
725                BinderInfo::Default,
726                Name::str("x"),
727                Box::new(Expr::Sort(Level::zero())),
728                Box::new(Expr::BVar(0)),
729            ),
730        };
731        module.add_declaration(Name::str("myThm"), thm);
732        let bytes = serialize_module(&module);
733        let decoded = deserialize_module(&bytes).expect("decoded should be present");
734        assert_eq!(decoded.name, "my_module");
735        assert_eq!(decoded.dependencies, vec!["base"]);
736        assert_eq!(
737            decoded
738                .metadata
739                .get("author")
740                .expect("element at \'author\' should exist"),
741            "alice"
742        );
743        assert_eq!(decoded.declarations.len(), 3);
744        assert_eq!(decoded.declarations[0].0, Name::str("MyAxiom"));
745        assert_eq!(decoded.declarations[1].0, Name::str("myDef"));
746        assert_eq!(decoded.declarations[2].0, Name::str("myThm"));
747    }
748    #[test]
749    fn test_serialize_complex_expr() {
750        let expr = Expr::App(
751            Box::new(Expr::Lam(
752                BinderInfo::Implicit,
753                Name::str("x"),
754                Box::new(Expr::Const(Name::str("Nat"), vec![])),
755                Box::new(Expr::BVar(0)),
756            )),
757            Box::new(Expr::Lit(Literal::Nat(7))),
758        );
759        let mut buf = Vec::new();
760        write_expr(&mut buf, &expr);
761        let decoded = read_expr(&buf, &mut 0).expect("decoded should be present");
762        assert_eq!(decoded, expr);
763    }
764    #[test]
765    fn test_serialize_name_components() {
766        let name = Name::str("Nat").append_str("add").append_num(3);
767        let mut buf = Vec::new();
768        write_name(&mut buf, &name);
769        let decoded = read_name(&buf, &mut 0).expect("decoded should be present");
770        assert_eq!(decoded, name);
771    }
772    #[test]
773    fn test_serialize_level_variants() {
774        let levels = vec![
775            Level::Zero,
776            Level::succ(Level::Zero),
777            Level::max(Level::Zero, Level::param(Name::str("u"))),
778            Level::imax(Level::param(Name::str("u")), Level::param(Name::str("v"))),
779            Level::MVar(LevelMVarId(99)),
780        ];
781        for level in &levels {
782            let mut buf = Vec::new();
783            write_level(&mut buf, level);
784            let decoded = read_level(&buf, &mut 0).expect("decoded should be present");
785            assert_eq!(&decoded, level);
786        }
787    }
788    #[test]
789    fn test_module_metadata() {
790        let mut module = ExportedModule::new("test".to_string());
791        module.set_metadata("author".to_string(), "oxilean".to_string());
792        assert_eq!(
793            module
794                .metadata
795                .get("author")
796                .expect("element at \'author\' should exist"),
797            "oxilean"
798        );
799    }
800    #[test]
801    fn test_cache_remove() {
802        let mut cache = ModuleCache::new();
803        cache.add(ExportedModule::new("mod1".to_string()));
804        cache.add(ExportedModule::new("mod2".to_string()));
805        assert_eq!(cache.num_modules(), 2);
806        cache.remove("mod1");
807        assert_eq!(cache.num_modules(), 1);
808        assert!(!cache.contains("mod1"));
809    }
810    #[test]
811    fn test_cache_clear() {
812        let mut cache = ModuleCache::new();
813        cache.add(ExportedModule::new("mod1".to_string()));
814        cache.clear();
815        assert_eq!(cache.num_modules(), 0);
816    }
817}
818/// Compute the diff between two module versions.
819///
820/// Returns a `ModuleDiff` describing what was added, removed, or changed.
821pub fn diff_modules(old: &ExportedModule, new: &ExportedModule) -> ModuleDiff {
822    let old_names: std::collections::HashSet<&Name> = old.declaration_names().into_iter().collect();
823    let new_names: std::collections::HashSet<&Name> = new.declaration_names().into_iter().collect();
824    let added = new_names
825        .difference(&old_names)
826        .map(|n| (*n).clone())
827        .collect();
828    let removed = old_names
829        .difference(&new_names)
830        .map(|n| (*n).clone())
831        .collect();
832    let changed = Vec::new();
833    ModuleDiff {
834        added,
835        removed,
836        changed,
837    }
838}
839/// Check the integrity of a module.
840pub fn check_module_integrity(module: &ExportedModule) -> IntegrityCheckResult {
841    if module.is_empty() {
842        return IntegrityCheckResult::EmptyModule;
843    }
844    let names = module.declaration_names();
845    let mut seen = std::collections::HashSet::new();
846    let mut duplicates = Vec::new();
847    for name in names {
848        if !seen.insert(name) {
849            duplicates.push(name.clone());
850        }
851    }
852    if !duplicates.is_empty() {
853        return IntegrityCheckResult::DuplicateNames(duplicates);
854    }
855    IntegrityCheckResult::Ok
856}
857/// Check the integrity of serialized module bytes.
858pub fn check_bytes_integrity(bytes: &[u8]) -> IntegrityCheckResult {
859    if bytes.len() < 8 {
860        return IntegrityCheckResult::BadMagicNumber;
861    }
862    let magic = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
863    if magic != MAGIC_NUMBER {
864        return IntegrityCheckResult::BadMagicNumber;
865    }
866    let version = u32::from_le_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]);
867    if version != FORMAT_VERSION {
868        return IntegrityCheckResult::UnsupportedVersion(version);
869    }
870    IntegrityCheckResult::Ok
871}
872#[cfg(test)]
873mod extra_tests {
874    use super::*;
875    use crate::{Expr, Level};
876    #[test]
877    fn test_module_diff_empty() {
878        let m1 = ExportedModule::new("m1".to_string());
879        let m2 = ExportedModule::new("m1".to_string());
880        let diff = diff_modules(&m1, &m2);
881        assert!(diff.is_empty());
882        assert_eq!(diff.total_changes(), 0);
883    }
884    #[test]
885    fn test_module_diff_added() {
886        let m1 = ExportedModule::new("m1".to_string());
887        let mut m2 = ExportedModule::new("m1".to_string());
888        m2.add_declaration(
889            Name::str("foo"),
890            Declaration::Axiom {
891                name: Name::str("foo"),
892                univ_params: vec![],
893                ty: Expr::Sort(Level::zero()),
894            },
895        );
896        let diff = diff_modules(&m1, &m2);
897        assert_eq!(diff.added.len(), 1);
898        assert_eq!(diff.removed.len(), 0);
899    }
900    #[test]
901    fn test_module_diff_removed() {
902        let mut m1 = ExportedModule::new("m1".to_string());
903        m1.add_declaration(
904            Name::str("foo"),
905            Declaration::Axiom {
906                name: Name::str("foo"),
907                univ_params: vec![],
908                ty: Expr::Sort(Level::zero()),
909            },
910        );
911        let m2 = ExportedModule::new("m1".to_string());
912        let diff = diff_modules(&m1, &m2);
913        assert_eq!(diff.removed.len(), 1);
914    }
915    #[test]
916    fn test_module_registry_register() {
917        let mut reg = ModuleRegistry::new();
918        reg.register(Name::str("foo"), "base".to_string());
919        assert_eq!(reg.module_for(&Name::str("foo")), Some("base"));
920        assert!(reg.contains_decl(&Name::str("foo")));
921        assert_eq!(reg.num_decls(), 1);
922    }
923    #[test]
924    fn test_module_registry_register_module() {
925        let mut module = ExportedModule::new("mymod".to_string());
926        module.add_declaration(
927            Name::str("bar"),
928            Declaration::Axiom {
929                name: Name::str("bar"),
930                univ_params: vec![],
931                ty: Expr::Sort(Level::zero()),
932            },
933        );
934        let mut reg = ModuleRegistry::new();
935        reg.register_module(&module);
936        assert_eq!(reg.module_for(&Name::str("bar")), Some("mymod"));
937    }
938    #[test]
939    fn test_module_registry_decls_for_module() {
940        let mut reg = ModuleRegistry::new();
941        reg.register(Name::str("a"), "mod".to_string());
942        reg.register(Name::str("b"), "mod".to_string());
943        assert_eq!(reg.decls_for_module("mod").len(), 2);
944    }
945    #[test]
946    fn test_dep_graph_topological_order() {
947        let mut g = ModuleDependencyGraph::new();
948        g.add_module("a".to_string());
949        g.add_module("b".to_string());
950        g.add_dep("b".to_string(), "a".to_string());
951        let order = g.topological_order().expect("order should be present");
952        assert_eq!(order.len(), 2);
953        assert!(order.contains(&"a".to_string()));
954        assert!(order.contains(&"b".to_string()));
955    }
956    #[test]
957    fn test_dep_graph_depends_on() {
958        let mut g = ModuleDependencyGraph::new();
959        g.add_module("a".to_string());
960        g.add_module("b".to_string());
961        g.add_dep("b".to_string(), "a".to_string());
962        assert!(g.depends_on("b", "a"));
963        assert!(!g.depends_on("a", "b"));
964    }
965    #[test]
966    fn test_check_module_integrity_ok() {
967        let mut m = ExportedModule::new("test".to_string());
968        m.add_declaration(
969            Name::str("foo"),
970            Declaration::Axiom {
971                name: Name::str("foo"),
972                univ_params: vec![],
973                ty: Expr::Sort(Level::zero()),
974            },
975        );
976        assert_eq!(check_module_integrity(&m), IntegrityCheckResult::Ok);
977    }
978    #[test]
979    fn test_check_module_integrity_empty() {
980        let m = ExportedModule::new("test".to_string());
981        assert_eq!(
982            check_module_integrity(&m),
983            IntegrityCheckResult::EmptyModule
984        );
985    }
986    #[test]
987    fn test_check_bytes_integrity_ok() {
988        let module = ExportedModule::new("t".to_string());
989        let bytes = serialize_module(&module);
990        assert_eq!(check_bytes_integrity(&bytes), IntegrityCheckResult::Ok);
991    }
992    #[test]
993    fn test_check_bytes_integrity_bad_magic() {
994        let bytes = vec![0u8; 16];
995        assert_eq!(
996            check_bytes_integrity(&bytes),
997            IntegrityCheckResult::BadMagicNumber
998        );
999    }
1000    #[test]
1001    fn test_module_diff_total_changes() {
1002        let diff = ModuleDiff {
1003            added: vec![Name::str("a")],
1004            removed: vec![Name::str("b"), Name::str("c")],
1005            changed: vec![],
1006        };
1007        assert_eq!(diff.total_changes(), 3);
1008        assert!(!diff.is_empty());
1009    }
1010}
1011#[cfg(test)]
1012mod version_tests {
1013    use super::*;
1014    #[test]
1015    fn test_version_display() {
1016        let v = ModuleVersion::new(1, 2, 3);
1017        assert_eq!(v.to_string(), "1.2.3");
1018    }
1019    #[test]
1020    fn test_version_parse_ok() {
1021        let v = ModuleVersion::parse("2.3.4").expect("v should be present");
1022        assert_eq!(v.major, 2);
1023        assert_eq!(v.minor, 3);
1024        assert_eq!(v.patch, 4);
1025    }
1026    #[test]
1027    fn test_version_parse_invalid() {
1028        assert!(ModuleVersion::parse("1.2").is_none());
1029        assert!(ModuleVersion::parse("a.b.c").is_none());
1030    }
1031    #[test]
1032    fn test_version_compatible_same() {
1033        let v1 = ModuleVersion::new(1, 0, 0);
1034        let v2 = ModuleVersion::new(1, 0, 0);
1035        assert!(v1.is_compatible_with(&v2));
1036    }
1037    #[test]
1038    fn test_version_compatible_newer_minor() {
1039        let newer = ModuleVersion::new(1, 1, 0);
1040        let older = ModuleVersion::new(1, 0, 0);
1041        assert!(newer.is_compatible_with(&older));
1042    }
1043    #[test]
1044    fn test_version_incompatible_different_major() {
1045        let v1 = ModuleVersion::new(2, 0, 0);
1046        let v2 = ModuleVersion::new(1, 5, 0);
1047        assert!(!v1.is_compatible_with(&v2));
1048    }
1049    #[test]
1050    fn test_module_info_builder() {
1051        let info = ModuleInfo::new()
1052            .with_version(ModuleVersion::new(0, 1, 0))
1053            .with_author("oxilean")
1054            .with_license("MIT")
1055            .with_description("core library");
1056        assert_eq!(info.author.as_deref(), Some("oxilean"));
1057        assert_eq!(info.license.as_deref(), Some("MIT"));
1058        assert!(info.version.is_some());
1059    }
1060    #[test]
1061    fn test_module_info_default_empty() {
1062        let info = ModuleInfo::new();
1063        assert!(info.version.is_none());
1064        assert!(info.author.is_none());
1065    }
1066    #[test]
1067    fn test_version_ordering() {
1068        let v1 = ModuleVersion::new(1, 0, 0);
1069        let v2 = ModuleVersion::new(1, 1, 0);
1070        assert!(v1 < v2);
1071    }
1072    #[test]
1073    fn test_version_roundtrip() {
1074        let v = ModuleVersion::new(3, 14, 159);
1075        let s = v.to_string();
1076        let v2 = ModuleVersion::parse(&s).expect("v2 should be present");
1077        assert_eq!(v, v2);
1078    }
1079}
1080#[cfg(test)]
1081mod tests_padding_infra {
1082    use super::*;
1083    #[test]
1084    fn test_stat_summary() {
1085        let mut ss = StatSummary::new();
1086        ss.record(10.0);
1087        ss.record(20.0);
1088        ss.record(30.0);
1089        assert_eq!(ss.count(), 3);
1090        assert!((ss.mean().expect("mean should succeed") - 20.0).abs() < 1e-9);
1091        assert_eq!(ss.min().expect("min should succeed") as i64, 10);
1092        assert_eq!(ss.max().expect("max should succeed") as i64, 30);
1093    }
1094    #[test]
1095    fn test_transform_stat() {
1096        let mut ts = TransformStat::new();
1097        ts.record_before(100.0);
1098        ts.record_after(80.0);
1099        let ratio = ts.mean_ratio().expect("ratio should be present");
1100        assert!((ratio - 0.8).abs() < 1e-9);
1101    }
1102    #[test]
1103    fn test_small_map() {
1104        let mut m: SmallMap<u32, &str> = SmallMap::new();
1105        m.insert(3, "three");
1106        m.insert(1, "one");
1107        m.insert(2, "two");
1108        assert_eq!(m.get(&2), Some(&"two"));
1109        assert_eq!(m.len(), 3);
1110        let keys = m.keys();
1111        assert_eq!(*keys[0], 1);
1112        assert_eq!(*keys[2], 3);
1113    }
1114    #[test]
1115    fn test_label_set() {
1116        let mut ls = LabelSet::new();
1117        ls.add("foo");
1118        ls.add("bar");
1119        ls.add("foo");
1120        assert_eq!(ls.count(), 2);
1121        assert!(ls.has("bar"));
1122        assert!(!ls.has("baz"));
1123    }
1124    #[test]
1125    fn test_config_node() {
1126        let mut root = ConfigNode::section("root");
1127        let child = ConfigNode::leaf("key", "value");
1128        root.add_child(child);
1129        assert_eq!(root.num_children(), 1);
1130    }
1131    #[test]
1132    fn test_versioned_record() {
1133        let mut vr = VersionedRecord::new(0u32);
1134        vr.update(1);
1135        vr.update(2);
1136        assert_eq!(*vr.current(), 2);
1137        assert_eq!(vr.version(), 2);
1138        assert!(vr.has_history());
1139        assert_eq!(*vr.at_version(0).expect("value should be present"), 0);
1140    }
1141    #[test]
1142    fn test_simple_dag() {
1143        let mut dag = SimpleDag::new(4);
1144        dag.add_edge(0, 1);
1145        dag.add_edge(1, 2);
1146        dag.add_edge(2, 3);
1147        assert!(dag.can_reach(0, 3));
1148        assert!(!dag.can_reach(3, 0));
1149        let order = dag.topological_sort().expect("order should be present");
1150        assert_eq!(order, vec![0, 1, 2, 3]);
1151    }
1152    #[test]
1153    fn test_focus_stack() {
1154        let mut fs: FocusStack<&str> = FocusStack::new();
1155        fs.focus("a");
1156        fs.focus("b");
1157        assert_eq!(fs.current(), Some(&"b"));
1158        assert_eq!(fs.depth(), 2);
1159        fs.blur();
1160        assert_eq!(fs.current(), Some(&"a"));
1161    }
1162}
1163#[cfg(test)]
1164mod tests_extra_iterators {
1165    use super::*;
1166    #[test]
1167    fn test_window_iterator() {
1168        let data = vec![1u32, 2, 3, 4, 5];
1169        let windows: Vec<_> = WindowIterator::new(&data, 3).collect();
1170        assert_eq!(windows.len(), 3);
1171        assert_eq!(windows[0], &[1, 2, 3]);
1172        assert_eq!(windows[2], &[3, 4, 5]);
1173    }
1174    #[test]
1175    fn test_non_empty_vec() {
1176        let mut nev = NonEmptyVec::singleton(10u32);
1177        nev.push(20);
1178        nev.push(30);
1179        assert_eq!(nev.len(), 3);
1180        assert_eq!(*nev.first(), 10);
1181        assert_eq!(*nev.last(), 30);
1182    }
1183}
1184#[cfg(test)]
1185mod tests_padding2 {
1186    use super::*;
1187    #[test]
1188    fn test_sliding_sum() {
1189        let mut ss = SlidingSum::new(3);
1190        ss.push(1.0);
1191        ss.push(2.0);
1192        ss.push(3.0);
1193        assert!((ss.sum() - 6.0).abs() < 1e-9);
1194        ss.push(4.0);
1195        assert!((ss.sum() - 9.0).abs() < 1e-9);
1196        assert_eq!(ss.count(), 3);
1197    }
1198    #[test]
1199    fn test_path_buf() {
1200        let mut pb = PathBuf::new();
1201        pb.push("src");
1202        pb.push("main");
1203        assert_eq!(pb.as_str(), "src/main");
1204        assert_eq!(pb.depth(), 2);
1205        pb.pop();
1206        assert_eq!(pb.as_str(), "src");
1207    }
1208    #[test]
1209    fn test_string_pool() {
1210        let mut pool = StringPool::new();
1211        let s = pool.take();
1212        assert!(s.is_empty());
1213        pool.give("hello".to_string());
1214        let s2 = pool.take();
1215        assert!(s2.is_empty());
1216        assert_eq!(pool.free_count(), 0);
1217    }
1218    #[test]
1219    fn test_transitive_closure() {
1220        let mut tc = TransitiveClosure::new(4);
1221        tc.add_edge(0, 1);
1222        tc.add_edge(1, 2);
1223        tc.add_edge(2, 3);
1224        assert!(tc.can_reach(0, 3));
1225        assert!(!tc.can_reach(3, 0));
1226        let r = tc.reachable_from(0);
1227        assert_eq!(r.len(), 4);
1228    }
1229    #[test]
1230    fn test_token_bucket() {
1231        let mut tb = TokenBucket::new(100, 10);
1232        assert_eq!(tb.available(), 100);
1233        assert!(tb.try_consume(50));
1234        assert_eq!(tb.available(), 50);
1235        assert!(!tb.try_consume(60));
1236        assert_eq!(tb.capacity(), 100);
1237    }
1238    #[test]
1239    fn test_rewrite_rule_set() {
1240        let mut rrs = RewriteRuleSet::new();
1241        rrs.add(RewriteRule::unconditional(
1242            "beta",
1243            "App(Lam(x, b), v)",
1244            "b[x:=v]",
1245        ));
1246        rrs.add(RewriteRule::conditional("comm", "a + b", "b + a"));
1247        assert_eq!(rrs.len(), 2);
1248        assert_eq!(rrs.unconditional_rules().len(), 1);
1249        assert_eq!(rrs.conditional_rules().len(), 1);
1250        assert!(rrs.get("beta").is_some());
1251        let disp = rrs
1252            .get("beta")
1253            .expect("element at \'beta\' should exist")
1254            .display();
1255        assert!(disp.contains("→"));
1256    }
1257}