Skip to content

Fix enums and typedefs in framework crates #310

@madsmtm

Description

@madsmtm

Right now we're just using type aliases - instead, we should generate newtypes with the appropriate traits and constants. See also how Swift does it.

EDIT: I think the output should be something like this (depending on the naming scheme, so until that the variant/method names might be longer):

  • NS_OPTIONS (example: NSSortOptions):

    bitflags! {
        #[repr(transparent)]
        #[derive(Default)]
        pub struct NSSortOptions: NSUInteger {
            #[doc(alias = "NSSortConcurrent")]
            const CONCURRENT = 1 << 0;
            #[doc(alias = "NSSortStable")]
            const STABLE = 1 << 4;
        }
    }
    // Or perhaps we do something custom instead of `bitflags`?
    // Not sure if we want all the traits and helper functions it exposes?
    
    unsafe impl Encode for NSSortOptions { ... }
    unsafe impl RefEncode for NSSortOptions { ... }
  • NS_ENUM (example: NSDecodingFailurePolicy):

    // Cannot be a Rust `enum`, since that assumes that the enum is exhaustive
    // ABI-wise, even with `#[non_exhaustive]`.
    //
    // See https://play.rust-lang.org/?version=stable&mode=release&edition=2021&gist=3a19fcb4267d6fdb0d26b0c9defd946a
    #[repr(transparent)]
    #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
    pub struct NSDecodingFailurePolicy(NSInteger);
    
    unsafe impl Encode for NSDecodingFailurePolicy { ... }
    unsafe impl RefEncode for NSDecodingFailurePolicy { ... }
    
    impl NSDecodingFailurePolicy {
        pub fn as_raw(self) -> NSInteger { ... }
        pub fn from_raw(raw: NSInteger) -> Option<Self> { ... }
        pub unsafe fn from_raw_unchecked(raw: NSInteger) -> Self { ... }
    
        #[doc(alias = "NSDecodingFailurePolicyRaiseException")]
        pub const RAISE_EXCEPTION: Self = Self(0 as NSInteger);
        #[doc(alias = "NSDecodingFailurePolicySetErrorAndReturn")]
        pub const SET_ERROR_AND_RETURN: Self = Self(1 as NSInteger);
    }
    
    impl fmt::Debug for NSDecodingFailurePolicy { ... }
    
    // Same as `as_raw`
    impl From<NSDecodingFailurePolicy> for NSInteger { ... }
    // Same as `from_raw`
    impl TryFrom<NSInteger> for NSDecodingFailurePolicy { ... }
  • NS_CLOSED_ENUM (example: NSComparisonResult):

    #[repr(isize)]
    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
    enum NSComparisonResult {
        NSOrderedAscending = -1,
        NSOrderedSame = 0,
        NSOrderedDescending = 1,
    }
    
    unsafe impl Encode for NSComparisonResult { ... }
    unsafe impl RefEncode for NSComparisonResult { ... }
  • NS_TYPED_ENUM (example: NSStringEncodingDetectionOptionsKey):

    #[repr(C)]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct NSStringEncodingDetectionOptionsKey(NSString);
    
    unsafe impl RefEncode for NSStringEncodingDetectionOptionsKey { ... }
    unsafe impl Message for NSStringEncodingDetectionOptionsKey { ... }
    
    impl NSStringEncodingDetectionOptionsKey {
        pub fn as_raw(&self) -> &NSString { ... }
        pub fn into_raw(this: Id<Self>) -> Id<NSString> { ... }
        pub unsafe fn from_raw_unchecked(raw: &NSString) -> &Self { ... }
        pub unsafe fn from_raw_id_unchecked(raw: Id<NSString>) -> Id<Self> { ... }
    }
    
    // Delegates to `NSString`
    impl fmt::Display for NSStringEncodingDetectionOptionsKey { ... }
    
    // + AsRef, Borrow and From implementations
    
    // Constants
    impl NSStringEncodingDetectionOptionsKey {
        #[doc(alias = "NSStringEncodingDetectionSuggestedEncodingsKey")]
        pub fn suggested_encodings_key() -> &'static Self { ... }
    }
    impl NSStringEncodingDetectionOptionsKey {
        #[doc(alias = "NSStringEncodingDetectionDisallowedEncodingsKey")]
        pub fn disallowed_encodings_key() -> &'static Self { ... }
    }
    // ...
  • NS_TYPED_EXTENSIBLE_ENUM (example: NSExceptionName):

    #[repr(C)]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct NSExceptionName(pub(crate) NSString);
    
    unsafe impl RefEncode for NSExceptionName { ... }
    unsafe impl Message for NSExceptionName { ... }
    
    impl NSExceptionName {
        pub fn as_raw(&self) -> &NSString { ... }
        pub fn into_raw(this: Id<Self>) -> Id<NSString> { ... }
        pub fn from_raw(raw: &NSString) -> &Self { ... }
        pub fn from_raw_id(raw: Id<NSString>) -> Id<Self> { ... }
    }
    
    // Delegates to `NSString`
    impl fmt::Display for NSExceptionName { ... }
    
    // + AsRef, Borrow and From implementations
    
    // Constants (may be spread across frameworks)
    impl NSExceptionName {
        #[doc(alias = "NSGenericException")]
        pub fn generic_exception() -> &'static Self { ... }
    }
    impl NSExceptionName {
        #[doc(alias = "NSRangeException")]
        pub fn range_exception() -> &'static Self { ... }
    }
    // ...
  • NS_ERROR_ENUM with typedef (example: MTLIOError + MTLIOErrorDomain):

    todo!()
  • NS_ERROR_ENUM without typedef (example: NSURLErrorDomain + related URL errors):

    todo!()
  • Anonymous enum (example: Memory Allocation Options):

    const NSScannedOption: NSUInteger = 1 << 0;
    const NSCollectorDisabledOption: NSUInteger = 1 << 1;
    
    // Note: A bit unsure of the type here, maybe we just want to always use `NSInteger` like Swift does?

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-frameworkAffects the framework crates and the translator for themI-unsoundA soundness hole

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions