📄 lib.rs
use std::ffi::{CStr, CString, c_char};

use syntect::{highlighting::ThemeSet, html::highlighted_html_for_string, parsing::SyntaxSet};

#[unsafe(no_mangle)]
pub extern "C" fn can_highlight_file(file_extension: *const c_char) -> bool {
    let Ok(ext) = unsafe { CStr::from_ptr(file_extension) }.to_str() else {
        return false;
    };

    let ss = SyntaxSet::load_defaults_newlines();
    ss.find_syntax_by_extension(&ext[1..]).is_some()
}

#[unsafe(no_mangle)]
pub extern "C" fn highlight_syntax_html(
    file_extension: *const c_char,
    text: *const c_char,
) -> *const c_char {
    let Ok(ext) = unsafe { CStr::from_ptr(file_extension) }.to_str() else {
        return CString::default().into_raw();
    };
    let Ok(text) = unsafe { CStr::from_ptr(text) }.to_str() else {
        return CString::default().into_raw();
    };

    let ss = SyntaxSet::load_defaults_newlines();
    let Some(syntax) = ss.find_syntax_by_extension(&ext[1..]) else {
        return CString::default().into_raw();
    };

    let ts = ThemeSet::load_defaults();
    let github_theme = &ts.themes["base16-ocean.dark"];

    let Ok(highlighted) = highlighted_html_for_string(text, &ss, syntax, github_theme) else {
        return CString::default().into_raw();
    };
    CString::new(highlighted)
        .unwrap_or_else(|_| CString::default())
        .into_raw()
}