| ... | ... | @@ -157,7 +157,7 @@ fn Processing( |
| 157 | 157 | while (it.nextCodepointSlice()) |s| { |
| 158 | 158 | const c = std.unicode.utf8Decode(s) catch unreachable; |
| 159 | 159 | const p = ucd.unicode_data.find(c); |
| 160 | | switch (p[4]) { |
| 160 | switch (ucd.unicode_data.data_bc[p]) { |
| 161 | 161 | .R, .AL, .AN => domain_is_bidi = true, |
| 162 | 162 | else => {}, |
| 163 | 163 | } |
| ... | ... | @@ -229,11 +229,13 @@ fn Validity_Criteria( |
| 229 | 229 | const first_l = std.unicode.utf8ByteSequenceLength(first_b) catch unreachable; |
| 230 | 230 | const first_c = std.unicode.utf8Decode(label[0..first_l]) catch unreachable; |
| 231 | 231 | const first_p = ucd.unicode_data.find(first_c); |
| 232 | | if (first_p[2] == .M) return error.IDNAFailure; |
| 233 | | if (first_p[2] == .Combining_Mark) return error.IDNAFailure; |
| 234 | | if (first_p[2] == .Mc) return error.IDNAFailure; |
| 235 | | if (first_p[2] == .Me) return error.IDNAFailure; |
| 236 | | if (first_p[2] == .Mn) return error.IDNAFailure; |
| 232 | const first_gc = ucd.unicode_data.data_gc[first_p]; |
| 233 | const first_bc = ucd.unicode_data.data_bc[first_p]; |
| 234 | if (first_gc == .M) return error.IDNAFailure; |
| 235 | if (first_gc == .Combining_Mark) return error.IDNAFailure; |
| 236 | if (first_gc == .Mc) return error.IDNAFailure; |
| 237 | if (first_gc == .Me) return error.IDNAFailure; |
| 238 | if (first_gc == .Mn) return error.IDNAFailure; |
| 237 | 239 | |
| 238 | 240 | // 7. Each code point in the label must only have certain Status values according to Section 5, IDNA Mapping Table: |
| 239 | 241 | var it = std.unicode.Utf8View.initUnchecked(label).iterator(); |
| ... | ... | @@ -241,8 +243,8 @@ fn Validity_Criteria( |
| 241 | 243 | var prev_cp: u21 = 0; |
| 242 | 244 | |
| 243 | 245 | // 8. If CheckJoiners, the label must satisify the ContextJ rules from RFC 5892 Appendix A. |
| 244 | | var point_2before: ucd.unicode_data.Codepoint = ucd.unicode_data.data[0]; |
| 245 | | var point_before: ucd.unicode_data.Codepoint = ucd.unicode_data.data[0]; |
| 246 | var point_2before: usize = 0; |
| 247 | var point_before: usize = 0; |
| 246 | 248 | var zwnj_state: enum { start, dual_joining, transparent1, zwnj, transparent2, right_joining } = .start; |
| 247 | 249 | var check_zwnj_state: ?bool = null; |
| 248 | 250 | |
| ... | ... | @@ -257,7 +259,7 @@ fn Validity_Criteria( |
| 257 | 259 | var seen_an = false; |
| 258 | 260 | var last_bidi_class: ucd.BidiClass = .NSM; |
| 259 | 261 | if (CheckBidi) { |
| 260 | | switch (first_p[4]) { |
| 262 | switch (first_bc) { |
| 261 | 263 | .L => {}, |
| 262 | 264 | .R, .AL => {}, |
| 263 | 265 | else => return error.IDNAFailure, |
| ... | ... | @@ -274,23 +276,25 @@ fn Validity_Criteria( |
| 274 | 276 | for (&ucd.derived_normalization_props.nfc_qc_n.data) |d| if (cp == d) return error.IDNAFailure; |
| 275 | 277 | for (&ucd.derived_normalization_props.nfc_qc_n.data_range) |d| if (cp >= d.from and cp <= d.to) return error.IDNAFailure; |
| 276 | 278 | for (&ucd.derived_normalization_props.nfc_qc_m.data) |d| if (cp == d) { |
| 277 | | for (&ucd.unicode_data.data) |r| { |
| 278 | | if (r[5] != .__canonical) continue; |
| 279 | | if (r[6].len != 2) continue; |
| 280 | | if (r[6][0] != prev_cp) continue; |
| 281 | | if (r[6][1] != cp) continue; |
| 282 | | if (std.sort.binarySearch(u21, &ucd.composition_exclusions.data, r[0], extras.compareFnBasic(u21)) != null) continue; |
| 279 | const ud = ucd.unicode_data; |
| 280 | for (&ud.data_code, &ud.data_decomp, &ud.data_decomp_map) |_cp, dc, dm| { |
| 281 | if (dc != .__canonical) continue; |
| 282 | if (dm.len != 2) continue; |
| 283 | if (dm[0] != prev_cp) continue; |
| 284 | if (dm[1] != cp) continue; |
| 285 | if (std.sort.binarySearch(u21, &ucd.composition_exclusions.data, _cp, extras.compareFnBasic(u21)) != null) continue; |
| 283 | 286 | // if (r[3] != 0) continue; |
| 284 | 287 | return error.IDNAFailure; |
| 285 | 288 | } |
| 286 | 289 | }; |
| 287 | 290 | for (&ucd.derived_normalization_props.nfc_qc_m.data_range) |d| if (cp >= d.from and cp <= d.to) { |
| 288 | | for (&ucd.unicode_data.data) |r| { |
| 289 | | if (r[5] != .__canonical) continue; |
| 290 | | if (r[6].len != 2) continue; |
| 291 | | if (r[6][0] != prev_cp) continue; |
| 292 | | if (r[6][1] != cp) continue; |
| 293 | | if (std.sort.binarySearch(u21, &ucd.composition_exclusions.data, r[0], extras.compareFnBasic(u21)) != null) continue; |
| 291 | const ud = ucd.unicode_data; |
| 292 | for (&ud.data_code, &ud.data_decomp, &ud.data_decomp_map) |cpp, dc, dm| { |
| 293 | if (dc != .__canonical) continue; |
| 294 | if (dm.len != 2) continue; |
| 295 | if (dm[0] != prev_cp) continue; |
| 296 | if (dm[1] != cp) continue; |
| 297 | if (std.sort.binarySearch(u21, &ucd.composition_exclusions.data, cpp, extras.compareFnBasic(u21)) != null) continue; |
| 294 | 298 | // if (r[3] != 0) continue; |
| 295 | 299 | return error.IDNAFailure; |
| 296 | 300 | } |
| ... | ... | @@ -316,12 +320,13 @@ fn Validity_Criteria( |
| 316 | 320 | } |
| 317 | 321 | |
| 318 | 322 | const p = ucd.unicode_data.find(cp); |
| 323 | const p_bc = ucd.unicode_data.data_bc[p]; |
| 319 | 324 | |
| 320 | 325 | if (CheckJoiners) { |
| 321 | 326 | // Appendix A.1. ZERO WIDTH NON-JOINER |
| 322 | 327 | if (cp == 0x200C) { |
| 323 | 328 | if (check_zwnj_state == null) check_zwnj_state = true; |
| 324 | | if (point_before[3] == 9) check_zwnj_state = false; |
| 329 | if (ucd.unicode_data.data_ccc[point_before] == 9) check_zwnj_state = false; |
| 325 | 330 | } |
| 326 | 331 | switch (zwnj_state) { |
| 327 | 332 | .start => { |
| ... | ... | @@ -377,15 +382,15 @@ fn Validity_Criteria( |
| 377 | 382 | }, |
| 378 | 383 | } |
| 379 | 384 | // Appendix A.2. ZERO WIDTH JOINER |
| 380 | | if (cp == 0x200D and point_before[3] != 9) return error.IDNAFailure; |
| 385 | if (cp == 0x200D and ucd.unicode_data.data_ccc[point_before] != 9) return error.IDNAFailure; |
| 381 | 386 | // Appendix A.3. MIDDLE DOT |
| 382 | | if (point_before[0] == 0x00B7 and !(point_2before[0] == 0x006C and cp == 0x006C)) return error.IDNAFailure; |
| 387 | if (ucd.unicode_data.data_code[point_before] == 0x00B7 and !(ucd.unicode_data.data_code[point_2before] == 0x006C and cp == 0x006C)) return error.IDNAFailure; |
| 383 | 388 | // Appendix A.4. GREEK LOWER NUMERAL SIGN (KERAIA) |
| 384 | | if (point_before[0] == 0x0375 and !(Script(cp) == .Greek)) return error.IDNAFailure; |
| 389 | if (ucd.unicode_data.data_code[point_before] == 0x0375 and !(Script(cp) == .Greek)) return error.IDNAFailure; |
| 385 | 390 | // Appendix A.5. HEBREW PUNCTUATION GERESH |
| 386 | | if (cp == 0x05F3 and !(Script(point_before[0]) == .Hebrew)) return error.IDNAFailure; |
| 391 | if (cp == 0x05F3 and !(Script(ucd.unicode_data.data_code[point_before]) == .Hebrew)) return error.IDNAFailure; |
| 387 | 392 | // Appendix A.6. HEBREW PUNCTUATION GERSHAYIM |
| 388 | | if (cp == 0x05F4 and !(Script(point_before[0]) == .Hebrew)) return error.IDNAFailure; |
| 393 | if (cp == 0x05F4 and !(Script(ucd.unicode_data.data_code[point_before]) == .Hebrew)) return error.IDNAFailure; |
| 389 | 394 | // Appendix A.7. KATAKANA MIDDLE DOT |
| 390 | 395 | if (false) return error.IDNAFailure; |
| 391 | 396 | // Appendix A.8. ARABIC-INDIC DIGITS |
| ... | ... | @@ -397,24 +402,24 @@ fn Validity_Criteria( |
| 397 | 402 | point_before = p; |
| 398 | 403 | |
| 399 | 404 | if (CheckBidi) { |
| 400 | | switch (first_p[4]) { |
| 405 | switch (first_bc) { |
| 401 | 406 | .L => { |
| 402 | | switch (p[4]) { |
| 407 | switch (p_bc) { |
| 403 | 408 | .L, .EN, .ES, .CS, .ET, .ON, .BN => |cl| last_bidi_class = cl, |
| 404 | 409 | .NSM => {}, |
| 405 | 410 | else => return error.IDNAFailure, |
| 406 | 411 | } |
| 407 | 412 | }, |
| 408 | 413 | .R, .AL => { |
| 409 | | switch (p[4]) { |
| 414 | switch (p_bc) { |
| 410 | 415 | .R, .AL, .AN, .EN, .ES, .CS, .ET, .ON, .BN => |cl| last_bidi_class = cl, |
| 411 | 416 | .NSM => {}, |
| 412 | 417 | else => return error.IDNAFailure, |
| 413 | 418 | } |
| 414 | | if (p[4] == .EN and seen_an) return error.IDNAFailure; |
| 415 | | if (p[4] == .EN) seen_en = true; |
| 416 | | if (p[4] == .AN and seen_en) return error.IDNAFailure; |
| 417 | | if (p[4] == .AN) seen_an = true; |
| 419 | if (p_bc == .EN and seen_an) return error.IDNAFailure; |
| 420 | if (p_bc == .EN) seen_en = true; |
| 421 | if (p_bc == .AN and seen_en) return error.IDNAFailure; |
| 422 | if (p_bc == .AN) seen_an = true; |
| 418 | 423 | }, |
| 419 | 424 | else => unreachable, |
| 420 | 425 | } |
| ... | ... | @@ -424,7 +429,7 @@ fn Validity_Criteria( |
| 424 | 429 | if (check_zwnj_state == true and zwnj_state != .right_joining) return error.IDNAFailure; |
| 425 | 430 | } |
| 426 | 431 | if (CheckBidi) { |
| 427 | | switch (first_p[4]) { |
| 432 | switch (first_bc) { |
| 428 | 433 | .L => { |
| 429 | 434 | switch (last_bidi_class) { |
| 430 | 435 | .L, .EN => {}, |