apk-tools-sys 0.1.0

Rust bindings for Alpine Linux' package manager, the Alpine Package Keeper (APK)
use crate::*;
use std::{
    convert::TryFrom,
    error::Error,
    ffi::{CString, IntoStringError, NulError},
    fmt, slice,
};

impl apk_blob_t {
    pub fn new(string: &str) -> Self {
        apk_blob_t {
            len: string.len() as std::os::raw::c_long,
            ptr: CString::new(string).unwrap().into_raw(),
        }
    }
}

#[derive(Debug)]
pub enum ApkBlobConvertError {
    NullError(String),
    UTF8Error(String),
}

impl From<IntoStringError> for ApkBlobConvertError {
    fn from(e: IntoStringError) -> Self {
        Self::UTF8Error(e.to_string())
    }
}

impl From<NulError> for ApkBlobConvertError {
    fn from(e: NulError) -> Self {
        Self::NullError(e.to_string())
    }
}

impl fmt::Display for ApkBlobConvertError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ApkBlobConvertError::NullError(e) | ApkBlobConvertError::UTF8Error(e) => {
                write!(f, "{}", e)
            }
        }
    }
}

impl Error for ApkBlobConvertError {}

impl TryFrom<&apk_blob_t> for String {
    type Error = ApkBlobConvertError;

    fn try_from(blob: &apk_blob_t) -> Result<Self, Self::Error> {
        unsafe {
            let slice = slice::from_raw_parts::<u8>(blob.ptr.cast(), blob.len as usize);
            Ok(CString::new(slice)?.into_string()?)
        }
    }
}

impl Copy for apk_blob_t {}

impl Clone for apk_blob_t {
    fn clone(&self) -> Self {
        Self {
            len: self.len,
            ptr: self.ptr,
        }
    }
}