Search code examples
stringswiftcharacter-encodingcharacternscharacterset

Defining a custom PURE Swift Character Set


So, using Foundation you can use NSCharacterSet to define character sets and test character membership in Strings. I would like to do so without Cocoa classes, but in a purely Swift manner.

Ideally, code could be used like so:

struct ReservedCharacters: CharacterSet {
    characters "!", "#", "$", "&", ... etc.

    func isMember(character: Character) -> Bool

    func encodeCharacter(parameters) { accepts a closure }

    func decodeCharacter(parameters) { accepts a closure }
}

This is probably a very loaded question. But I'd like to see what you Swifters think.


Solution

  • You can already test for membership in a character set by initializing a String and using the contains global function:

    let vowels = "aeiou"
    
    let isVowel = contains(vowels, "i") // isVowel == true
    

    As far as your encode and decode functions go, are you just trying to get the 8-bit or 16-bit encodings for the Character? If that is the case then just convert them to a String and access there utf8 or utf16 properties:

    let char = Character("c")
    
    let a = Array(String(char).utf8)
    println()          // This prints [99]
    

    Decode would take a little more work, but I know there's a function for it...

    Edit: This will replace a character from a characterSet with '%' followed by the character's hex value:

    let encode: String -> String = { s in
        reduce(String(s).unicodeScalars, "") { x, y in
            switch contains(charSet, Character(y)) {
            case true:
                return x + "%" + String(y.value, radix: 16)
            default:
                return x + String(y)
            }
        }
    }
    
    let badURL = "http://why won't this work.com"
    let encoded = encode(badURL)
    println(encoded)   // prints "http://why%20won%27t%20this%20work.com"
    

    Decoding, again, is a bit more challenging, but I'm sure it can be done...