use std::marker::PhantomData;
use std::fmt;
use gccjit_sys;
use context::Context;
use context;
use object;
use object::{Object, ToObject};
use gccjit_sys::gcc_jit_types::*;
#[derive(Copy, Clone)]
pub struct Type<'ctx> {
marker: PhantomData<&'ctx Context<'ctx>>,
ptr: *mut gccjit_sys::gcc_jit_type
}
impl<'ctx> ToObject<'ctx> for Type<'ctx> {
fn to_object(&self) -> Object<'ctx> {
unsafe {
let ptr = gccjit_sys::gcc_jit_type_as_object(self.ptr);
object::from_ptr(ptr)
}
}
}
impl<'ctx> fmt::Debug for Type<'ctx> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
let obj = self.to_object();
obj.fmt(fmt)
}
}
impl<'ctx> Type<'ctx> {
pub fn make_pointer(self) -> Type<'ctx> {
unsafe {
from_ptr(gccjit_sys::gcc_jit_type_get_pointer(self.ptr))
}
}
pub fn make_const(self) -> Type<'ctx> {
unsafe {
from_ptr(gccjit_sys::gcc_jit_type_get_const(self.ptr))
}
}
pub fn make_volatile(self) -> Type<'ctx> {
unsafe {
from_ptr(gccjit_sys::gcc_jit_type_get_volatile(self.ptr))
}
}
}
pub trait Typeable {
fn get_type<'a, 'ctx>(&'a Context<'ctx>) -> Type<'a>;
}
macro_rules! typeable_def {
($ty:ty, $expr:expr) => {
impl Typeable for $ty {
fn get_type<'a, 'ctx>(ctx: &'a Context<'ctx>) -> Type<'a> {
unsafe {
let ctx_ptr = context::get_ptr(ctx);
let ptr = gccjit_sys::gcc_jit_context_get_type(ctx_ptr, $expr);
from_ptr(ptr)
}
}
}
}
}
typeable_def!((), GCC_JIT_TYPE_VOID);
typeable_def!(bool, GCC_JIT_TYPE_BOOL);
typeable_def!(char, GCC_JIT_TYPE_CHAR);
typeable_def!(i8, GCC_JIT_TYPE_SIGNED_CHAR);
typeable_def!(u8, GCC_JIT_TYPE_UNSIGNED_CHAR);
typeable_def!(i16, GCC_JIT_TYPE_SHORT);
typeable_def!(u16, GCC_JIT_TYPE_UNSIGNED_SHORT);
typeable_def!(i32, GCC_JIT_TYPE_INT);
typeable_def!(u32, GCC_JIT_TYPE_UNSIGNED_INT);
typeable_def!(i64, GCC_JIT_TYPE_LONG);
typeable_def!(u64, GCC_JIT_TYPE_UNSIGNED_LONG);
typeable_def!(f32, GCC_JIT_TYPE_FLOAT);
typeable_def!(f64, GCC_JIT_TYPE_DOUBLE);
typeable_def!(usize, GCC_JIT_TYPE_SIZE_T);
impl<T> Typeable for *mut T {
fn get_type<'a, 'ctx>(ctx: &'a Context<'ctx>) -> Type<'a> {
unsafe {
let ctx_ptr = context::get_ptr(ctx);
let ptr = gccjit_sys::gcc_jit_context_get_type(ctx_ptr, GCC_JIT_TYPE_VOID_PTR);
from_ptr(ptr)
}
}
}
impl<T> Typeable for *const T {
fn get_type<'a, 'ctx>(ctx: &'a Context<'ctx>) -> Type<'a> {
unsafe {
let ctx_ptr = context::get_ptr(ctx);
let ptr = gccjit_sys::gcc_jit_context_get_type(ctx_ptr, GCC_JIT_TYPE_VOID_PTR);
from_ptr(ptr).make_const()
}
}
}
pub unsafe fn from_ptr<'ctx>(ptr: *mut gccjit_sys::gcc_jit_type) -> Type<'ctx> {
Type {
marker: PhantomData,
ptr: ptr
}
}
pub unsafe fn get_ptr<'ctx>(ty: &Type<'ctx>) -> *mut gccjit_sys::gcc_jit_type {
ty.ptr
}