use std::ffi::{CStr, CString};
use std::path::Path;
use std::ptr::NonNull;
#[derive(Debug)]
pub struct GgufContext {
ctx: NonNull<llama_cpp_sys_2::gguf_context>,
}
impl GgufContext {
pub fn from_file(path: &Path) -> Option<Self> {
let c_path = CString::new(path.to_str()?).ok()?;
let params = llama_cpp_sys_2::gguf_init_params {
no_alloc: true,
ctx: std::ptr::null_mut(),
};
let ptr = unsafe { llama_cpp_sys_2::gguf_init_from_file(c_path.as_ptr(), params) };
Some(Self {
ctx: NonNull::new(ptr)?,
})
}
pub fn n_kv(&self) -> i64 {
unsafe { llama_cpp_sys_2::gguf_get_n_kv(self.ctx.as_ptr()) }
}
pub fn find_key(&self, key: &str) -> i64 {
let Ok(c_key) = CString::new(key) else {
return -1;
};
unsafe { llama_cpp_sys_2::gguf_find_key(self.ctx.as_ptr(), c_key.as_ptr()) }
}
pub fn key_at(&self, idx: i64) -> Option<&str> {
let ptr = unsafe { llama_cpp_sys_2::gguf_get_key(self.ctx.as_ptr(), idx) };
if ptr.is_null() {
return None;
}
unsafe { CStr::from_ptr(ptr).to_str().ok() }
}
pub fn kv_type(&self, idx: i64) -> llama_cpp_sys_2::gguf_type {
unsafe { llama_cpp_sys_2::gguf_get_kv_type(self.ctx.as_ptr(), idx) }
}
pub fn val_u32(&self, idx: i64) -> u32 {
unsafe { llama_cpp_sys_2::gguf_get_val_u32(self.ctx.as_ptr(), idx) }
}
pub fn val_i32(&self, idx: i64) -> i32 {
unsafe { llama_cpp_sys_2::gguf_get_val_i32(self.ctx.as_ptr(), idx) }
}
pub fn val_u64(&self, idx: i64) -> u64 {
unsafe { llama_cpp_sys_2::gguf_get_val_u64(self.ctx.as_ptr(), idx) }
}
pub fn val_str(&self, idx: i64) -> Option<&str> {
let ptr = unsafe { llama_cpp_sys_2::gguf_get_val_str(self.ctx.as_ptr(), idx) };
if ptr.is_null() {
return None;
}
unsafe { CStr::from_ptr(ptr).to_str().ok() }
}
pub fn n_tensors(&self) -> i64 {
unsafe { llama_cpp_sys_2::gguf_get_n_tensors(self.ctx.as_ptr()) }
}
}
impl Drop for GgufContext {
fn drop(&mut self) {
unsafe { llama_cpp_sys_2::gguf_free(self.ctx.as_ptr()) }
}
}
#[cfg(test)]
mod tests;