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}