swiftstringcommoncrypto

Is There A Swift preprocessor Way to Detect Bridging Header Includes?


The only answer I found was in this, and I'm not satisfied with it.

I am adding a standard MD5 converter as a String extension:

/* ###################################################################################################################################### */
/**
 From here: https://stackoverflow.com/q/24123518/879365
 I am not making this public, because it requires the common crypto in the bridging header.
 */
fileprivate extension String {
    /* ################################################################## */
    /**
     - returns: the String, as an MD5 hash.
     */
    var md5: String {
        let str = self.cString(using: String.Encoding.utf8)
        let strLen = CUnsignedInt(self.lengthOfBytes(using: String.Encoding.utf8))
        let digestLen = Int(CC_MD5_DIGEST_LENGTH)
        let result = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: digestLen)
        CC_MD5(str!, strLen, result)

        let hash = NSMutableString()

        for i in 0..<digestLen {
            hash.appendFormat("%02x", result[i])
        }

        result.deallocate()
        return hash as String
    }
}

It requires that I add the following to my bridging header:

#import <CommonCrypto/CommonCrypto.h>

Since I'd like to add this to a suite of reusable tools, I'd like to see if there was a way to detect, at compile time, whether or not the common crypto library was being used.

Is there a way for me to set this up as a conditional compile?

It's not a big deal if not; just means that I'll need to set this up as a separate source file.


Solution

  • It might be worth noting that you can call CC_MD5 without a bridging header, if you use dlsym to access it.

    import Foundation
    
    typealias CC_MD5_Type = @convention(c) (UnsafeRawPointer, UInt32, UnsafeMutableRawPointer) -> UnsafeMutableRawPointer
    
    let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: -2)
    let CC_MD5 = unsafeBitCast(dlsym(RTLD_DEFAULT, "CC_MD5")!, to: CC_MD5_Type.self)
    
    var md5 = Data(count: 16)
    md5.withUnsafeMutableBytes {
        _ = CC_MD5("abc", 3, $0)
    }
    
    assert(md5 == Data(bytes: [0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0, 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72]))