Skip to content

Commit ff0d74c

Browse files
committed
Implement PartialOrd and Ord for CF types
Implement for the types that support it, namely `CFDate`, `CFNumber` and `CFString`.
1 parent 3e0e109 commit ff0d74c

File tree

5 files changed

+128
-6
lines changed

5 files changed

+128
-6
lines changed

framework-crates/objc2-core-foundation/src/base.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,13 @@
3939
// That means we can use `isize`/`usize`, which is more ergonomic.
4040

4141
use core::cell::UnsafeCell;
42+
use core::cmp::Ordering;
4243
use core::convert::AsRef;
4344
use core::fmt;
4445
use core::hash;
4546
use core::marker::{PhantomData, PhantomPinned};
4647

48+
use crate::CFComparisonResult;
4749
use crate::ConcreteType;
4850
use crate::{CFEqual, CFHash, Type};
4951

@@ -164,3 +166,32 @@ crate::__cf_type_objc2!(CFType, crate::__cf_macro_helpers::Encoding::Void);
164166

165167
// NOTE: impl AsRef<CFType> for AnyObject would probably not be valid, since
166168
// not all Objective-C objects can be used as CoreFoundation objects (?)
169+
170+
impl Default for CFComparisonResult {
171+
#[inline]
172+
fn default() -> Self {
173+
Self::CompareEqualTo
174+
}
175+
}
176+
177+
impl From<Ordering> for CFComparisonResult {
178+
#[inline]
179+
fn from(order: Ordering) -> Self {
180+
match order {
181+
Ordering::Less => Self::CompareLessThan,
182+
Ordering::Equal => Self::CompareEqualTo,
183+
Ordering::Greater => Self::CompareGreaterThan,
184+
}
185+
}
186+
}
187+
188+
impl From<CFComparisonResult> for Ordering {
189+
#[inline]
190+
fn from(comparison_result: CFComparisonResult) -> Self {
191+
match comparison_result.0 {
192+
..=-1 => Self::Less, // ..=CFComparisonResult::CompareLessThan
193+
0 => Self::Equal, // CFComparisonResult::CompareEqualTo
194+
1.. => Self::Greater, // CFComparisonResult::CompareGreaterThan..
195+
}
196+
}
197+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#![cfg(feature = "CFBase")]
2+
use core::{cmp::Ordering, ptr};
3+
4+
use crate::{CFDate, CFDateCompare};
5+
6+
impl PartialOrd for CFDate {
7+
#[inline]
8+
#[doc(alias = "CFDateCompare")]
9+
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
10+
Some(self.cmp(other))
11+
}
12+
}
13+
14+
impl Ord for CFDate {
15+
#[inline]
16+
#[doc(alias = "CFDateCompare")]
17+
fn cmp(&self, other: &Self) -> Ordering {
18+
// Documented that one should pass NULL here.
19+
let context = ptr::null_mut();
20+
unsafe { CFDateCompare(self, Some(other), context) }.into()
21+
}
22+
}
23+
24+
#[cfg(test)]
25+
mod test {
26+
use crate::{CFAbsoluteTimeGetCurrent, CFDateCreate, CFDateGetAbsoluteTime};
27+
28+
use super::*;
29+
30+
#[test]
31+
fn cmp() {
32+
let now = unsafe { CFDateCreate(None, CFAbsoluteTimeGetCurrent()).unwrap() };
33+
let past = unsafe { CFDateCreate(None, CFDateGetAbsoluteTime(&now) - 1.0).unwrap() };
34+
assert_eq!(now.cmp(&past), Ordering::Greater);
35+
assert_eq!(now.cmp(&now), Ordering::Equal);
36+
assert_eq!(past.cmp(&now), Ordering::Less);
37+
38+
assert_eq!(now, now);
39+
assert_ne!(now, past);
40+
}
41+
}

framework-crates/objc2-core-foundation/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,15 @@ mod base;
2323
#[cfg(feature = "CFBundle")]
2424
mod bundle;
2525
mod cf_type;
26+
#[cfg(feature = "CFDate")]
27+
mod date;
2628
mod generated;
2729
#[cfg(feature = "CFCGTypes")]
2830
mod geometry;
2931
#[cfg(feature = "CFNumber")]
3032
mod number;
3133
mod retained;
32-
#[cfg(all(feature = "CFBase", feature = "CFString"))]
34+
#[cfg(feature = "CFString")]
3335
mod string;
3436
mod type_traits;
3537

framework-crates/objc2-core-foundation/src/number.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
#![cfg(feature = "CFBase")]
2+
use core::cmp::Ordering;
3+
use core::ptr;
4+
25
use crate::{
3-
kCFBooleanFalse, kCFBooleanTrue, CFBoolean, CFBooleanGetValue, CFNumber, CFNumberCreate,
4-
CFNumberGetValue, CFNumberType, CFRetained,
6+
kCFBooleanFalse, kCFBooleanTrue, CFBoolean, CFBooleanGetValue, CFNumber, CFNumberCompare,
7+
CFNumberCreate, CFNumberGetValue, CFNumberType, CFRetained,
58
};
69

710
impl CFBoolean {
@@ -104,6 +107,24 @@ impl CFNumber {
104107
}
105108
}
106109

110+
impl PartialOrd for CFNumber {
111+
#[inline]
112+
#[doc(alias = "CFNumberCompare")]
113+
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
114+
Some(self.cmp(other))
115+
}
116+
}
117+
118+
impl Ord for CFNumber {
119+
#[inline]
120+
#[doc(alias = "CFNumberCompare")]
121+
fn cmp(&self, other: &Self) -> Ordering {
122+
// Documented that one should pass NULL here.
123+
let context = ptr::null_mut();
124+
unsafe { CFNumberCompare(self, Some(other), context) }.into()
125+
}
126+
}
127+
107128
#[cfg(test)]
108129
mod tests {
109130
use super::*;
@@ -129,4 +150,11 @@ mod tests {
129150
assert_eq!(n.as_f32(), Some(442.0));
130151
assert_eq!(n.as_f64(), Some(442.0));
131152
}
153+
154+
#[test]
155+
fn cmp_number() {
156+
assert!(CFNumber::new_i32(2) < CFNumber::new_i32(3));
157+
assert!(CFNumber::new_i32(3) == CFNumber::new_i32(3));
158+
assert!(CFNumber::new_i32(4) > CFNumber::new_i32(3));
159+
}
132160
}

framework-crates/objc2-core-foundation/src/string.rs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1+
#![cfg(feature = "CFBase")]
2+
use core::cmp::Ordering;
13
use core::ffi::{c_char, CStr};
24
use core::fmt::Write;
35
use core::ptr::NonNull;
46
use core::{fmt, str};
57

68
use crate::{
7-
kCFAllocatorNull, Boolean, CFRange, CFRetained, CFString, CFStringCreateWithBytes,
8-
CFStringCreateWithBytesNoCopy, CFStringEncoding, CFStringGetBytes, CFStringGetCStringPtr,
9-
CFStringGetLength,
9+
kCFAllocatorNull, Boolean, CFRange, CFRetained, CFString, CFStringCompare,
10+
CFStringCompareFlags, CFStringCreateWithBytes, CFStringCreateWithBytesNoCopy, CFStringEncoding,
11+
CFStringGetBytes, CFStringGetCStringPtr, CFStringGetLength,
1012
};
1113

1214
#[track_caller]
@@ -172,6 +174,24 @@ impl fmt::Display for CFString {
172174
}
173175
}
174176

177+
impl PartialOrd for CFString {
178+
#[inline]
179+
#[doc(alias = "CFStringCompare")]
180+
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
181+
Some(self.cmp(other))
182+
}
183+
}
184+
185+
impl Ord for CFString {
186+
#[inline]
187+
#[doc(alias = "CFStringCompare")]
188+
fn cmp(&self, other: &Self) -> Ordering {
189+
// Request standard lexiographical ordering.
190+
let flags = CFStringCompareFlags::empty();
191+
unsafe { CFStringCompare(self, Some(other), flags) }.into()
192+
}
193+
}
194+
175195
#[cfg(test)]
176196
mod tests {
177197
use alloc::string::ToString;

0 commit comments

Comments
 (0)