Skip to content

Instantly share code, notes, and snippets.

@pitfield
Last active July 12, 2020 20:11
Show Gist options
  • Save pitfield/01bc4851e779091ec7d098ac3c83f68d to your computer and use it in GitHub Desktop.
Save pitfield/01bc4851e779091ec7d098ac3c83f68d to your computer and use it in GitHub Desktop.
Swift implementation of SASLPrep (RFC 4013)
//
// SASLPrep.swift
//
// Copyright 2020 David Pitfield
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
internal extension String {
/// Gets the SASLPrep (RFC 4013) transformation of this `String`.
///
/// - Parameter stringType: whether to treat this string as a "stored string"
/// or a "query" (see RFC 3454)
///
/// - Throws: `String.SASLPrepError` if the operation fails
/// - Returns: the transformed string
func saslPrep(stringType: SASLPrepStringType) throws -> String {
// Section 2.1 Mapping
var codeUnits = unicodeScalars.map { $0.isNonAsciiSpaceCharacter ? " " : $0 }
codeUnits = codeUnits.compactMap { $0.isCommonlyMappedToNothing ? nil : $0 }
// Section 2.2 Normalization
codeUnits = [UnicodeScalarView.Element](
String(UnicodeScalarView(codeUnits))
.precomposedStringWithCompatibilityMapping
.unicodeScalars)
// Section 2.3 Prohibited output
for codeUnit in codeUnits {
if codeUnit.isProhibitedOutput {
throw SASLPrepError.prohibitedOutput(scalar: codeUnit)
}
}
// Section 2.4 Bidirectional characters
let containsRandALCat = codeUnits.contains { $0.isRandALCat }
let containsLCat = codeUnits.contains { $0.isLCat }
if containsRandALCat && containsLCat {
throw SASLPrepError.prohibitedBidirectionalString(string: self)
}
if containsRandALCat {
if !codeUnits.first!.isRandALCat ||
!codeUnits.last!.isRandALCat {
throw SASLPrepError.prohibitedBidirectionalString(string: self)
}
}
// Section 2.5 Unassigned code points
if stringType == .storedString {
for codeUnit in codeUnits {
if codeUnit.isUnassignedCodePoint {
throw SASLPrepError.unassignedCodePoint(scalar: codeUnit)
}
}
}
return String(UnicodeScalarView(codeUnits))
}
enum SASLPrepStringType {
case storedString
case query
}
enum SASLPrepError: Error {
case prohibitedOutput(scalar: Unicode.Scalar)
case prohibitedBidirectionalString(string: String)
case unassignedCodePoint(scalar: Unicode.Scalar)
}
}
fileprivate extension Unicode.Scalar {
// The Unicode code point tables are from the Postgres server's SASLPrep implementation.
// https://doxygen.postgresql.org/saslprep_8c_source.html
// RFC 3454 table C.1.2
var isNonAsciiSpaceCharacter: Bool {
let ranges: [ClosedRange<UInt32>] = [
0x00A0...0x00A0,
0x1680...0x1680,
0x2000...0x200B,
0x202F...0x202F,
0x205F...0x205F,
0x3000...0x3000 ]
return ranges.contains { $0.contains(value) }
}
// RFC 3454 table B.1
var isCommonlyMappedToNothing: Bool {
let ranges: [ClosedRange<UInt32>] = [
0x00AD...0x00AD,
0x034F...0x034F,
0x1806...0x1806,
0x180B...0x180D,
0x200B...0x200D,
0x2060...0x2060,
0xFE00...0xFE0F,
0xFEFF...0xFEFF ]
return ranges.contains { $0.contains(value) }
}
// RFC 3454 tables:
// C.1.2 Non-ASCII space characters
// C.2.1 ASCII control characters
// C.2.2 Non-ASCII control characters
// C.3 Private Use characters
// C.4 Non-character code points
// C.5 Surrogate code points
// C.6 Inappropriate for plain text characters
// C.7 Inappropriate for canonical representation characters
// C.8 Change display properties or deprecated characters
// C.9 Tagging characters
var isProhibitedOutput: Bool {
let ranges: [ClosedRange<UInt32>] = [
0x0000...0x001F, // C.2.1
0x007F...0x00A0, // C.1.2...C.2.1...C.2.2
0x0340...0x0341, // C.8
0x06DD...0x06DD, // C.2.2
0x070F...0x070F, // C.2.2
0x1680...0x1680, // C.1.2
0x180E...0x180E, // C.2.2
0x2000...0x200F, // C.1.2...C.2.2...C.8
0x2028...0x202F, // C.1.2...C.2.2...C.8
0x205F...0x2063, // C.1.2...C.2.2
0x206A...0x206F, // C.2.2...C.8
0x2FF0...0x2FFB, // C.7
0x3000...0x3000, // C.1.2
0xD800...0xF8FF, // C.3...C.5
0xFDD0...0xFDEF, // C.4
0xFEFF...0xFEFF, // C.2.2
0xFFF9...0xFFFF, // C.2.2...C.4...C.6
0x1D173...0x1D17A, // C.2.2
0x1FFFE...0x1FFFF, // C.4
0x2FFFE...0x2FFFF, // C.4
0x3FFFE...0x3FFFF, // C.4
0x4FFFE...0x4FFFF, // C.4
0x5FFFE...0x5FFFF, // C.4
0x6FFFE...0x6FFFF, // C.4
0x7FFFE...0x7FFFF, // C.4
0x8FFFE...0x8FFFF, // C.4
0x9FFFE...0x9FFFF, // C.4
0xAFFFE...0xAFFFF, // C.4
0xBFFFE...0xBFFFF, // C.4
0xCFFFE...0xCFFFF, // C.4
0xDFFFE...0xDFFFF, // C.4
0xE0001...0xE0001, // C.9
0xE0020...0xE007F, // C.9
0xEFFFE...0xEFFFF, // C.4
0xF0000...0xFFFFF, // C.3...C.4
0x100000...0x10FFFF ] // C.3...C.4
return ranges.contains { $0.contains(value) }
}
// RFC 3454 table A.1
var isUnassignedCodePoint: Bool {
let ranges: [ClosedRange<UInt32>] = [
0x0221...0x0221,
0x0234...0x024F,
0x02AE...0x02AF,
0x02EF...0x02FF,
0x0350...0x035F,
0x0370...0x0373,
0x0376...0x0379,
0x037B...0x037D,
0x037F...0x0383,
0x038B...0x038B,
0x038D...0x038D,
0x03A2...0x03A2,
0x03CF...0x03CF,
0x03F7...0x03FF,
0x0487...0x0487,
0x04CF...0x04CF,
0x04F6...0x04F7,
0x04FA...0x04FF,
0x0510...0x0530,
0x0557...0x0558,
0x0560...0x0560,
0x0588...0x0588,
0x058B...0x0590,
0x05A2...0x05A2,
0x05BA...0x05BA,
0x05C5...0x05CF,
0x05EB...0x05EF,
0x05F5...0x060B,
0x060D...0x061A,
0x061C...0x061E,
0x0620...0x0620,
0x063B...0x063F,
0x0656...0x065F,
0x06EE...0x06EF,
0x06FF...0x06FF,
0x070E...0x070E,
0x072D...0x072F,
0x074B...0x077F,
0x07B2...0x0900,
0x0904...0x0904,
0x093A...0x093B,
0x094E...0x094F,
0x0955...0x0957,
0x0971...0x0980,
0x0984...0x0984,
0x098D...0x098E,
0x0991...0x0992,
0x09A9...0x09A9,
0x09B1...0x09B1,
0x09B3...0x09B5,
0x09BA...0x09BB,
0x09BD...0x09BD,
0x09C5...0x09C6,
0x09C9...0x09CA,
0x09CE...0x09D6,
0x09D8...0x09DB,
0x09DE...0x09DE,
0x09E4...0x09E5,
0x09FB...0x0A01,
0x0A03...0x0A04,
0x0A0B...0x0A0E,
0x0A11...0x0A12,
0x0A29...0x0A29,
0x0A31...0x0A31,
0x0A34...0x0A34,
0x0A37...0x0A37,
0x0A3A...0x0A3B,
0x0A3D...0x0A3D,
0x0A43...0x0A46,
0x0A49...0x0A4A,
0x0A4E...0x0A58,
0x0A5D...0x0A5D,
0x0A5F...0x0A65,
0x0A75...0x0A80,
0x0A84...0x0A84,
0x0A8C...0x0A8C,
0x0A8E...0x0A8E,
0x0A92...0x0A92,
0x0AA9...0x0AA9,
0x0AB1...0x0AB1,
0x0AB4...0x0AB4,
0x0ABA...0x0ABB,
0x0AC6...0x0AC6,
0x0ACA...0x0ACA,
0x0ACE...0x0ACF,
0x0AD1...0x0ADF,
0x0AE1...0x0AE5,
0x0AF0...0x0B00,
0x0B04...0x0B04,
0x0B0D...0x0B0E,
0x0B11...0x0B12,
0x0B29...0x0B29,
0x0B31...0x0B31,
0x0B34...0x0B35,
0x0B3A...0x0B3B,
0x0B44...0x0B46,
0x0B49...0x0B4A,
0x0B4E...0x0B55,
0x0B58...0x0B5B,
0x0B5E...0x0B5E,
0x0B62...0x0B65,
0x0B71...0x0B81,
0x0B84...0x0B84,
0x0B8B...0x0B8D,
0x0B91...0x0B91,
0x0B96...0x0B98,
0x0B9B...0x0B9B,
0x0B9D...0x0B9D,
0x0BA0...0x0BA2,
0x0BA5...0x0BA7,
0x0BAB...0x0BAD,
0x0BB6...0x0BB6,
0x0BBA...0x0BBD,
0x0BC3...0x0BC5,
0x0BC9...0x0BC9,
0x0BCE...0x0BD6,
0x0BD8...0x0BE6,
0x0BF3...0x0C00,
0x0C04...0x0C04,
0x0C0D...0x0C0D,
0x0C11...0x0C11,
0x0C29...0x0C29,
0x0C34...0x0C34,
0x0C3A...0x0C3D,
0x0C45...0x0C45,
0x0C49...0x0C49,
0x0C4E...0x0C54,
0x0C57...0x0C5F,
0x0C62...0x0C65,
0x0C70...0x0C81,
0x0C84...0x0C84,
0x0C8D...0x0C8D,
0x0C91...0x0C91,
0x0CA9...0x0CA9,
0x0CB4...0x0CB4,
0x0CBA...0x0CBD,
0x0CC5...0x0CC5,
0x0CC9...0x0CC9,
0x0CCE...0x0CD4,
0x0CD7...0x0CDD,
0x0CDF...0x0CDF,
0x0CE2...0x0CE5,
0x0CF0...0x0D01,
0x0D04...0x0D04,
0x0D0D...0x0D0D,
0x0D11...0x0D11,
0x0D29...0x0D29,
0x0D3A...0x0D3D,
0x0D44...0x0D45,
0x0D49...0x0D49,
0x0D4E...0x0D56,
0x0D58...0x0D5F,
0x0D62...0x0D65,
0x0D70...0x0D81,
0x0D84...0x0D84,
0x0D97...0x0D99,
0x0DB2...0x0DB2,
0x0DBC...0x0DBC,
0x0DBE...0x0DBF,
0x0DC7...0x0DC9,
0x0DCB...0x0DCE,
0x0DD5...0x0DD5,
0x0DD7...0x0DD7,
0x0DE0...0x0DF1,
0x0DF5...0x0E00,
0x0E3B...0x0E3E,
0x0E5C...0x0E80,
0x0E83...0x0E83,
0x0E85...0x0E86,
0x0E89...0x0E89,
0x0E8B...0x0E8C,
0x0E8E...0x0E93,
0x0E98...0x0E98,
0x0EA0...0x0EA0,
0x0EA4...0x0EA4,
0x0EA6...0x0EA6,
0x0EA8...0x0EA9,
0x0EAC...0x0EAC,
0x0EBA...0x0EBA,
0x0EBE...0x0EBF,
0x0EC5...0x0EC5,
0x0EC7...0x0EC7,
0x0ECE...0x0ECF,
0x0EDA...0x0EDB,
0x0EDE...0x0EFF,
0x0F48...0x0F48,
0x0F6B...0x0F70,
0x0F8C...0x0F8F,
0x0F98...0x0F98,
0x0FBD...0x0FBD,
0x0FCD...0x0FCE,
0x0FD0...0x0FFF,
0x1022...0x1022,
0x1028...0x1028,
0x102B...0x102B,
0x1033...0x1035,
0x103A...0x103F,
0x105A...0x109F,
0x10C6...0x10CF,
0x10F9...0x10FA,
0x10FC...0x10FF,
0x115A...0x115E,
0x11A3...0x11A7,
0x11FA...0x11FF,
0x1207...0x1207,
0x1247...0x1247,
0x1249...0x1249,
0x124E...0x124F,
0x1257...0x1257,
0x1259...0x1259,
0x125E...0x125F,
0x1287...0x1287,
0x1289...0x1289,
0x128E...0x128F,
0x12AF...0x12AF,
0x12B1...0x12B1,
0x12B6...0x12B7,
0x12BF...0x12BF,
0x12C1...0x12C1,
0x12C6...0x12C7,
0x12CF...0x12CF,
0x12D7...0x12D7,
0x12EF...0x12EF,
0x130F...0x130F,
0x1311...0x1311,
0x1316...0x1317,
0x131F...0x131F,
0x1347...0x1347,
0x135B...0x1360,
0x137D...0x139F,
0x13F5...0x1400,
0x1677...0x167F,
0x169D...0x169F,
0x16F1...0x16FF,
0x170D...0x170D,
0x1715...0x171F,
0x1737...0x173F,
0x1754...0x175F,
0x176D...0x176D,
0x1771...0x1771,
0x1774...0x177F,
0x17DD...0x17DF,
0x17EA...0x17FF,
0x180F...0x180F,
0x181A...0x181F,
0x1878...0x187F,
0x18AA...0x1DFF,
0x1E9C...0x1E9F,
0x1EFA...0x1EFF,
0x1F16...0x1F17,
0x1F1E...0x1F1F,
0x1F46...0x1F47,
0x1F4E...0x1F4F,
0x1F58...0x1F58,
0x1F5A...0x1F5A,
0x1F5C...0x1F5C,
0x1F5E...0x1F5E,
0x1F7E...0x1F7F,
0x1FB5...0x1FB5,
0x1FC5...0x1FC5,
0x1FD4...0x1FD5,
0x1FDC...0x1FDC,
0x1FF0...0x1FF1,
0x1FF5...0x1FF5,
0x1FFF...0x1FFF,
0x2053...0x2056,
0x2058...0x205E,
0x2064...0x2069,
0x2072...0x2073,
0x208F...0x209F,
0x20B2...0x20CF,
0x20EB...0x20FF,
0x213B...0x213C,
0x214C...0x2152,
0x2184...0x218F,
0x23CF...0x23FF,
0x2427...0x243F,
0x244B...0x245F,
0x24FF...0x24FF,
0x2614...0x2615,
0x2618...0x2618,
0x267E...0x267F,
0x268A...0x2700,
0x2705...0x2705,
0x270A...0x270B,
0x2728...0x2728,
0x274C...0x274C,
0x274E...0x274E,
0x2753...0x2755,
0x2757...0x2757,
0x275F...0x2760,
0x2795...0x2797,
0x27B0...0x27B0,
0x27BF...0x27CF,
0x27EC...0x27EF,
0x2B00...0x2E7F,
0x2E9A...0x2E9A,
0x2EF4...0x2EFF,
0x2FD6...0x2FEF,
0x2FFC...0x2FFF,
0x3040...0x3040,
0x3097...0x3098,
0x3100...0x3104,
0x312D...0x3130,
0x318F...0x318F,
0x31B8...0x31EF,
0x321D...0x321F,
0x3244...0x3250,
0x327C...0x327E,
0x32CC...0x32CF,
0x32FF...0x32FF,
0x3377...0x337A,
0x33DE...0x33DF,
0x33FF...0x33FF,
0x4DB6...0x4DFF,
0x9FA6...0x9FFF,
0xA48D...0xA48F,
0xA4C7...0xABFF,
0xD7A4...0xD7FF,
0xFA2E...0xFA2F,
0xFA6B...0xFAFF,
0xFB07...0xFB12,
0xFB18...0xFB1C,
0xFB37...0xFB37,
0xFB3D...0xFB3D,
0xFB3F...0xFB3F,
0xFB42...0xFB42,
0xFB45...0xFB45,
0xFBB2...0xFBD2,
0xFD40...0xFD4F,
0xFD90...0xFD91,
0xFDC8...0xFDCF,
0xFDFD...0xFDFF,
0xFE10...0xFE1F,
0xFE24...0xFE2F,
0xFE47...0xFE48,
0xFE53...0xFE53,
0xFE67...0xFE67,
0xFE6C...0xFE6F,
0xFE75...0xFE75,
0xFEFD...0xFEFE,
0xFF00...0xFF00,
0xFFBF...0xFFC1,
0xFFC8...0xFFC9,
0xFFD0...0xFFD1,
0xFFD8...0xFFD9,
0xFFDD...0xFFDF,
0xFFE7...0xFFE7,
0xFFEF...0xFFF8,
0x10000...0x102FF,
0x1031F...0x1031F,
0x10324...0x1032F,
0x1034B...0x103FF,
0x10426...0x10427,
0x1044E...0x1CFFF,
0x1D0F6...0x1D0FF,
0x1D127...0x1D129,
0x1D1DE...0x1D3FF,
0x1D455...0x1D455,
0x1D49D...0x1D49D,
0x1D4A0...0x1D4A1,
0x1D4A3...0x1D4A4,
0x1D4A7...0x1D4A8,
0x1D4AD...0x1D4AD,
0x1D4BA...0x1D4BA,
0x1D4BC...0x1D4BC,
0x1D4C1...0x1D4C1,
0x1D4C4...0x1D4C4,
0x1D506...0x1D506,
0x1D50B...0x1D50C,
0x1D515...0x1D515,
0x1D51D...0x1D51D,
0x1D53A...0x1D53A,
0x1D53F...0x1D53F,
0x1D545...0x1D545,
0x1D547...0x1D549,
0x1D551...0x1D551,
0x1D6A4...0x1D6A7,
0x1D7CA...0x1D7CD,
0x1D800...0x1FFFD,
0x2A6D7...0x2F7FF,
0x2FA1E...0x2FFFD,
0x30000...0x3FFFD,
0x40000...0x4FFFD,
0x50000...0x5FFFD,
0x60000...0x6FFFD,
0x70000...0x7FFFD,
0x80000...0x8FFFD,
0x90000...0x9FFFD,
0xA0000...0xAFFFD,
0xB0000...0xBFFFD,
0xC0000...0xCFFFD,
0xD0000...0xDFFFD,
0xE0000...0xE0000,
0xE0002...0xE001F,
0xE0080...0xEFFFD
]
return ranges.contains { $0.contains(value) }
}
// RFC 3454 table D.1
var isRandALCat: Bool {
let ranges: [ClosedRange<UInt32>] = [
0x05BE...0x05BE,
0x05C0...0x05C0,
0x05C3...0x05C3,
0x05D0...0x05EA,
0x05F0...0x05F4,
0x061B...0x061B,
0x061F...0x061F,
0x0621...0x063A,
0x0640...0x064A,
0x066D...0x066F,
0x0671...0x06D5,
0x06DD...0x06DD,
0x06E5...0x06E6,
0x06FA...0x06FE,
0x0700...0x070D,
0x0710...0x0710,
0x0712...0x072C,
0x0780...0x07A5,
0x07B1...0x07B1,
0x200F...0x200F,
0xFB1D...0xFB1D,
0xFB1F...0xFB28,
0xFB2A...0xFB36,
0xFB38...0xFB3C,
0xFB3E...0xFB3E,
0xFB40...0xFB41,
0xFB43...0xFB44,
0xFB46...0xFBB1,
0xFBD3...0xFD3D,
0xFD50...0xFD8F,
0xFD92...0xFDC7,
0xFDF0...0xFDFC,
0xFE70...0xFE74,
0xFE76...0xFEFC ]
return ranges.contains { $0.contains(value) }
}
// RFC 3454 table D.2
var isLCat: Bool {
let ranges: [ClosedRange<UInt32>] = [
0x0041...0x005A,
0x0061...0x007A,
0x00AA...0x00AA,
0x00B5...0x00B5,
0x00BA...0x00BA,
0x00C0...0x00D6,
0x00D8...0x00F6,
0x00F8...0x0220,
0x0222...0x0233,
0x0250...0x02AD,
0x02B0...0x02B8,
0x02BB...0x02C1,
0x02D0...0x02D1,
0x02E0...0x02E4,
0x02EE...0x02EE,
0x037A...0x037A,
0x0386...0x0386,
0x0388...0x038A,
0x038C...0x038C,
0x038E...0x03A1,
0x03A3...0x03CE,
0x03D0...0x03F5,
0x0400...0x0482,
0x048A...0x04CE,
0x04D0...0x04F5,
0x04F8...0x04F9,
0x0500...0x050F,
0x0531...0x0556,
0x0559...0x055F,
0x0561...0x0587,
0x0589...0x0589,
0x0903...0x0903,
0x0905...0x0939,
0x093D...0x0940,
0x0949...0x094C,
0x0950...0x0950,
0x0958...0x0961,
0x0964...0x0970,
0x0982...0x0983,
0x0985...0x098C,
0x098F...0x0990,
0x0993...0x09A8,
0x09AA...0x09B0,
0x09B2...0x09B2,
0x09B6...0x09B9,
0x09BE...0x09C0,
0x09C7...0x09C8,
0x09CB...0x09CC,
0x09D7...0x09D7,
0x09DC...0x09DD,
0x09DF...0x09E1,
0x09E6...0x09F1,
0x09F4...0x09FA,
0x0A05...0x0A0A,
0x0A0F...0x0A10,
0x0A13...0x0A28,
0x0A2A...0x0A30,
0x0A32...0x0A33,
0x0A35...0x0A36,
0x0A38...0x0A39,
0x0A3E...0x0A40,
0x0A59...0x0A5C,
0x0A5E...0x0A5E,
0x0A66...0x0A6F,
0x0A72...0x0A74,
0x0A83...0x0A83,
0x0A85...0x0A8B,
0x0A8D...0x0A8D,
0x0A8F...0x0A91,
0x0A93...0x0AA8,
0x0AAA...0x0AB0,
0x0AB2...0x0AB3,
0x0AB5...0x0AB9,
0x0ABD...0x0AC0,
0x0AC9...0x0AC9,
0x0ACB...0x0ACC,
0x0AD0...0x0AD0,
0x0AE0...0x0AE0,
0x0AE6...0x0AEF,
0x0B02...0x0B03,
0x0B05...0x0B0C,
0x0B0F...0x0B10,
0x0B13...0x0B28,
0x0B2A...0x0B30,
0x0B32...0x0B33,
0x0B36...0x0B39,
0x0B3D...0x0B3E,
0x0B40...0x0B40,
0x0B47...0x0B48,
0x0B4B...0x0B4C,
0x0B57...0x0B57,
0x0B5C...0x0B5D,
0x0B5F...0x0B61,
0x0B66...0x0B70,
0x0B83...0x0B83,
0x0B85...0x0B8A,
0x0B8E...0x0B90,
0x0B92...0x0B95,
0x0B99...0x0B9A,
0x0B9C...0x0B9C,
0x0B9E...0x0B9F,
0x0BA3...0x0BA4,
0x0BA8...0x0BAA,
0x0BAE...0x0BB5,
0x0BB7...0x0BB9,
0x0BBE...0x0BBF,
0x0BC1...0x0BC2,
0x0BC6...0x0BC8,
0x0BCA...0x0BCC,
0x0BD7...0x0BD7,
0x0BE7...0x0BF2,
0x0C01...0x0C03,
0x0C05...0x0C0C,
0x0C0E...0x0C10,
0x0C12...0x0C28,
0x0C2A...0x0C33,
0x0C35...0x0C39,
0x0C41...0x0C44,
0x0C60...0x0C61,
0x0C66...0x0C6F,
0x0C82...0x0C83,
0x0C85...0x0C8C,
0x0C8E...0x0C90,
0x0C92...0x0CA8,
0x0CAA...0x0CB3,
0x0CB5...0x0CB9,
0x0CBE...0x0CBE,
0x0CC0...0x0CC4,
0x0CC7...0x0CC8,
0x0CCA...0x0CCB,
0x0CD5...0x0CD6,
0x0CDE...0x0CDE,
0x0CE0...0x0CE1,
0x0CE6...0x0CEF,
0x0D02...0x0D03,
0x0D05...0x0D0C,
0x0D0E...0x0D10,
0x0D12...0x0D28,
0x0D2A...0x0D39,
0x0D3E...0x0D40,
0x0D46...0x0D48,
0x0D4A...0x0D4C,
0x0D57...0x0D57,
0x0D60...0x0D61,
0x0D66...0x0D6F,
0x0D82...0x0D83,
0x0D85...0x0D96,
0x0D9A...0x0DB1,
0x0DB3...0x0DBB,
0x0DBD...0x0DBD,
0x0DC0...0x0DC6,
0x0DCF...0x0DD1,
0x0DD8...0x0DDF,
0x0DF2...0x0DF4,
0x0E01...0x0E30,
0x0E32...0x0E33,
0x0E40...0x0E46,
0x0E4F...0x0E5B,
0x0E81...0x0E82,
0x0E84...0x0E84,
0x0E87...0x0E88,
0x0E8A...0x0E8A,
0x0E8D...0x0E8D,
0x0E94...0x0E97,
0x0E99...0x0E9F,
0x0EA1...0x0EA3,
0x0EA5...0x0EA5,
0x0EA7...0x0EA7,
0x0EAA...0x0EAB,
0x0EAD...0x0EB0,
0x0EB2...0x0EB3,
0x0EBD...0x0EBD,
0x0EC0...0x0EC4,
0x0EC6...0x0EC6,
0x0ED0...0x0ED9,
0x0EDC...0x0EDD,
0x0F00...0x0F17,
0x0F1A...0x0F34,
0x0F36...0x0F36,
0x0F38...0x0F38,
0x0F3E...0x0F47,
0x0F49...0x0F6A,
0x0F7F...0x0F7F,
0x0F85...0x0F85,
0x0F88...0x0F8B,
0x0FBE...0x0FC5,
0x0FC7...0x0FCC,
0x0FCF...0x0FCF,
0x1000...0x1021,
0x1023...0x1027,
0x1029...0x102A,
0x102C...0x102C,
0x1031...0x1031,
0x1038...0x1038,
0x1040...0x1057,
0x10A0...0x10C5,
0x10D0...0x10F8,
0x10FB...0x10FB,
0x1100...0x1159,
0x115F...0x11A2,
0x11A8...0x11F9,
0x1200...0x1206,
0x1208...0x1246,
0x1248...0x1248,
0x124A...0x124D,
0x1250...0x1256,
0x1258...0x1258,
0x125A...0x125D,
0x1260...0x1286,
0x1288...0x1288,
0x128A...0x128D,
0x1290...0x12AE,
0x12B0...0x12B0,
0x12B2...0x12B5,
0x12B8...0x12BE,
0x12C0...0x12C0,
0x12C2...0x12C5,
0x12C8...0x12CE,
0x12D0...0x12D6,
0x12D8...0x12EE,
0x12F0...0x130E,
0x1310...0x1310,
0x1312...0x1315,
0x1318...0x131E,
0x1320...0x1346,
0x1348...0x135A,
0x1361...0x137C,
0x13A0...0x13F4,
0x1401...0x1676,
0x1681...0x169A,
0x16A0...0x16F0,
0x1700...0x170C,
0x170E...0x1711,
0x1720...0x1731,
0x1735...0x1736,
0x1740...0x1751,
0x1760...0x176C,
0x176E...0x1770,
0x1780...0x17B6,
0x17BE...0x17C5,
0x17C7...0x17C8,
0x17D4...0x17DA,
0x17DC...0x17DC,
0x17E0...0x17E9,
0x1810...0x1819,
0x1820...0x1877,
0x1880...0x18A8,
0x1E00...0x1E9B,
0x1EA0...0x1EF9,
0x1F00...0x1F15,
0x1F18...0x1F1D,
0x1F20...0x1F45,
0x1F48...0x1F4D,
0x1F50...0x1F57,
0x1F59...0x1F59,
0x1F5B...0x1F5B,
0x1F5D...0x1F5D,
0x1F5F...0x1F7D,
0x1F80...0x1FB4,
0x1FB6...0x1FBC,
0x1FBE...0x1FBE,
0x1FC2...0x1FC4,
0x1FC6...0x1FCC,
0x1FD0...0x1FD3,
0x1FD6...0x1FDB,
0x1FE0...0x1FEC,
0x1FF2...0x1FF4,
0x1FF6...0x1FFC,
0x200E...0x200E,
0x2071...0x2071,
0x207F...0x207F,
0x2102...0x2102,
0x2107...0x2107,
0x210A...0x2113,
0x2115...0x2115,
0x2119...0x211D,
0x2124...0x2124,
0x2126...0x2126,
0x2128...0x2128,
0x212A...0x212D,
0x212F...0x2131,
0x2133...0x2139,
0x213D...0x213F,
0x2145...0x2149,
0x2160...0x2183,
0x2336...0x237A,
0x2395...0x2395,
0x249C...0x24E9,
0x3005...0x3007,
0x3021...0x3029,
0x3031...0x3035,
0x3038...0x303C,
0x3041...0x3096,
0x309D...0x309F,
0x30A1...0x30FA,
0x30FC...0x30FF,
0x3105...0x312C,
0x3131...0x318E,
0x3190...0x31B7,
0x31F0...0x321C,
0x3220...0x3243,
0x3260...0x327B,
0x327F...0x32B0,
0x32C0...0x32CB,
0x32D0...0x32FE,
0x3300...0x3376,
0x337B...0x33DD,
0x33E0...0x33FE,
0x3400...0x4DB5,
0x4E00...0x9FA5,
0xA000...0xA48C,
0xAC00...0xD7A3,
0xD800...0xFA2D,
0xFA30...0xFA6A,
0xFB00...0xFB06,
0xFB13...0xFB17,
0xFF21...0xFF3A,
0xFF41...0xFF5A,
0xFF66...0xFFBE,
0xFFC2...0xFFC7,
0xFFCA...0xFFCF,
0xFFD2...0xFFD7,
0xFFDA...0xFFDC,
0x10300...0x1031E,
0x10320...0x10323,
0x10330...0x1034A,
0x10400...0x10425,
0x10428...0x1044D,
0x1D000...0x1D0F5,
0x1D100...0x1D126,
0x1D12A...0x1D166,
0x1D16A...0x1D172,
0x1D183...0x1D184,
0x1D18C...0x1D1A9,
0x1D1AE...0x1D1DD,
0x1D400...0x1D454,
0x1D456...0x1D49C,
0x1D49E...0x1D49F,
0x1D4A2...0x1D4A2,
0x1D4A5...0x1D4A6,
0x1D4A9...0x1D4AC,
0x1D4AE...0x1D4B9,
0x1D4BB...0x1D4BB,
0x1D4BD...0x1D4C0,
0x1D4C2...0x1D4C3,
0x1D4C5...0x1D505,
0x1D507...0x1D50A,
0x1D50D...0x1D514,
0x1D516...0x1D51C,
0x1D51E...0x1D539,
0x1D53B...0x1D53E,
0x1D540...0x1D544,
0x1D546...0x1D546,
0x1D54A...0x1D550,
0x1D552...0x1D6A3,
0x1D6A8...0x1D7C9,
0x20000...0x2A6D6,
0x2F800...0x2FA1D,
0xF0000...0xFFFFD,
0x100000...0x10FFFD ]
return ranges.contains { $0.contains(value) }
}
}
// EOF
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment