printwell-cli 0.1.11

Command-line tool for HTML to PDF conversion
Documentation
//! printwell-cli library - exports C entry point for linking by Chromium's ninja.
//!
//! This architecture keeps our Rust stdlib separate from Chromium's internal
//! Rust stdlib, avoiding ABI conflicts.

// Allow unsafe FFI code - required for C interop
#![allow(unsafe_code)]

mod cli;

use std::ffi::{CStr, c_char, c_int};

/// C entry point called from C++ main.
/// Takes argument count/values and returns exit code.
///
/// # Safety
/// - `arg_values` must be a valid pointer to an array of `arg_count` C strings
/// - Each C string in `arg_values` must be valid and null-terminated
#[unsafe(no_mangle)]
pub unsafe extern "C" fn printwell_main(
    arg_count: c_int,
    arg_values: *const *const c_char,
) -> c_int {
    // Convert C args to Rust
    let arguments: Vec<String> = if arg_values.is_null() || arg_count <= 0 {
        vec!["printwell".to_string()]
    } else {
        (0..usize::try_from(arg_count).unwrap_or(0))
            .filter_map(|i| {
                // SAFETY: arg_values is valid for arg_count pointers
                let ptr = unsafe { *arg_values.add(i) };
                if ptr.is_null() {
                    None
                } else {
                    // SAFETY: ptr is a valid C string
                    unsafe { CStr::from_ptr(ptr) }
                        .to_str()
                        .ok()
                        .map(String::from)
                }
            })
            .collect()
    };

    // Run the CLI
    match cli::run(arguments) {
        Ok(()) => 0,
        Err(e) => {
            eprintln!("Error: {e:?}");
            1
        }
    }
}

/// Initialize the Rust runtime (called once at startup).
#[unsafe(no_mangle)]
pub const extern "C" fn printwell_init() {
    // Nothing needed for now - tokio runtime is created per-invocation
}

/// Cleanup the Rust runtime (called once at shutdown).
#[unsafe(no_mangle)]
pub const extern "C" fn printwell_cleanup() {
    // Nothing needed for now
}