pub fn compile_safe(layout: Box<Layout>) -> Result<Box<Doc>, CompilerError>Expand description
Compiles a layout into an optimized document with error handling (safe path)
This function provides safe compilation with comprehensive error handling instead of panics.
It uses the same 10-pass compilation pipeline as compile() but returns a Result to
handle errors gracefully. The function uses a default maximum recursion depth of 10,000
to prevent stack overflow on deeply nested layouts.
This is the recommended function for applications that need robust error handling, user-facing compilation, or when processing untrusted layout structures.
§Arguments
layout- The input layout tree to compile. Can be any layout created with constructor functions, including deeply nested or potentially problematic structures.
§Returns
Ok(Box<Doc>)- Successfully compiled document ready for renderingErr(CompilerError)- Compilation failed with detailed error information
§Error Conditions
This function can return the following errors:
CompilerError::StackOverflow- Layout nesting exceeds the default 10,000 level limitCompilerError::AllocationFailed- Memory allocation failed during compilationCompilerError::InvalidInput- Internal state corruption (rare)
§Performance Notes
- Time: O(n) where n is the number of layout nodes (same as
compile()) - Memory: Uses 10 temporary bump allocators during compilation
- Overhead: Minimal additional cost compared to
compile()(error checking only) - Stack Protection: Includes recursion depth tracking to prevent stack overflow
§Examples
§Basic Error Handling
use typeset::{compile_safe, render, text};
let layout = text("Hello, world!".to_string());
match compile_safe(layout) {
Ok(doc) => {
let output = render(doc, 2, 80);
println!("Success: {}", output);
}
Err(e) => {
eprintln!("Compilation failed: {}", e);
}
}§Handling Complex Layout Compilation
use typeset::{compile_safe, render, text, comp, nest, grp, seq, join_with_lines};
// Build a potentially complex layout
let items: Vec<_> = (0..100)
.map(|i| text(format!("item_{}", i)))
.collect();
let layout = seq(join_with_lines(items));
match compile_safe(layout) {
Ok(doc) => {
let output = render(doc, 4, 80);
println!("Compiled {} items successfully", 100);
}
Err(e) => {
eprintln!("Failed to compile large layout: {}", e);
// Handle error appropriately - maybe reduce complexity
}
}§User Input Compilation (Untrusted Layouts)
use typeset::{compile_safe, render, text, CompilerError};
fn compile_user_layout(user_content: String) -> Result<String, String> {
let layout = text(user_content);
match compile_safe(layout) {
Ok(doc) => {
let output = render(doc, 2, 80);
Ok(output)
}
Err(CompilerError::StackOverflow { depth, max_depth }) => {
Err(format!("Layout too complex: {} levels (max: {})", depth, max_depth))
}
Err(CompilerError::AllocationFailed(msg)) => {
Err(format!("Out of memory: {}", msg))
}
Err(CompilerError::InvalidInput(msg)) => {
Err(format!("Invalid layout: {}", msg))
}
}
}§Batch Compilation with Error Recovery
use typeset::{compile_safe, render, text};
fn compile_multiple_layouts(contents: Vec<String>) -> Vec<Result<String, String>> {
contents.into_iter()
.map(|content| {
let layout = text(content);
match compile_safe(layout) {
Ok(doc) => Ok(render(doc, 2, 80)),
Err(e) => Err(e.to_string()),
}
})
.collect()
}§See Also
compile()- Fast compilation that panics on errorscompile_safe_with_depth()- Safe compilation with custom recursion limitsCompilerError- Detailed error types and descriptionsrender()- Convert compiled documents to strings