Swift equivalent to Objective-C FourCharCode single quote literals (e.g. 'TEXT')

I found the following typealiases from the Swift API:

typealias FourCharCode = UInt32
typealias OSType = FourCharCode

And the following functions:

func NSFileTypeForHFSTypeCode(hfsFileTypeCode: OSType) -> String!
func NSHFSTypeCodeFromFileType(fileTypeString: String!) -> OSType

This should allow me to create the equivalent code:

let type : UInt32 = UInt32(NSHFSTypeCodeFromFileType("TEXT"))
let creator : UInt32 = UInt32(NSHFSTypeCodeFromFileType("pdos"))

But those 4-character strings doesn't work and return 0.

If you wrap each string in ' single quotes ' and call the same functions, you will get the correct return values:

let type : UInt32 = UInt32(NSHFSTypeCodeFromFileType("'TEXT'"))
let creator : UInt32 = UInt32(NSHFSTypeCodeFromFileType("'pdos'"))

I'm using this in my Cocoa Scripting apps, it considers characters > 0x80 correctly

func OSTypeFrom(string : String) -> UInt {
  var result : UInt = 0
  if let data = string.dataUsingEncoding(NSMacOSRomanStringEncoding) {
    let bytes = UnsafePointer<UInt8>(data.bytes)
    for i in 0..<data.length {
      result = result << 8 + UInt(bytes[i])
    }
  }
  return result
}

Edit:

Alternatively

func fourCharCodeFrom(string : String) -> FourCharCode
{
  assert(string.count == 4, "String length must be 4")
  var result : FourCharCode = 0
  for char in string.utf16 {
    result = (result << 8) + FourCharCode(char)
  }
  return result
}

or still swiftier

func fourCharCode(from string : String) -> FourCharCode
{
  return string.utf16.reduce(0, {$0 << 8 + FourCharCode($1)})
}

In Swift 4 or later, I use this code - if the string is not 4 characters in size, it will return an OSType(0):

extension String {
    public func osType() -> OSType {
       var result:UInt = 0

       if let data = self.data(using: .macOSRoman), data.count == 4
       {
            data.withUnsafeBytes { (ptr:UnsafePointer<UInt8>) in
                for i in 0..<data.count {
                    result = result << 8 + UInt(ptr[i])
                }
            }
       }

       return OSType(result)
    }
}

let type = "APPL".osType()                 // 1095782476

// check if this is OK in a playground
let hexStr = String(format: "0x%lx", type) // 0x4150504c -> "APPL" in ASCII

Adopt the ExpressibleByStringLiteral protocol to use four-character string literals directly:

extension FourCharCode: ExpressibleByStringLiteral {
    
    public init(stringLiteral value: StringLiteralType) {
        if let data = value.data(using: .macOSRoman), data.count == 4 {
            self = data.reduce(0, {$0 << 8 + Self($1)})
        } else {
            self = 0
        }
    }
   
}

Now you can just pass a string literal as the FourCharCode / OSType / UInt32 parameter:

let record = NSAppleEventDescriptor.record()
record.setDescriptor(NSAppleEventDescriptor(boolean: true), forKeyword: "test")