alef_codegen/c_consumer/mod.rs
1//! Shared C-FFI consumer scaffolding for language backends.
2//!
3//! This module provides utilities for generating language bindings that consume
4//! the C FFI layer produced by cbindgen. Each consumer backend (Go, Java, C#, Zig)
5//! uses the same C interface:
6//! - A C header file (`config.ffi_header_name()`)
7//! - A library name (`config.ffi_lib_name()`)
8//! - A symbol prefix (`config.ffi_prefix()`)
9//! - Standard helper symbols: `{prefix}_free_string`, `{prefix}_last_error_code`, `{prefix}_last_error_context`
10
11use alef_core::config::{AlefConfig, resolve_output_dir};
12use std::path::PathBuf;
13
14/// Context capturing the shared FFI consumer inputs across all language backends.
15pub struct CConsumerContext<'a> {
16 /// Reference to the Alef configuration.
17 pub config: &'a AlefConfig,
18 /// C header filename (e.g., "html_to_markdown.h").
19 pub header: String,
20 /// C library name used for linking (e.g., "html_to_markdown").
21 pub lib_name: String,
22 /// C symbol prefix for FFI functions (e.g., "htm").
23 pub prefix: String,
24}
25
26impl<'a> CConsumerContext<'a> {
27 /// Create a new CConsumerContext from the Alef configuration.
28 pub fn from_config(config: &'a AlefConfig) -> Self {
29 Self {
30 config,
31 header: config.ffi_header_name(),
32 lib_name: config.ffi_lib_name(),
33 prefix: config.ffi_prefix(),
34 }
35 }
36}
37
38/// Return the C symbol name for freeing FFI-allocated strings.
39///
40/// Format: `{prefix}_free_string`
41///
42/// # Example
43/// ```ignore
44/// let sym = free_string_symbol("htm");
45/// assert_eq!(sym, "htm_free_string");
46/// ```
47pub fn free_string_symbol(prefix: &str) -> String {
48 format!("{prefix}_free_string")
49}
50
51/// Return the C symbol name for reading the thread-local last error code.
52///
53/// Format: `{prefix}_last_error_code`
54///
55/// # Example
56/// ```ignore
57/// let sym = last_error_code_symbol("krz");
58/// assert_eq!(sym, "krz_last_error_code");
59/// ```
60pub fn last_error_code_symbol(prefix: &str) -> String {
61 format!("{prefix}_last_error_code")
62}
63
64/// Return the C symbol name for reading the thread-local last error context message.
65///
66/// Format: `{prefix}_last_error_context`
67///
68/// # Example
69/// ```ignore
70/// let sym = last_error_context_symbol("krz");
71/// assert_eq!(sym, "krz_last_error_context");
72/// ```
73pub fn last_error_context_symbol(prefix: &str) -> String {
74 format!("{prefix}_last_error_context")
75}
76
77/// Resolve the per-backend output directory for generated files.
78///
79/// This helper wraps `resolve_output_dir` with a sensible default for C-FFI consumers,
80/// allowing backends to pass a language-specific default (e.g., "packages/go/", "packages/java/src/main/java/").
81///
82/// # Arguments
83/// - `config`: The Alef configuration.
84/// - `default`: The backend-specific default output directory (e.g., "packages/go/").
85///
86/// # Returns
87/// A PathBuf representing the resolved output directory.
88pub fn default_output_dir(config: &AlefConfig, default: &str) -> PathBuf {
89 let resolved = resolve_output_dir(None, &config.crate_config.name, default);
90 PathBuf::from(resolved)
91}