libknot 0.2.3

High Level bindings to a subset of libknot, the library of the knot dns server
Documentation
#[cfg(feature = "native")]
use libknot_sys as sys;
#[cfg(feature = "native")]
use std::os::raw;
#[cfg(feature = "native")]
use std::ffi::CStr;

use std::string::FromUtf8Error;
use thiserror::Error;

#[derive(Debug, Error)]
pub enum KnotError {
    #[error("Out of Memory")]
    #[cfg(feature = "native")]
    OutOfMemory,
    #[error("Knot Error Code {code}")]
    #[cfg(feature = "native")]
    KnotError { code: u32, message: String },
    #[error("NUL Byte in String")]
    #[cfg(feature = "native")]
    NulError,
    #[error("UTF-8 Error")]
    UTF8Error,
    #[error("Knot Error Message: {msg}")]
    KnotErrorMsg { msg: String },
    #[error("IO Error: {err}")]
    IOError {
        #[from] err: std::io::Error,
    },
    #[error("Invalid Field Index: {}", _0)]
    InvalidFieldIndex(u8),
    #[error("Section is of invalid type")]
    InvalidSectionType,
    #[error("Section is not present")]
    UnknownSection,
    #[error("Attempt to nest two transactions")]
    NestedTransaction,
    #[error("Config item ID unknown")]
    UnknownID,
}

impl From<FromUtf8Error> for KnotError {
    fn from(_: FromUtf8Error) -> Self {
        KnotError::UTF8Error
    }
}

#[cfg(feature = "native")]
pub fn auto_err(code: raw::c_int) -> Result<()> {
    if code == sys::knot_error_KNOT_EOK {
        Ok(())
    } else {
        let c_str = unsafe { sys::knot_strerror(code) };
        if c_str.is_null() {
            panic!("Unknown error code {}", code);
        }
        let val = unsafe { CStr::from_ptr(c_str) };
        Err(KnotError::KnotError {
            code: code as u32,
            message: val.to_string_lossy().to_string(),
        })
    }
}

pub type Result<T> = ::std::result::Result<T, KnotError>;