llvm_quick 181.0.0-alpha.7

Rust's wrapper for llvm.
Documentation
use std::borrow::Borrow;
use std::ffi::{c_char, CStr};
use std::fmt::{Debug, Formatter};
use std::ops::Deref;
use std::ptr::NonNull;

use llvm_sys::error::*;

use crate::owning::{OpaqueDrop, Owning};
use crate::{Opaque, PhantomOpaque};

pub fn string_error_type_id() -> LLVMErrorTypeId {
    unsafe { LLVMGetStringErrorTypeId() }
}

#[repr(transparent)]
pub struct Error {
    _opaque: PhantomOpaque,
}

unsafe impl Opaque for Error {
    type Inner = LLVMOpaqueError;
}

impl Error {
    pub unsafe fn check(ptr: *mut LLVMOpaqueError) -> Result<(), Owning<Self>> {
        if let Some(e) = unsafe { Owning::from_ptr(ptr) } {
            Err(e)
        } else {
            Ok(())
        }
    }
}

impl Error {
    pub fn get_type_id(&self) -> LLVMErrorTypeId {
        unsafe { LLVMGetErrorTypeId(self.as_raw()) }
    }
}

impl OpaqueDrop for LLVMOpaqueError {
    unsafe fn drop_raw(ptr: *mut Self) {
        unsafe { LLVMConsumeError(ptr) }
    }
}

impl Error {
    pub fn get_message(&self) -> ErrorMessage {
        unsafe { ErrorMessage::from_raw(LLVMGetErrorMessage(self.as_raw())) }
    }
}

impl Drop for ErrorMessage {
    fn drop(&mut self) {
        unsafe { LLVMDisposeErrorMessage(self.as_raw()) }
    }
}

impl Error {
    pub fn create_string_error(err_msg: &CStr) -> Owning<Self> {
        unsafe { Owning::from_raw(LLVMCreateStringError(err_msg.as_ptr())) }
    }
}

impl Debug for Error {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        let mut s = f.debug_struct("Error");
        s.field("type_id", &self.get_type_id());
        s.field("message", &self.get_message());
        s.finish()
    }
}

pub struct ErrorMessage {
    ptr: NonNull<CStr>,
}

impl Debug for ErrorMessage {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        Debug::fmt(&self.deref(), f)
    }
}

impl AsRef<CStr> for ErrorMessage {
    fn as_ref(&self) -> &CStr {
        self.deref()
    }
}

impl Borrow<CStr> for ErrorMessage {
    fn borrow(&self) -> &CStr {
        self.deref()
    }
}

impl Deref for ErrorMessage {
    type Target = CStr;

    fn deref(&self) -> &Self::Target {
        unsafe { self.ptr.as_ref() }
    }
}

impl ErrorMessage {
    pub unsafe fn from_raw(ptr: *mut c_char) -> Self {
        let ptr = unsafe { CStr::from_ptr(ptr).into() };
        Self { ptr }
    }

    pub fn as_raw(&self) -> *mut c_char {
        self.ptr.as_ptr() as _
    }
}