Files
core-foundation-rs/number.rs
T
2013-03-26 16:44:16 -06:00

187 lines
5.7 KiB
Rust

use base::{
AbstractCFTypeRef,
Boolean,
CFAllocatorRef,
CFIndex,
CFTypeID,
CFTypeRef,
CFWrapper,
kCFAllocatorDefault
};
use core::libc::{c_int, c_void};
pub type CFNumberType = u32;
// members of enum CFNumberType
static kCFNumberSInt8Type: CFNumberType = 1;
static kCFNumberSInt16Type: CFNumberType = 2;
static kCFNumberSInt32Type: CFNumberType = 3;
static kCFNumberSInt64Type: CFNumberType = 4;
static kCFNumberFloat32Type: CFNumberType = 5;
static kCFNumberFloat64Type: CFNumberType = 6;
static kCFNumberCharType: CFNumberType = 7;
static kCFNumberShortType: CFNumberType = 8;
static kCFNumberIntType: CFNumberType = 9;
static kCFNumberLongType: CFNumberType = 10;
static kCFNumberLongLongType: CFNumberType = 11;
static kCFNumberFloatType: CFNumberType = 12;
static kCFNumberDoubleType: CFNumberType = 13;
static kCFNumberCFIndexType: CFNumberType = 14;
static kCFNumberNSIntegerType: CFNumberType = 15;
static kCFNumberCGFloatType: CFNumberType = 16;
static kCFNumberMaxType: CFNumberType = 16;
struct __CFNumber { private: () }
pub type CFNumberRef = *__CFNumber;
impl AbstractCFTypeRef for CFNumberRef {
fn as_type_ref(&self) -> CFTypeRef { *self as CFTypeRef }
fn type_id() -> CFTypeID {
unsafe {
CFNumberGetTypeID()
}
}
}
pub type CFNumber = CFWrapper<CFNumberRef, (), ()>;
pub impl CFNumber {
fn new<T:Copy + ConvertibleToCFNumber>(n: T) -> CFNumber {
unsafe {
let objref = CFNumberCreate(kCFAllocatorDefault,
n.cf_number_type(),
cast::transmute::<&T, *c_void>(&n));
CFWrapper::wrap_owned(objref)
}
}
fn to_i8(&self) -> i8 {
let ty = kCFNumberSInt8Type;
assert!(self.has_number_type(ty));
unsafe {
let val: i8 = 0i8;
if !CFNumberGetValue(self.obj, ty, cast::transmute::<&i8, *c_void>(&val)) {
fail!(~"Error in unwrapping CFNumber to i8");
}
return val;
}
}
fn to_i16(&self) -> i16 {
let ty = kCFNumberSInt16Type;
assert!(self.has_number_type(ty));
unsafe {
let val: i16 = 0i16;
if !CFNumberGetValue(self.obj, ty, cast::transmute::<&i16, *c_void>(&val)) {
fail!(~"Error in unwrapping CFNumber to i16");
}
return val;
}
}
fn to_i32(&self) -> i32 {
let ty = kCFNumberSInt32Type;
assert!(self.has_number_type(ty));
unsafe {
let val: i32 = 0i32;
if !CFNumberGetValue(self.obj, ty, cast::transmute::<&i32, *c_void>(&val)) {
fail!(~"Error in unwrapping CFNumber to i32");
}
return val;
}
}
fn to_float(&self) -> float {
unsafe {
assert!(self.has_float_type());
let ty = CFNumberGetType(self.obj);
if ty == kCFNumberFloat32Type || ty == kCFNumberFloatType {
let mut val: libc::c_float = 0.0f as libc::c_float;
if !CFNumberGetValue(self.obj, ty, cast::transmute::<&libc::c_float, *c_void>(&val)) {
fail!(~"Error in unwrapping CFNumber to libc::c_float");
}
return val as float;
}
else if ty == kCFNumberFloat64Type || ty == kCFNumberDoubleType {
let mut val: libc::c_double = 0.0f as libc::c_double;
if !CFNumberGetValue(self.obj, ty, cast::transmute::<&libc::c_double, *c_void>(&val)) {
fail!(~"Error in unwrapping CFNumber to libc::c_double");
}
return val as float;
}
fail!(fmt!("Unable to wrap CFNumber into float: with type tag=%?", ty))
}
}
priv fn has_float_type(&self) -> bool {
unsafe {
CFNumberIsFloatType(self.obj) as bool
}
}
priv fn has_number_type(&self, ty: CFNumberType) -> bool {
unsafe {
CFNumberGetType(self.obj) == ty
}
}
}
pub trait ConvertibleToCFNumber {
// FIXME: Should be static, but that breaks.
fn cf_number_type(&self) -> CFNumberType;
}
impl ConvertibleToCFNumber for i8 {
fn cf_number_type(&self) -> CFNumberType { kCFNumberSInt8Type as CFNumberType }
}
impl ConvertibleToCFNumber for i16 {
fn cf_number_type(&self) -> CFNumberType { kCFNumberSInt16Type as CFNumberType }
}
impl ConvertibleToCFNumber for i32 {
fn cf_number_type(&self) -> CFNumberType { kCFNumberSInt32Type as CFNumberType }
}
impl ConvertibleToCFNumber for i64 {
fn cf_number_type(&self) -> CFNumberType { kCFNumberSInt64Type as CFNumberType }
}
impl ConvertibleToCFNumber for float {
fn cf_number_type(&self) -> CFNumberType { kCFNumberFloatType as CFNumberType }
}
#[link_args="-framework CoreFoundation"]
#[nolink]
extern {
/*
* CFNumber.h
*/
static kCFNumberNaN: CFNumberRef;
static kCFNumberNegativeInfinity: CFNumberRef;
static kCFNumberPositiveInfinity: CFNumberRef;
fn CFNumberCreate(allocator: CFAllocatorRef, theType: CFNumberType, valuePtr: *c_void)
-> CFNumberRef;
//fn CFNumberGetByteSize
fn CFNumberGetType(number: CFNumberRef) -> CFNumberType;
fn CFNumberGetValue(number: CFNumberRef, theType: CFNumberType, valuePtr: *c_void) -> bool;
fn CFNumberIsFloatType(number: CFNumberRef) -> Boolean;
//fn CFNumberCompare
fn CFNumberGetTypeID() -> CFTypeID;
}
#[test]
#[should_fail]
fn should_fail_on_bad_downcast() {
use base;
use boolean::CFBooleanRef;
let one = CFWrapper::to_CFType(CFNumber::new(1_i32));
base::downcast::<CFBooleanRef>(*one.borrow_ref());
}