@@ -294,6 +294,104 @@ pub fn resourceprep(s: &str) -> Result<Cow<'_, str>, Error> {
294
294
Ok ( Cow :: Owned ( normalized) )
295
295
}
296
296
297
+ fn is_combining_char ( c : char ) -> bool {
298
+ matches ! ( c, '\u{0300}' ..='\u{0345}' |
299
+ '\u{0360}' ..='\u{0361}' |
300
+ '\u{0483}' ..='\u{0486}' |
301
+ '\u{0591}' ..='\u{05A1}' |
302
+ '\u{05A3}' ..='\u{05B9}' |
303
+ '\u{05BB}' ..='\u{05BD}' |
304
+ '\u{05BF}' |
305
+ '\u{05C1}' ..='\u{05C2}' |
306
+ '\u{05C4}' |
307
+ '\u{064B}' ..='\u{0652}' |
308
+ '\u{0670}' |
309
+ '\u{06D6}' ..='\u{06DC}' |
310
+ '\u{06DD}' ..='\u{06DF}' |
311
+ '\u{06E0}' ..='\u{06E4}' |
312
+ '\u{06E7}' ..='\u{06E8}' |
313
+ '\u{06EA}' ..='\u{06ED}' |
314
+ '\u{0901}' ..='\u{0903}' |
315
+ '\u{093C}' |
316
+ '\u{093E}' ..='\u{094C}' |
317
+ '\u{094D}' |
318
+ '\u{0951}' ..='\u{0954}' |
319
+ '\u{0962}' ..='\u{0963}' |
320
+ '\u{0981}' ..='\u{0983}' |
321
+ '\u{09BC}' |
322
+ '\u{09BE}' |
323
+ '\u{09BF}' |
324
+ '\u{09C0}' ..='\u{09C4}' |
325
+ '\u{09C7}' ..='\u{09C8}' |
326
+ '\u{09CB}' ..='\u{09CD}' |
327
+ '\u{09D7}' |
328
+ '\u{09E2}' ..='\u{09E3}' |
329
+ '\u{0A02}' |
330
+ '\u{0A3C}' |
331
+ '\u{0A3E}' |
332
+ '\u{0A3F}' |
333
+ '\u{0A40}' ..='\u{0A42}' |
334
+ '\u{0A47}' ..='\u{0A48}' |
335
+ '\u{0A4B}' ..='\u{0A4D}' |
336
+ '\u{0A70}' ..='\u{0A71}' |
337
+ '\u{0A81}' ..='\u{0A83}' |
338
+ '\u{0ABC}' |
339
+ '\u{0ABE}' ..='\u{0AC5}' |
340
+ '\u{0AC7}' ..='\u{0AC9}' |
341
+ '\u{0ACB}' ..='\u{0ACD}' |
342
+ '\u{0B01}' ..='\u{0B03}' |
343
+ '\u{0B3C}' |
344
+ '\u{0B3E}' ..='\u{0B43}' |
345
+ '\u{0B47}' ..='\u{0B48}' |
346
+ '\u{0B4B}' ..='\u{0B4D}' |
347
+ '\u{0B56}' ..='\u{0B57}' |
348
+ '\u{0B82}' ..='\u{0B83}' |
349
+ '\u{0BBE}' ..='\u{0BC2}' |
350
+ '\u{0BC6}' ..='\u{0BC8}' |
351
+ '\u{0BCA}' ..='\u{0BCD}' |
352
+ '\u{0BD7}' |
353
+ '\u{0C01}' ..='\u{0C03}' |
354
+ '\u{0C3E}' ..='\u{0C44}' |
355
+ '\u{0C46}' ..='\u{0C48}' |
356
+ '\u{0C4A}' ..='\u{0C4D}' |
357
+ '\u{0C55}' ..='\u{0C56}' |
358
+ '\u{0C82}' ..='\u{0C83}' |
359
+ '\u{0CBE}' ..='\u{0CC4}' |
360
+ '\u{0CC6}' ..='\u{0CC8}' |
361
+ '\u{0CCA}' ..='\u{0CCD}' |
362
+ '\u{0CD5}' ..='\u{0CD6}' |
363
+ '\u{0D02}' ..='\u{0D03}' |
364
+ '\u{0D3E}' ..='\u{0D43}' |
365
+ '\u{0D46}' ..='\u{0D48}' |
366
+ '\u{0D4A}' ..='\u{0D4D}' |
367
+ '\u{0D57}' |
368
+ '\u{0E31}' |
369
+ '\u{0E34}' ..='\u{0E3A}' |
370
+ '\u{0E47}' ..='\u{0E4E}' |
371
+ '\u{0EB1}' |
372
+ '\u{0EB4}' ..='\u{0EB9}' |
373
+ '\u{0EBB}' ..='\u{0EBC}' |
374
+ '\u{0EC8}' ..='\u{0ECD}' |
375
+ '\u{0F18}' ..='\u{0F19}' |
376
+ '\u{0F35}' |
377
+ '\u{0F37}' |
378
+ '\u{0F39}' |
379
+ '\u{0F3E}' |
380
+ '\u{0F3F}' |
381
+ '\u{0F71}' ..='\u{0F84}' |
382
+ '\u{0F86}' ..='\u{0F8B}' |
383
+ '\u{0F90}' ..='\u{0F95}' |
384
+ '\u{0F97}' |
385
+ '\u{0F99}' ..='\u{0FAD}' |
386
+ '\u{0FB1}' ..='\u{0FB7}' |
387
+ '\u{0FB9}' |
388
+ '\u{20D0}' ..='\u{20DC}' |
389
+ '\u{20E1}' |
390
+ '\u{302A}' ..='\u{302F}' |
391
+ '\u{3099}' |
392
+ '\u{309A}' )
393
+ }
394
+
297
395
/// Prepares a string according to the procedures described in Section 7 of
298
396
/// [ITU-T Recommendation X.520 (2019)](https://www.itu.int/rec/T-REC-X.520-201910-I/en).
299
397
///
@@ -351,7 +449,7 @@ pub fn x520prep(s: &str, case_fold: bool) -> Result<Cow<'_, str>, Error> {
351
449
// "The first code point of a string is prohibited from being a combining character."
352
450
match s. chars ( ) . next ( ) {
353
451
Some ( c) => {
354
- if c . is_mark ( ) {
452
+ if is_combining_char ( c ) {
355
453
return Err ( Error ( ErrorCause :: StartsWithCombiningCharacter ) ) ;
356
454
}
357
455
}
0 commit comments