diff --git a/objc2-encode/src/encoding.rs b/objc2-encode/src/encoding.rs index e1079422b..0d8b5bd27 100644 --- a/objc2-encode/src/encoding.rs +++ b/objc2-encode/src/encoding.rs @@ -10,10 +10,13 @@ use crate::parse; /// NSLog(@"Encoding of NSException: %s", @encode(NSException)); /// ``` /// -/// For more information, see [Apple's documentation][ocrtTypeEncodings]. +/// For more information, see [Apple's documentation][ocrtTypeEncodings] and +/// [`clang`'s source code for generating `@encode`][clang-src]. /// -/// [ocrtTypeEncodings]: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html +/// [ocrtTypeEncodings]: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html +/// [clang-src]: https://github.com/llvm/llvm-project/blob/fae0dfa6421ea6c02f86ba7292fa782e1e2b69d1/clang/lib/AST/ASTContext.cpp#L7500-L7850 #[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[non_exhaustive] // Maybe we're missing some encodings? pub enum Encoding<'a> { /// A C `char`. Corresponds to the `c` code. Char, @@ -39,6 +42,15 @@ pub enum Encoding<'a> { Float, /// A C `double`. Corresponds to the `d` code. Double, + /// A C `long double`. Corresponds to the `D` code. + LongDouble, + /// A C `float _Complex`. Corresponds to the `jf` code. + FloatComplex, + /// A C `_Complex` or `double _Complex`. Corresponds to the `jd` code. + DoubleComplex, + /// A C `long double _Complex`. Corresponds to the `jD` code. + LongDoubleComplex, + // TODO: Complex(&Encoding) ??? /// A C++ `bool` / C99 `_Bool`. Corresponds to the `B` code. Bool, /// A C `void`. Corresponds to the `v` code. @@ -54,6 +66,8 @@ pub enum Encoding<'a> { /// An Objective-C selector (`SEL`). Corresponds to the `:` code. Sel, /// An unknown type. Corresponds to the `?` code. + /// + /// This is usually used to encode functions. Unknown, /// A bitfield with the given number of bits. /// @@ -81,6 +95,15 @@ pub enum Encoding<'a> { /// /// Corresponds to the `(name=fields...)` code. Union(&'a str, &'a [Encoding<'a>]), + // "Vector" types have the '!' encoding, but are not implemented in clang + + // TODO: Atomic, const and other such specifiers + // typedef struct x { + // int a; + // void* b; + // } x_t; + // NSLog(@"Encoding: %s", @encode(_Atomic x_t)); // -> A{x} + // NSLog(@"Encoding: %s", @encode(const int*)); // -> r^i } impl fmt::Display for Encoding<'_> { @@ -99,6 +122,10 @@ impl fmt::Display for Encoding<'_> { ULongLong => "Q", Float => "f", Double => "d", + LongDouble => "D", + FloatComplex => "jf", + DoubleComplex => "jd", + LongDoubleComplex => "jD", Bool => "B", Void => "v", String => "*", diff --git a/objc2-encode/src/lib.rs b/objc2-encode/src/lib.rs index d38590088..bc94f984a 100644 --- a/objc2-encode/src/lib.rs +++ b/objc2-encode/src/lib.rs @@ -1,6 +1,11 @@ //! # Objective-C type-encoding //! //! This is re-exported into the top level of `objc2`. +//! +//! Further resources: +//! - +//! - +//! - #![no_std] #![warn(elided_lifetimes_in_paths)] diff --git a/objc2-encode/src/parse.rs b/objc2-encode/src/parse.rs index 9fa00817b..69cd60009 100644 --- a/objc2-encode/src/parse.rs +++ b/objc2-encode/src/parse.rs @@ -28,6 +28,10 @@ fn rm_enc_prefix<'a>(s: &'a str, enc: &Encoding<'_>) -> Option<&'a str> { ULongLong => "Q", Float => "f", Double => "d", + LongDouble => "D", + FloatComplex => "jf", + DoubleComplex => "jd", + LongDoubleComplex => "jD", Bool => "B", Void => "v", String => "*", diff --git a/objc2/src/message/apple/x86.rs b/objc2/src/message/apple/x86.rs index a782ab942..ab2088faf 100644 --- a/objc2/src/message/apple/x86.rs +++ b/objc2/src/message/apple/x86.rs @@ -15,7 +15,9 @@ use crate::{Encode, Encoding}; /// unsafe impl MsgSendFn for T { const MSG_SEND: Imp = { - if let Encoding::Float | Encoding::Double = T::ENCODING { + // See lines 156 to 172 in: + // https://opensource.apple.com/source/objc4/objc4-818.2/runtime/message.h.auto.html + if let Encoding::Float | Encoding::Double | Encoding::LongDouble = T::ENCODING { objc_msgSend_fpret } else if let 0 | 1 | 2 | 4 | 8 = mem::size_of::() { objc_msgSend diff --git a/objc2/src/message/apple/x86_64.rs b/objc2/src/message/apple/x86_64.rs index 78fbbc3b5..1f1ee4147 100644 --- a/objc2/src/message/apple/x86_64.rs +++ b/objc2/src/message/apple/x86_64.rs @@ -1,9 +1,12 @@ use core::mem; -use objc_sys::{objc_msgSend, objc_msgSendSuper, objc_msgSendSuper_stret, objc_msgSend_stret}; +use objc_sys::{ + objc_msgSend, objc_msgSendSuper, objc_msgSendSuper_stret, objc_msgSend_fp2ret, + objc_msgSend_fpret, objc_msgSend_stret, +}; use super::MsgSendFn; use crate::runtime::Imp; -use crate::Encode; +use crate::{Encode, Encoding}; /// If the size of an object is larger than two eightbytes, it has class /// MEMORY. If the type has class MEMORY, then the caller provides space for @@ -13,7 +16,13 @@ use crate::Encode; unsafe impl MsgSendFn for T { // TODO: Should we use objc_msgSend_fpret and objc_msgSend_fp2ret ? const MSG_SEND: Imp = { - if mem::size_of::() <= 16 { + // See lines 156 to 172 in: + // https://opensource.apple.com/source/objc4/objc4-818.2/runtime/message.h.auto.html + if let Encoding::LongDouble = T::ENCODING { + objc_msgSend_fpret + } else if let Encoding::LongDoubleComplex = T::ENCODING { + objc_msgSend_fp2ret + } else if mem::size_of::() <= 16 { objc_msgSend } else { objc_msgSend_stret