use std::fmt;
use std::mem;
use std::ptr::{Unique, self};
use libc;
use low;
type Type_ = *mut low::ffi_type;
type TypeArray_ = *mut Type_;
type Owned<T> = T;
pub struct Type(Unique<low::ffi_type>);
pub struct TypeArray(Unique<*mut low::ffi_type>);
impl fmt::Debug for Type {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_fmt(format_args!("Type({:?})", *self.0))
}
}
impl fmt::Debug for TypeArray {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_fmt(format_args!("TypeArray({:?})", *self.0))
}
}
unsafe fn ffi_type_array_len(mut array: TypeArray_) -> usize {
let mut count = 0;
while !(*array).is_null() {
count += 1;
array = array.offset(1);
}
count
}
unsafe fn ffi_type_array_create_empty(len: usize) -> Owned<TypeArray_> {
let array = libc::malloc((len + 1) * mem::size_of::<Type_>())
as TypeArray_;
assert!(!array.is_null());
*array.offset(len as isize) = ptr::null::<low::ffi_type>() as Type_;
array
}
unsafe fn ffi_type_array_create(elements: Vec<Type>)
-> Owned<TypeArray_>
{
let size = elements.len();
let new = ffi_type_array_create_empty(size);
for i in 0 .. size {
*new.offset(i as isize) = *elements[i].0;
}
for t in elements {
mem::forget(t);
}
new
}
unsafe fn ffi_type_struct_create_raw(elements: Owned<TypeArray_>)
-> Owned<Type_>
{
let new = libc::malloc(mem::size_of::<low::ffi_type>()) as Type_;
assert!(!new.is_null());
(*new).size = 0;
(*new).alignment = 0;
(*new).type_ = low::type_tag::STRUCT;
(*new).elements = elements;
new
}
unsafe fn ffi_type_struct_create(elements: Vec<Type>) -> Owned<Type_> {
ffi_type_struct_create_raw(ffi_type_array_create(elements))
}
unsafe fn ffi_type_array_clone(old: TypeArray_) -> Owned<TypeArray_> {
let size = ffi_type_array_len(old);
let new = ffi_type_array_create_empty(size);
for i in 0 .. size {
*new.offset(i as isize) = ffi_type_clone(*old.offset(i as isize));
}
new
}
unsafe fn ffi_type_clone(old: Type_) -> Owned<Type_> {
if (*old).type_ == low::type_tag::STRUCT {
ffi_type_struct_create_raw(ffi_type_array_clone((*old).elements))
} else {
old
}
}
unsafe fn ffi_type_array_destroy(victim: Owned<TypeArray_>) {
let mut current = victim;
while !(*current).is_null() {
ffi_type_destroy(*current);
current = current.offset(1);
}
libc::free(victim as *mut libc::c_void);
}
unsafe fn ffi_type_destroy(victim: Owned<Type_>) {
if (*victim).type_ == low::type_tag::STRUCT {
ffi_type_array_destroy((*victim).elements);
libc::free(victim as *mut libc::c_void);
}
}
impl Drop for Type {
fn drop(&mut self) {
unsafe { ffi_type_destroy(self.0.get_mut()) }
}
}
impl Drop for TypeArray {
fn drop(&mut self) {
unsafe { ffi_type_array_destroy(self.0.get_mut()) }
}
}
impl Clone for Type {
fn clone(&self) -> Self {
unsafe { Type(Unique::new(ffi_type_clone(*self.0))) }
}
}
impl Clone for TypeArray {
fn clone(&self) -> Self {
unsafe {
TypeArray(Unique::new(ffi_type_array_clone(*self.0)))
}
}
}
impl Type {
pub fn void() -> Self {
Type(unsafe { Unique::new(&mut low::types::void) })
}
pub fn u8() -> Self {
Type(unsafe { Unique::new(&mut low::types::uint8) })
}
pub fn i8() -> Self {
Type(unsafe { Unique::new(&mut low::types::sint8) })
}
pub fn u16() -> Self {
Type(unsafe { Unique::new(&mut low::types::uint16) })
}
pub fn i16() -> Self {
Type(unsafe { Unique::new(&mut low::types::sint16) })
}
pub fn u32() -> Self {
Type(unsafe { Unique::new(&mut low::types::uint32) })
}
pub fn i32() -> Self {
Type(unsafe { Unique::new(&mut low::types::sint32) })
}
pub fn u64() -> Self {
Type(unsafe { Unique::new(&mut low::types::uint64) })
}
pub fn i64() -> Self {
Type(unsafe { Unique::new(&mut low::types::sint64) })
}
#[cfg(target_pointer_width = "16")]
pub fn usize() -> Self {
Self::u16()
}
#[cfg(target_pointer_width = "16")]
pub fn isize() -> Self {
Self::i16()
}
#[cfg(target_pointer_width = "32")]
pub fn usize() -> Self {
Self::u32()
}
#[cfg(target_pointer_width = "32")]
pub fn isize() -> Self {
Self::i32()
}
#[cfg(target_pointer_width = "64")]
pub fn usize() -> Self {
Self::u64()
}
#[cfg(target_pointer_width = "64")]
pub fn isize() -> Self {
Self::i64()
}
pub fn f32() -> Self {
Type(unsafe { Unique::new(&mut low::types::float) })
}
pub fn f64() -> Self {
Type(unsafe { Unique::new(&mut low::types::double) })
}
pub fn pointer() -> Self {
Type(unsafe { Unique::new(&mut low::types::pointer) })
}
pub fn longdouble() -> Self {
Type(unsafe { Unique::new(&mut low::types::longdouble) })
}
pub fn c32() -> Self {
Type(unsafe { Unique::new(&mut low::types::complex_float) })
}
pub fn c64() -> Self {
Type(unsafe { Unique::new(&mut low::types::complex_double) })
}
pub fn complex_longdouble() -> Self {
Type(unsafe { Unique::new(&mut low::types::complex_longdouble) })
}
pub fn structure(fields: Vec<Type>) -> Self {
unsafe {
Type(Unique::new(ffi_type_struct_create(fields)))
}
}
pub fn structure_from_array(fields: TypeArray) -> Self {
unsafe {
Type(Unique::new(ffi_type_struct_create_raw(*fields.0)))
}
}
pub fn as_raw_ptr(&self) -> *mut low::ffi_type {
*self.0
}
}
impl TypeArray {
pub fn new(elements: Vec<Type>) -> Self {
unsafe { TypeArray(Unique::new(ffi_type_array_create(elements))) }
}
pub fn len(&self) -> usize {
unsafe { ffi_type_array_len(*self.0) }
}
pub fn as_raw_ptr(&self) -> *mut *mut low::ffi_type {
*self.0
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn create_u64() {
Type::u64();
}
#[test]
fn clone_u64() {
Type::u64().clone().clone();
}
#[test]
fn create_struct() {
Type::structure(vec![Type::i64(),
Type::i64(),
Type::u64()]);
}
#[test]
fn clone_struct() {
Type::structure(vec![Type::i64(),
Type::i64(),
Type::u64()]).clone().clone();
}
}