Skip to main content

printwell_cli/
lib.rs

1//! printwell-cli library - exports C entry point for linking by Chromium's ninja.
2//!
3//! This architecture keeps our Rust stdlib separate from Chromium's internal
4//! Rust stdlib, avoiding ABI conflicts.
5
6// Allow unsafe FFI code - required for C interop
7#![allow(unsafe_code)]
8
9mod cli;
10
11use std::ffi::{CStr, c_char, c_int};
12
13/// C entry point called from C++ main.
14/// Takes argument count/values and returns exit code.
15///
16/// # Safety
17/// - `arg_values` must be a valid pointer to an array of `arg_count` C strings
18/// - Each C string in `arg_values` must be valid and null-terminated
19#[unsafe(no_mangle)]
20pub unsafe extern "C" fn printwell_main(
21    arg_count: c_int,
22    arg_values: *const *const c_char,
23) -> c_int {
24    // Convert C args to Rust
25    let arguments: Vec<String> = if arg_values.is_null() || arg_count <= 0 {
26        vec!["printwell".to_string()]
27    } else {
28        (0..usize::try_from(arg_count).unwrap_or(0))
29            .filter_map(|i| {
30                // SAFETY: arg_values is valid for arg_count pointers
31                let ptr = unsafe { *arg_values.add(i) };
32                if ptr.is_null() {
33                    None
34                } else {
35                    // SAFETY: ptr is a valid C string
36                    unsafe { CStr::from_ptr(ptr) }
37                        .to_str()
38                        .ok()
39                        .map(String::from)
40                }
41            })
42            .collect()
43    };
44
45    // Run the CLI
46    match cli::run(arguments) {
47        Ok(()) => 0,
48        Err(e) => {
49            eprintln!("Error: {e:?}");
50            1
51        }
52    }
53}
54
55/// Initialize the Rust runtime (called once at startup).
56#[unsafe(no_mangle)]
57pub const extern "C" fn printwell_init() {
58    // Nothing needed for now - tokio runtime is created per-invocation
59}
60
61/// Cleanup the Rust runtime (called once at shutdown).
62#[unsafe(no_mangle)]
63pub const extern "C" fn printwell_cleanup() {
64    // Nothing needed for now
65}