objc2_core_foundation/
number.rs1use core::cmp::Ordering;
2use core::ptr;
3
4use crate::{kCFBooleanFalse, kCFBooleanTrue, CFBoolean, CFNumber, CFNumberType, CFRetained};
5
6impl CFBoolean {
7 pub fn new(value: bool) -> &'static CFBoolean {
8 if value {
9 unsafe { kCFBooleanTrue }.unwrap()
10 } else {
11 unsafe { kCFBooleanFalse }.unwrap()
12 }
13 }
14
15 pub fn as_bool(&self) -> bool {
16 self.value()
17 }
18}
19
20macro_rules! def_new_fn {
21 {$(
22 $(#[$($m:meta)*])*
23 ($fn_name:ident($fn_inp:ty); $type:ident),
24 )*} => {$(
25 $(#[$($m)*])*
26 #[inline]
27 pub fn $fn_name(val: $fn_inp) -> CFRetained<Self> {
28 let ptr: *const $fn_inp = &val;
29 unsafe { Self::new(None, CFNumberType::$type, ptr.cast()).expect("failed creating CFNumber") }
30 }
31 )*}
32}
33
34impl CFNumber {
35 def_new_fn! {
36 (new_i8(i8); SInt8Type),
37 (new_i16(i16); SInt16Type),
38 (new_i32(i32); SInt32Type),
39 (new_i64(i64); SInt64Type),
40 (new_isize(isize); NSIntegerType),
41
42 (new_f32(f32); Float32Type),
43 (new_f64(f64); Float64Type),
44 }
45
46 #[cfg(feature = "CFCGTypes")]
47 #[inline]
48 pub fn new_cgfloat(val: crate::CGFloat) -> CFRetained<Self> {
49 #[cfg(not(target_pointer_width = "64"))]
50 {
51 Self::new_f32(val)
52 }
53 #[cfg(target_pointer_width = "64")]
54 {
55 Self::new_f64(val)
56 }
57 }
58}
59
60macro_rules! def_get_fn {
61 {$(
62 $(#[$($m:meta)*])*
63 ($fn_name:ident -> $fn_ret:ty; $type:ident),
64 )*} => {$(
65 $(#[$($m)*])*
66 #[inline]
67 pub fn $fn_name(&self) -> Option<$fn_ret> {
68 let mut value: $fn_ret = <$fn_ret>::default();
69 let ptr: *mut $fn_ret = &mut value;
70 let ret = unsafe { self.value(CFNumberType::$type, ptr.cast()) };
71 if ret {
72 Some(value)
73 } else {
74 None
75 }
76 }
77 )*}
78}
79
80impl CFNumber {
81 def_get_fn! {
82 (as_i8 -> i8; SInt8Type),
83 (as_i16 -> i16; SInt16Type),
84 (as_i32 -> i32; SInt32Type),
85 (as_i64 -> i64; SInt64Type),
86 (as_isize -> isize; NSIntegerType),
87
88 (as_f32 -> f32; Float32Type),
89 (as_f64 -> f64; Float64Type),
90 }
91
92 #[cfg(feature = "CFCGTypes")]
93 #[inline]
94 pub fn as_cgfloat(&self) -> Option<crate::CGFloat> {
95 #[cfg(not(target_pointer_width = "64"))]
96 {
97 self.as_f32()
98 }
99 #[cfg(target_pointer_width = "64")]
100 {
101 self.as_f64()
102 }
103 }
104}
105
106impl PartialOrd for CFNumber {
107 #[inline]
108 #[doc(alias = "CFNumberCompare")]
109 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
110 Some(self.cmp(other))
111 }
112}
113
114impl Ord for CFNumber {
115 #[inline]
116 #[doc(alias = "CFNumberCompare")]
117 fn cmp(&self, other: &Self) -> Ordering {
118 let context = ptr::null_mut();
120 unsafe { self.compare(Some(other), context) }.into()
121 }
122}
123
124#[cfg(test)]
125mod tests {
126 use super::*;
127
128 #[test]
129 fn to_from_bool() {
130 let cffalse = CFBoolean::new(false);
131 let cftrue = CFBoolean::new(true);
132 assert_ne!(cffalse, cftrue);
133 assert_eq!(cftrue, CFBoolean::new(true));
134 assert_eq!(cffalse, CFBoolean::new(false));
135 assert!(!cffalse.as_bool());
136 assert!(cftrue.as_bool());
137 }
138
139 #[test]
140 fn to_from_number() {
141 let n = CFNumber::new_i32(442);
142 if cfg!(all(target_os = "macos", target_arch = "x86")) {
143 assert_eq!(n.as_i8(), None);
145 } else {
146 assert_eq!(n.as_i8(), Some(442i32 as i8));
147 }
148 assert_eq!(n.as_i16(), Some(442));
149 assert_eq!(n.as_i32(), Some(442));
150 assert_eq!(n.as_i64(), Some(442));
151 assert_eq!(n.as_f32(), Some(442.0));
152 assert_eq!(n.as_f64(), Some(442.0));
153 }
154
155 #[test]
156 fn cmp_number() {
157 assert!(CFNumber::new_i32(2) < CFNumber::new_i32(3));
158 assert!(CFNumber::new_i32(3) == CFNumber::new_i32(3));
159 assert!(CFNumber::new_i32(4) > CFNumber::new_i32(3));
160 }
161}