Skip to content

Commit 6ca12bd

Browse files
committed
Fix CFConstString on big-endian and document it a bit more
1 parent a4a5383 commit 6ca12bd

File tree

1 file changed

+34
-14
lines changed

1 file changed

+34
-14
lines changed

objc2-foundation/src/__string_macro.rs

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,23 @@ extern "C" {
2525
pub static __CFConstantStringClassReference: Class;
2626
}
2727

28-
// From `CFString.c`:
29-
// https://github.com/apple-oss-distributions/CF/blob/CF-1153.18/CFString.c#L184-L212
30-
// > !!! Note: Constant CFStrings use the bit patterns:
31-
// > C8 (11001000 = default allocator, not inline, not freed contents; 8-bit; has NULL byte; doesn't have length; is immutable)
32-
// > D0 (11010000 = default allocator, not inline, not freed contents; Unicode; is immutable)
33-
// > The bit usages should not be modified in a way that would effect these bit patterns.
34-
//
35-
// The 7 byte is the `CFTypeID` of `CFStringRef`.
36-
const FLAGS_ASCII: usize = 0x07_C8;
37-
const FLAGS_UTF16: usize = 0x07_D0;
38-
28+
/// Structure used to describe a constant `CFString`.
29+
///
30+
/// This struct is the same as [`CF_CONST_STRING`], which contains
31+
/// [`CFRuntimeBase`]. While the documentation clearly says that the ABI of
32+
/// `CFRuntimeBase` should not be relied on, we can rely on it as long as we
33+
/// only do it with regards to `CFString` (because `clang` does this as well).
34+
///
35+
/// [`CFRuntimeBase`]: <https://github.com/apple-oss-distributions/CF/blob/CF-1153.18/CFRuntime.h#L216-L228>
36+
/// [`CF_CONST_STRING`]: <https://github.com/apple-oss-distributions/CF/blob/CF-1153.18/CFInternal.h#L332-L336>
3937
#[repr(C)]
4038
pub struct CFConstString {
4139
isa: &'static Class,
42-
flags: usize,
40+
// Important that we don't just use `usize` here, since that would be
41+
// wrong on big-endian systems!
42+
cfinfo: u32,
43+
#[cfg(target_pointer_width = "64")]
44+
_rc: u32,
4345
data: *const c_void,
4446
len: usize,
4547
}
@@ -48,10 +50,26 @@ pub struct CFConstString {
4850
unsafe impl Sync for CFConstString {}
4951

5052
impl CFConstString {
53+
// From `CFString.c`:
54+
// <https://github.com/apple-oss-distributions/CF/blob/CF-1153.18/CFString.c#L184-L212>
55+
// > !!! Note: Constant CFStrings use the bit patterns:
56+
// > C8 (11001000 = default allocator, not inline, not freed contents; 8-bit; has NULL byte; doesn't have length; is immutable)
57+
// > D0 (11010000 = default allocator, not inline, not freed contents; Unicode; is immutable)
58+
// > The bit usages should not be modified in a way that would effect these bit patterns.
59+
//
60+
// Hence CoreFoundation guarantees that these two are always valid.
61+
//
62+
// The `CFTypeID` of `CFStringRef` is guaranteed to always be 7:
63+
// <https://github.com/apple-oss-distributions/CF/blob/CF-1153.18/CFRuntime.c#L982>
64+
const FLAGS_ASCII: u32 = 0x07_C8;
65+
const FLAGS_UTF16: u32 = 0x07_D0;
66+
5167
pub const unsafe fn new_ascii(isa: &'static Class, data: &'static [u8]) -> Self {
5268
Self {
5369
isa,
54-
flags: FLAGS_ASCII,
70+
cfinfo: Self::FLAGS_ASCII,
71+
#[cfg(target_pointer_width = "64")]
72+
_rc: 0,
5573
data: data.as_ptr().cast(),
5674
// The length does not include the trailing NUL.
5775
len: data.len() - 1,
@@ -61,7 +79,9 @@ impl CFConstString {
6179
pub const unsafe fn new_utf16(isa: &'static Class, data: &'static [u16]) -> Self {
6280
Self {
6381
isa,
64-
flags: FLAGS_UTF16,
82+
cfinfo: Self::FLAGS_UTF16,
83+
#[cfg(target_pointer_width = "64")]
84+
_rc: 0,
6585
data: data.as_ptr().cast(),
6686
// The length does not include the trailing NUL.
6787
len: data.len() - 1,

0 commit comments

Comments
 (0)