use std::ffi::{CStr, CString};
use std::os::raw::c_char;
use slug::slugify;
use crate::ffi::ffi_utils::{c_str_from_str, load_repo_ffi, str_from_c_str};
use crate::fs::get_nibb_dir;
use crate::result::NibbFFIError;
use crate::{FSRepo, Snippet, SnippetRepository};
use crate::git::git_integration::nibb_git_generic;
#[unsafe(no_mangle)]
pub extern "C" fn load_snippet_ffi(name: *const c_char) -> *mut c_char {
let repo = match load_repo_ffi() {
Ok(repo) => repo,
Err(e) => return e,
};
let name = unsafe { CStr::from_ptr(name) };
let name = match name.to_str() {
Ok(name) => name,
Err(e) => return c_str_from_str(&NibbFFIError::FFIError(e.to_string()).to_json())
};
let slug = slugify(name);
let snippet = match repo.load(&slug) {
Ok(snippet) => snippet,
Err(e) => return c_str_from_str(&e.to_json())
};
c_str_from_str(&snippet.to_json())
}
#[unsafe(no_mangle)]
pub extern "C" fn save_snippet_ffi(snippet_json: *const c_char) -> bool {
let snippet_json = str_from_c_str(snippet_json);
let snippet = match serde_json::from_str(&snippet_json) {
Ok(snippet) => {
snippet
}
Err(_) => {
return false;
}
};
let repo = match FSRepo::new(get_nibb_dir().unwrap()) {
Ok(repo) => repo,
Err(_) => return false
};
match repo.save(&snippet) {
Ok(_) => true,
Err(_) => false,
}
}
#[unsafe(no_mangle)]
pub extern "C" fn delete_snippet_ffi(name: *const c_char) -> bool {
let repo = match FSRepo::new(get_nibb_dir().unwrap()) {
Ok(repo) => repo,
Err(_) => return false
};
let name = str_from_c_str(name);
match repo.delete(&name) {
Ok(_) => true,
Err(_) => false,
}
}
#[unsafe(no_mangle)]
pub extern "C" fn load_all_ffi() -> *mut c_char {
let repo = match load_repo_ffi() {
Ok(repo) => repo,
Err(e) => return e,
};
let snippets = match repo.load_all() {
Ok(snippets) => snippets,
Err(e) => return c_str_from_str(&e.to_json())
};
c_str_from_str(
&serde_json::to_string(&snippets)
.unwrap_or_else(|_| "{\"type\":\"Other\",\"message\":\"Serialization failed\"}"
.to_string())
)
}
#[unsafe(no_mangle)]
pub extern "C" fn save_all_ffi(snippets_json: *const c_char) -> bool {
let snippets_json = str_from_c_str(snippets_json);
let snippets: Vec<Snippet> = match serde_json::from_str(&snippets_json) {
Ok(snippets) => {
snippets
}
Err(_) => {
return false;
}
};
let repo = match load_repo_ffi() {
Ok(repo) => repo,
Err(_) => return false,
};
match repo.save_all(&snippets) {
Ok(_) => true,
Err(_) => false,
}
}
#[unsafe(no_mangle)]
pub extern "C" fn nibb_git_generic_ffi(args: *const c_char) -> *const c_char{
let args = str_from_c_str(args);
let args: Vec<String> = args.split_whitespace().map(|s| s.to_string()).collect();
let out = nibb_git_generic(args).unwrap_or_else(|e| e.to_json());
c_str_from_str(&out)
}
#[unsafe(no_mangle)]
pub extern "C" fn free_string_ffi(s: *mut c_char) {
unsafe {
if s.is_null() {
return;
}
drop(CString::from_raw(s));
}
}