Skip to main content

compile_safe

Function compile_safe 

Source
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 rendering
  • Err(CompilerError) - Compilation failed with detailed error information

§Error Conditions

This function can return the following errors:

§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