llam 0.1.3

Safe, Go-style Rust bindings for the LLAM runtime
use crate::error::{Error, Result};
use crate::sys;
use std::ffi::CStr;
use std::mem;

#[derive(Clone, Copy, Debug)]
pub struct AbiInfo {
    raw: sys::llam_abi_info_t,
}

impl AbiInfo {
    pub fn load() -> Result<Self> {
        let mut raw = unsafe { mem::zeroed::<sys::llam_abi_info_t>() };
        let rc = unsafe { sys::llam_abi_get_info(&mut raw, mem::size_of_val(&raw)) };
        if rc == 0 {
            Ok(Self { raw })
        } else {
            Err(Error::last())
        }
    }

    pub fn abi_major(&self) -> u32 {
        self.raw.abi_major
    }

    pub fn abi_minor(&self) -> u32 {
        self.raw.abi_minor
    }

    pub fn version(&self) -> (u32, u32, u32) {
        (
            self.raw.version_major,
            self.raw.version_minor,
            self.raw.version_patch,
        )
    }

    pub fn runtime_name(&self) -> String {
        cstr_to_string(self.raw.runtime_name)
    }

    pub fn version_string(&self) -> String {
        cstr_to_string(self.raw.version_string)
    }

    pub fn platform_name(&self) -> String {
        cstr_to_string(self.raw.platform_name)
    }

    pub fn raw(&self) -> &sys::llam_abi_info_t {
        &self.raw
    }
}

pub fn abi_version() -> u32 {
    unsafe { sys::llam_abi_version() }
}

pub fn version_string() -> String {
    unsafe { cstr_to_string(sys::llam_version_string()) }
}

fn cstr_to_string(ptr: *const std::os::raw::c_char) -> String {
    if ptr.is_null() {
        String::new()
    } else {
        unsafe { CStr::from_ptr(ptr) }
            .to_string_lossy()
            .into_owned()
    }
}