From 3e3e70d529d8c7d7c4d7bc4fefc9f109393b9245 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:19:43 +0200 Subject: Merging upstream version 1.69.0+dfsg1. Signed-off-by: Daniel Baumann --- vendor/unicode-bidi/.cargo-checksum.json | 2 +- vendor/unicode-bidi/Cargo.toml | 7 +- vendor/unicode-bidi/src/char_data/mod.rs | 18 +- vendor/unicode-bidi/src/char_data/tables.rs | 311 +++++++++-------- vendor/unicode-bidi/src/data_source.rs | 30 ++ vendor/unicode-bidi/src/explicit.rs | 44 ++- vendor/unicode-bidi/src/implicit.rs | 521 +++++++++++++++++++++++----- vendor/unicode-bidi/src/lib.rs | 93 ++++- vendor/unicode-bidi/src/prepare.rs | 102 +++++- 9 files changed, 873 insertions(+), 255 deletions(-) (limited to 'vendor/unicode-bidi') diff --git a/vendor/unicode-bidi/.cargo-checksum.json b/vendor/unicode-bidi/.cargo-checksum.json index 6dc5a203e..ab0bb707a 100644 --- a/vendor/unicode-bidi/.cargo-checksum.json +++ b/vendor/unicode-bidi/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"AUTHORS":"1ff3a7c8519b29544bb28ba9b1e7502df0cb764051fb9a1172e60006aa2b8dcc","COPYRIGHT":"edb20b474f6cbd4f4db066b54a9e0f687d0009d309412a63431189b59b8e2a07","Cargo.toml":"c0862499053fc6c7d7c34bbcc5443d818a6d69c3e0f56a5ec1331a87895aaa1a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"81d3dc6d894a68894d982760b0a907f9dcbb0da179a8063ed9de1d2257518957","src/char_data/mod.rs":"eeef418c98739eed13f993c21cb2ed872b40c31f102d437e5b37cc7a97aeb5de","src/char_data/tables.rs":"ca8f4f579fe2ef81cb39b13ef6ea3c0bc78cdf1c51668a25ccc2447adf1c95e4","src/data_source.rs":"4c7831c47c85eaf0d7412ed3e6baea667ba3b44f87ddffef4e7b76b5bb5b1272","src/deprecated.rs":"3c8b465b827a487df7945cb928e1eae98f9929b71c4d0c99511a470704455a8c","src/explicit.rs":"808aec21bcaa86cb00721b3f61f5f98c3eba40fcc6bb3f8a18739ce6a35b7c1c","src/format_chars.rs":"678399fec3f4bfaf4093f38cfdb8956288313386dc3511dab9fb58164e8dc01b","src/implicit.rs":"167be5386315acefbe8a38918b1850b80beccc7485f759d12bc3f5b2c6870c21","src/level.rs":"9bf4943fe3f6c134640e37acbf1bfcaf8b074739c7625736823bf0bc185e1e0d","src/lib.rs":"671b8b4339f1ddcc262df0a3f774c2874e0b2428269dcecf63a003b7848fee9f","src/prepare.rs":"94b74379faa4d8d8d905ea848292a92ca3d93bef1a428fd92afe262b54912c10"},"package":"099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"} \ No newline at end of file +{"files":{"AUTHORS":"1ff3a7c8519b29544bb28ba9b1e7502df0cb764051fb9a1172e60006aa2b8dcc","COPYRIGHT":"edb20b474f6cbd4f4db066b54a9e0f687d0009d309412a63431189b59b8e2a07","Cargo.toml":"bac3b9c34e93bfab34060c48f493cd82eece9ae99d9b1c98df1d875a8266bfff","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"81d3dc6d894a68894d982760b0a907f9dcbb0da179a8063ed9de1d2257518957","src/char_data/mod.rs":"0622df8ce4b4de60aea7e4787635d3187f79f7a3f9001e3d209f58fd07d03887","src/char_data/tables.rs":"50faf4eef73c831a38b735309ff3415e9f65992a0474ff5c055138f91c91ee16","src/data_source.rs":"36fa0785e51c549c1f72f09040cfe515b848d1b23fb30d469770a6b4b17b49df","src/deprecated.rs":"3c8b465b827a487df7945cb928e1eae98f9929b71c4d0c99511a470704455a8c","src/explicit.rs":"53428d618aef86c6790d195eb9477f09decc396772581427241d34139f886517","src/format_chars.rs":"678399fec3f4bfaf4093f38cfdb8956288313386dc3511dab9fb58164e8dc01b","src/implicit.rs":"454f35f0803ae7d1d7fdb2d1fb0cd675dd83c5dd92a8d31445847a5a2a16b6bf","src/level.rs":"9bf4943fe3f6c134640e37acbf1bfcaf8b074739c7625736823bf0bc185e1e0d","src/lib.rs":"33830f404ebdf3a0561c415ed3f0e5d8739e749db27f21f9e2644031afa511fa","src/prepare.rs":"7aa46ba8d0448a34be704cc3a1f49bc52ddfce62fa66af65618c2ac94cb88a4e"},"package":"d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58"} \ No newline at end of file diff --git a/vendor/unicode-bidi/Cargo.toml b/vendor/unicode-bidi/Cargo.toml index 9a8ca4a32..02ea8fabf 100644 --- a/vendor/unicode-bidi/Cargo.toml +++ b/vendor/unicode-bidi/Cargo.toml @@ -12,7 +12,7 @@ [package] edition = "2018" name = "unicode-bidi" -version = "0.3.8" +version = "0.3.10" authors = ["The Servo Project Developers"] exclude = [ "benches/**", @@ -42,6 +42,11 @@ repository = "https://github.com/servo/unicode-bidi" [lib] name = "unicode_bidi" +[[test]] +name = "conformance_tests" +path = "tests/conformance_tests.rs" +required-features = ["hardcoded-data"] + [dependencies.flame] version = "0.2" optional = true diff --git a/vendor/unicode-bidi/src/char_data/mod.rs b/vendor/unicode-bidi/src/char_data/mod.rs index a8b452788..4edf5b8f4 100644 --- a/vendor/unicode-bidi/src/char_data/mod.rs +++ b/vendor/unicode-bidi/src/char_data/mod.rs @@ -19,10 +19,10 @@ use core::cmp::Ordering::{Equal, Greater, Less}; #[cfg(feature = "hardcoded-data")] use self::tables::bidi_class_table; +use crate::data_source::BidiMatchedOpeningBracket; use crate::BidiClass::*; #[cfg(feature = "hardcoded-data")] use crate::BidiDataSource; - /// Hardcoded Bidi data that ships with the unicode-bidi crate. /// /// This can be enabled with the default `hardcoded-data` Cargo feature. @@ -42,6 +42,22 @@ pub fn bidi_class(c: char) -> BidiClass { bsearch_range_value_table(c, bidi_class_table) } +/// If this character is a bracket according to BidiBrackets.txt, +/// return the corresponding *normalized* *opening bracket* of the pair, +/// and whether or not it itself is an opening bracket. +pub(crate) fn bidi_matched_opening_bracket(c: char) -> Option { + for pair in self::tables::bidi_pairs_table { + if pair.0 == c || pair.1 == c { + let skeleton = pair.2.unwrap_or(pair.0); + return Some(BidiMatchedOpeningBracket { + opening: skeleton, + is_open: pair.0 == c, + }); + } + } + None +} + pub fn is_rtl(bidi_class: BidiClass) -> bool { match bidi_class { RLE | RLO | RLI => true, diff --git a/vendor/unicode-bidi/src/char_data/tables.rs b/vendor/unicode-bidi/src/char_data/tables.rs index 502ae9e90..ecdcf496d 100644 --- a/vendor/unicode-bidi/src/char_data/tables.rs +++ b/vendor/unicode-bidi/src/char_data/tables.rs @@ -5,7 +5,7 @@ #![cfg_attr(rustfmt, rustfmt_skip)] /// The [Unicode version](http://www.unicode.org/versions/) of data -pub const UNICODE_VERSION: (u64, u64, u64) = (14, 0, 0); +pub const UNICODE_VERSION: (u64, u64, u64) = (15, 0, 0); #[allow(non_camel_case_types)] #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -140,7 +140,7 @@ pub const bidi_class_table: &'static [(char, char, BidiClass)] = &[ '\u{cb9}', L), ('\u{cbc}', '\u{cbc}', NSM), ('\u{cbd}', '\u{cc4}', L), ('\u{cc6}', '\u{cc8}', L), ('\u{cca}', '\u{ccb}', L), ('\u{ccc}', '\u{ccd}', NSM), ('\u{cd5}', '\u{cd6}', L), ('\u{cdd}', '\u{cde}', L), ('\u{ce0}', '\u{ce1}', L), ('\u{ce2}', '\u{ce3}', NSM), ('\u{ce6}', - '\u{cef}', L), ('\u{cf1}', '\u{cf2}', L), ('\u{d00}', '\u{d01}', NSM), ('\u{d02}', '\u{d0c}', + '\u{cef}', L), ('\u{cf1}', '\u{cf3}', L), ('\u{d00}', '\u{d01}', NSM), ('\u{d02}', '\u{d0c}', L), ('\u{d0e}', '\u{d10}', L), ('\u{d12}', '\u{d3a}', L), ('\u{d3b}', '\u{d3c}', NSM), ('\u{d3d}', '\u{d40}', L), ('\u{d41}', '\u{d44}', NSM), ('\u{d46}', '\u{d48}', L), ('\u{d4a}', '\u{d4c}', L), ('\u{d4d}', '\u{d4d}', NSM), ('\u{d4e}', '\u{d4f}', L), ('\u{d54}', '\u{d61}', @@ -154,7 +154,7 @@ pub const bidi_class_table: &'static [(char, char, BidiClass)] = &[ ('\u{e4f}', '\u{e5b}', L), ('\u{e81}', '\u{e82}', L), ('\u{e84}', '\u{e84}', L), ('\u{e86}', '\u{e8a}', L), ('\u{e8c}', '\u{ea3}', L), ('\u{ea5}', '\u{ea5}', L), ('\u{ea7}', '\u{eb0}', L), ('\u{eb1}', '\u{eb1}', NSM), ('\u{eb2}', '\u{eb3}', L), ('\u{eb4}', '\u{ebc}', NSM), ('\u{ebd}', - '\u{ebd}', L), ('\u{ec0}', '\u{ec4}', L), ('\u{ec6}', '\u{ec6}', L), ('\u{ec8}', '\u{ecd}', + '\u{ebd}', L), ('\u{ec0}', '\u{ec4}', L), ('\u{ec6}', '\u{ec6}', L), ('\u{ec8}', '\u{ece}', NSM), ('\u{ed0}', '\u{ed9}', L), ('\u{edc}', '\u{edf}', L), ('\u{f00}', '\u{f17}', L), ('\u{f18}', '\u{f19}', NSM), ('\u{f1a}', '\u{f34}', L), ('\u{f35}', '\u{f35}', NSM), ('\u{f36}', '\u{f36}', L), ('\u{f37}', '\u{f37}', NSM), ('\u{f38}', '\u{f38}', L), ('\u{f39}', '\u{f39}', @@ -361,96 +361,102 @@ pub const bidi_class_table: &'static [(char, char, BidiClass)] = &[ '\u{10cff}', R), ('\u{10d00}', '\u{10d23}', AL), ('\u{10d24}', '\u{10d27}', NSM), ('\u{10d28}', '\u{10d2f}', R), ('\u{10d30}', '\u{10d39}', AN), ('\u{10d3a}', '\u{10e5f}', R), ('\u{10e60}', '\u{10e7e}', AN), ('\u{10e7f}', '\u{10eaa}', R), ('\u{10eab}', '\u{10eac}', NSM), ('\u{10ead}', - '\u{10f2f}', R), ('\u{10f30}', '\u{10f45}', AL), ('\u{10f46}', '\u{10f50}', NSM), ('\u{10f51}', - '\u{10f59}', AL), ('\u{10f5a}', '\u{10f81}', R), ('\u{10f82}', '\u{10f85}', NSM), ('\u{10f86}', - '\u{10fff}', R), ('\u{11000}', '\u{11000}', L), ('\u{11001}', '\u{11001}', NSM), ('\u{11002}', - '\u{11037}', L), ('\u{11038}', '\u{11046}', NSM), ('\u{11047}', '\u{1104d}', L), ('\u{11052}', - '\u{11065}', ON), ('\u{11066}', '\u{1106f}', L), ('\u{11070}', '\u{11070}', NSM), ('\u{11071}', - '\u{11072}', L), ('\u{11073}', '\u{11074}', NSM), ('\u{11075}', '\u{11075}', L), ('\u{1107f}', - '\u{11081}', NSM), ('\u{11082}', '\u{110b2}', L), ('\u{110b3}', '\u{110b6}', NSM), ('\u{110b7}', - '\u{110b8}', L), ('\u{110b9}', '\u{110ba}', NSM), ('\u{110bb}', '\u{110c1}', L), ('\u{110c2}', - '\u{110c2}', NSM), ('\u{110cd}', '\u{110cd}', L), ('\u{110d0}', '\u{110e8}', L), ('\u{110f0}', - '\u{110f9}', L), ('\u{11100}', '\u{11102}', NSM), ('\u{11103}', '\u{11126}', L), ('\u{11127}', - '\u{1112b}', NSM), ('\u{1112c}', '\u{1112c}', L), ('\u{1112d}', '\u{11134}', NSM), ('\u{11136}', - '\u{11147}', L), ('\u{11150}', '\u{11172}', L), ('\u{11173}', '\u{11173}', NSM), ('\u{11174}', - '\u{11176}', L), ('\u{11180}', '\u{11181}', NSM), ('\u{11182}', '\u{111b5}', L), ('\u{111b6}', - '\u{111be}', NSM), ('\u{111bf}', '\u{111c8}', L), ('\u{111c9}', '\u{111cc}', NSM), ('\u{111cd}', - '\u{111ce}', L), ('\u{111cf}', '\u{111cf}', NSM), ('\u{111d0}', '\u{111df}', L), ('\u{111e1}', - '\u{111f4}', L), ('\u{11200}', '\u{11211}', L), ('\u{11213}', '\u{1122e}', L), ('\u{1122f}', - '\u{11231}', NSM), ('\u{11232}', '\u{11233}', L), ('\u{11234}', '\u{11234}', NSM), ('\u{11235}', - '\u{11235}', L), ('\u{11236}', '\u{11237}', NSM), ('\u{11238}', '\u{1123d}', L), ('\u{1123e}', - '\u{1123e}', NSM), ('\u{11280}', '\u{11286}', L), ('\u{11288}', '\u{11288}', L), ('\u{1128a}', - '\u{1128d}', L), ('\u{1128f}', '\u{1129d}', L), ('\u{1129f}', '\u{112a9}', L), ('\u{112b0}', - '\u{112de}', L), ('\u{112df}', '\u{112df}', NSM), ('\u{112e0}', '\u{112e2}', L), ('\u{112e3}', - '\u{112ea}', NSM), ('\u{112f0}', '\u{112f9}', L), ('\u{11300}', '\u{11301}', NSM), ('\u{11302}', - '\u{11303}', L), ('\u{11305}', '\u{1130c}', L), ('\u{1130f}', '\u{11310}', L), ('\u{11313}', - '\u{11328}', L), ('\u{1132a}', '\u{11330}', L), ('\u{11332}', '\u{11333}', L), ('\u{11335}', - '\u{11339}', L), ('\u{1133b}', '\u{1133c}', NSM), ('\u{1133d}', '\u{1133f}', L), ('\u{11340}', - '\u{11340}', NSM), ('\u{11341}', '\u{11344}', L), ('\u{11347}', '\u{11348}', L), ('\u{1134b}', - '\u{1134d}', L), ('\u{11350}', '\u{11350}', L), ('\u{11357}', '\u{11357}', L), ('\u{1135d}', - '\u{11363}', L), ('\u{11366}', '\u{1136c}', NSM), ('\u{11370}', '\u{11374}', NSM), ('\u{11400}', - '\u{11437}', L), ('\u{11438}', '\u{1143f}', NSM), ('\u{11440}', '\u{11441}', L), ('\u{11442}', - '\u{11444}', NSM), ('\u{11445}', '\u{11445}', L), ('\u{11446}', '\u{11446}', NSM), ('\u{11447}', - '\u{1145b}', L), ('\u{1145d}', '\u{1145d}', L), ('\u{1145e}', '\u{1145e}', NSM), ('\u{1145f}', - '\u{11461}', L), ('\u{11480}', '\u{114b2}', L), ('\u{114b3}', '\u{114b8}', NSM), ('\u{114b9}', - '\u{114b9}', L), ('\u{114ba}', '\u{114ba}', NSM), ('\u{114bb}', '\u{114be}', L), ('\u{114bf}', - '\u{114c0}', NSM), ('\u{114c1}', '\u{114c1}', L), ('\u{114c2}', '\u{114c3}', NSM), ('\u{114c4}', - '\u{114c7}', L), ('\u{114d0}', '\u{114d9}', L), ('\u{11580}', '\u{115b1}', L), ('\u{115b2}', - '\u{115b5}', NSM), ('\u{115b8}', '\u{115bb}', L), ('\u{115bc}', '\u{115bd}', NSM), ('\u{115be}', - '\u{115be}', L), ('\u{115bf}', '\u{115c0}', NSM), ('\u{115c1}', '\u{115db}', L), ('\u{115dc}', - '\u{115dd}', NSM), ('\u{11600}', '\u{11632}', L), ('\u{11633}', '\u{1163a}', NSM), ('\u{1163b}', - '\u{1163c}', L), ('\u{1163d}', '\u{1163d}', NSM), ('\u{1163e}', '\u{1163e}', L), ('\u{1163f}', - '\u{11640}', NSM), ('\u{11641}', '\u{11644}', L), ('\u{11650}', '\u{11659}', L), ('\u{11660}', - '\u{1166c}', ON), ('\u{11680}', '\u{116aa}', L), ('\u{116ab}', '\u{116ab}', NSM), ('\u{116ac}', - '\u{116ac}', L), ('\u{116ad}', '\u{116ad}', NSM), ('\u{116ae}', '\u{116af}', L), ('\u{116b0}', - '\u{116b5}', NSM), ('\u{116b6}', '\u{116b6}', L), ('\u{116b7}', '\u{116b7}', NSM), ('\u{116b8}', - '\u{116b9}', L), ('\u{116c0}', '\u{116c9}', L), ('\u{11700}', '\u{1171a}', L), ('\u{1171d}', - '\u{1171f}', NSM), ('\u{11720}', '\u{11721}', L), ('\u{11722}', '\u{11725}', NSM), ('\u{11726}', - '\u{11726}', L), ('\u{11727}', '\u{1172b}', NSM), ('\u{11730}', '\u{11746}', L), ('\u{11800}', - '\u{1182e}', L), ('\u{1182f}', '\u{11837}', NSM), ('\u{11838}', '\u{11838}', L), ('\u{11839}', - '\u{1183a}', NSM), ('\u{1183b}', '\u{1183b}', L), ('\u{118a0}', '\u{118f2}', L), ('\u{118ff}', - '\u{11906}', L), ('\u{11909}', '\u{11909}', L), ('\u{1190c}', '\u{11913}', L), ('\u{11915}', - '\u{11916}', L), ('\u{11918}', '\u{11935}', L), ('\u{11937}', '\u{11938}', L), ('\u{1193b}', - '\u{1193c}', NSM), ('\u{1193d}', '\u{1193d}', L), ('\u{1193e}', '\u{1193e}', NSM), ('\u{1193f}', - '\u{11942}', L), ('\u{11943}', '\u{11943}', NSM), ('\u{11944}', '\u{11946}', L), ('\u{11950}', - '\u{11959}', L), ('\u{119a0}', '\u{119a7}', L), ('\u{119aa}', '\u{119d3}', L), ('\u{119d4}', - '\u{119d7}', NSM), ('\u{119da}', '\u{119db}', NSM), ('\u{119dc}', '\u{119df}', L), ('\u{119e0}', - '\u{119e0}', NSM), ('\u{119e1}', '\u{119e4}', L), ('\u{11a00}', '\u{11a00}', L), ('\u{11a01}', - '\u{11a06}', NSM), ('\u{11a07}', '\u{11a08}', L), ('\u{11a09}', '\u{11a0a}', NSM), ('\u{11a0b}', - '\u{11a32}', L), ('\u{11a33}', '\u{11a38}', NSM), ('\u{11a39}', '\u{11a3a}', L), ('\u{11a3b}', - '\u{11a3e}', NSM), ('\u{11a3f}', '\u{11a46}', L), ('\u{11a47}', '\u{11a47}', NSM), ('\u{11a50}', - '\u{11a50}', L), ('\u{11a51}', '\u{11a56}', NSM), ('\u{11a57}', '\u{11a58}', L), ('\u{11a59}', - '\u{11a5b}', NSM), ('\u{11a5c}', '\u{11a89}', L), ('\u{11a8a}', '\u{11a96}', NSM), ('\u{11a97}', - '\u{11a97}', L), ('\u{11a98}', '\u{11a99}', NSM), ('\u{11a9a}', '\u{11aa2}', L), ('\u{11ab0}', - '\u{11af8}', L), ('\u{11c00}', '\u{11c08}', L), ('\u{11c0a}', '\u{11c2f}', L), ('\u{11c30}', - '\u{11c36}', NSM), ('\u{11c38}', '\u{11c3d}', NSM), ('\u{11c3e}', '\u{11c45}', L), ('\u{11c50}', - '\u{11c6c}', L), ('\u{11c70}', '\u{11c8f}', L), ('\u{11c92}', '\u{11ca7}', NSM), ('\u{11ca9}', - '\u{11ca9}', L), ('\u{11caa}', '\u{11cb0}', NSM), ('\u{11cb1}', '\u{11cb1}', L), ('\u{11cb2}', - '\u{11cb3}', NSM), ('\u{11cb4}', '\u{11cb4}', L), ('\u{11cb5}', '\u{11cb6}', NSM), ('\u{11d00}', - '\u{11d06}', L), ('\u{11d08}', '\u{11d09}', L), ('\u{11d0b}', '\u{11d30}', L), ('\u{11d31}', - '\u{11d36}', NSM), ('\u{11d3a}', '\u{11d3a}', NSM), ('\u{11d3c}', '\u{11d3d}', NSM), - ('\u{11d3f}', '\u{11d45}', NSM), ('\u{11d46}', '\u{11d46}', L), ('\u{11d47}', '\u{11d47}', NSM), - ('\u{11d50}', '\u{11d59}', L), ('\u{11d60}', '\u{11d65}', L), ('\u{11d67}', '\u{11d68}', L), - ('\u{11d6a}', '\u{11d8e}', L), ('\u{11d90}', '\u{11d91}', NSM), ('\u{11d93}', '\u{11d94}', L), - ('\u{11d95}', '\u{11d95}', NSM), ('\u{11d96}', '\u{11d96}', L), ('\u{11d97}', '\u{11d97}', NSM), - ('\u{11d98}', '\u{11d98}', L), ('\u{11da0}', '\u{11da9}', L), ('\u{11ee0}', '\u{11ef2}', L), - ('\u{11ef3}', '\u{11ef4}', NSM), ('\u{11ef5}', '\u{11ef8}', L), ('\u{11fb0}', '\u{11fb0}', L), - ('\u{11fc0}', '\u{11fd4}', L), ('\u{11fd5}', '\u{11fdc}', ON), ('\u{11fdd}', '\u{11fe0}', ET), - ('\u{11fe1}', '\u{11ff1}', ON), ('\u{11fff}', '\u{12399}', L), ('\u{12400}', '\u{1246e}', L), - ('\u{12470}', '\u{12474}', L), ('\u{12480}', '\u{12543}', L), ('\u{12f90}', '\u{12ff2}', L), - ('\u{13000}', '\u{1342e}', L), ('\u{13430}', '\u{13438}', L), ('\u{14400}', '\u{14646}', L), - ('\u{16800}', '\u{16a38}', L), ('\u{16a40}', '\u{16a5e}', L), ('\u{16a60}', '\u{16a69}', L), - ('\u{16a6e}', '\u{16abe}', L), ('\u{16ac0}', '\u{16ac9}', L), ('\u{16ad0}', '\u{16aed}', L), - ('\u{16af0}', '\u{16af4}', NSM), ('\u{16af5}', '\u{16af5}', L), ('\u{16b00}', '\u{16b2f}', L), - ('\u{16b30}', '\u{16b36}', NSM), ('\u{16b37}', '\u{16b45}', L), ('\u{16b50}', '\u{16b59}', L), - ('\u{16b5b}', '\u{16b61}', L), ('\u{16b63}', '\u{16b77}', L), ('\u{16b7d}', '\u{16b8f}', L), - ('\u{16e40}', '\u{16e9a}', L), ('\u{16f00}', '\u{16f4a}', L), ('\u{16f4f}', '\u{16f4f}', NSM), - ('\u{16f50}', '\u{16f87}', L), ('\u{16f8f}', '\u{16f92}', NSM), ('\u{16f93}', '\u{16f9f}', L), - ('\u{16fe0}', '\u{16fe1}', L), ('\u{16fe2}', '\u{16fe2}', ON), ('\u{16fe3}', '\u{16fe3}', L), - ('\u{16fe4}', '\u{16fe4}', NSM), ('\u{16ff0}', '\u{16ff1}', L), ('\u{17000}', '\u{187f7}', L), - ('\u{18800}', '\u{18cd5}', L), ('\u{18d00}', '\u{18d08}', L), ('\u{1aff0}', '\u{1aff3}', L), - ('\u{1aff5}', '\u{1affb}', L), ('\u{1affd}', '\u{1affe}', L), ('\u{1b000}', '\u{1b122}', L), - ('\u{1b150}', '\u{1b152}', L), ('\u{1b164}', '\u{1b167}', L), ('\u{1b170}', '\u{1b2fb}', L), + '\u{10efc}', R), ('\u{10efd}', '\u{10eff}', NSM), ('\u{10f00}', '\u{10f2f}', R), ('\u{10f30}', + '\u{10f45}', AL), ('\u{10f46}', '\u{10f50}', NSM), ('\u{10f51}', '\u{10f59}', AL), ('\u{10f5a}', + '\u{10f81}', R), ('\u{10f82}', '\u{10f85}', NSM), ('\u{10f86}', '\u{10fff}', R), ('\u{11000}', + '\u{11000}', L), ('\u{11001}', '\u{11001}', NSM), ('\u{11002}', '\u{11037}', L), ('\u{11038}', + '\u{11046}', NSM), ('\u{11047}', '\u{1104d}', L), ('\u{11052}', '\u{11065}', ON), ('\u{11066}', + '\u{1106f}', L), ('\u{11070}', '\u{11070}', NSM), ('\u{11071}', '\u{11072}', L), ('\u{11073}', + '\u{11074}', NSM), ('\u{11075}', '\u{11075}', L), ('\u{1107f}', '\u{11081}', NSM), ('\u{11082}', + '\u{110b2}', L), ('\u{110b3}', '\u{110b6}', NSM), ('\u{110b7}', '\u{110b8}', L), ('\u{110b9}', + '\u{110ba}', NSM), ('\u{110bb}', '\u{110c1}', L), ('\u{110c2}', '\u{110c2}', NSM), ('\u{110cd}', + '\u{110cd}', L), ('\u{110d0}', '\u{110e8}', L), ('\u{110f0}', '\u{110f9}', L), ('\u{11100}', + '\u{11102}', NSM), ('\u{11103}', '\u{11126}', L), ('\u{11127}', '\u{1112b}', NSM), ('\u{1112c}', + '\u{1112c}', L), ('\u{1112d}', '\u{11134}', NSM), ('\u{11136}', '\u{11147}', L), ('\u{11150}', + '\u{11172}', L), ('\u{11173}', '\u{11173}', NSM), ('\u{11174}', '\u{11176}', L), ('\u{11180}', + '\u{11181}', NSM), ('\u{11182}', '\u{111b5}', L), ('\u{111b6}', '\u{111be}', NSM), ('\u{111bf}', + '\u{111c8}', L), ('\u{111c9}', '\u{111cc}', NSM), ('\u{111cd}', '\u{111ce}', L), ('\u{111cf}', + '\u{111cf}', NSM), ('\u{111d0}', '\u{111df}', L), ('\u{111e1}', '\u{111f4}', L), ('\u{11200}', + '\u{11211}', L), ('\u{11213}', '\u{1122e}', L), ('\u{1122f}', '\u{11231}', NSM), ('\u{11232}', + '\u{11233}', L), ('\u{11234}', '\u{11234}', NSM), ('\u{11235}', '\u{11235}', L), ('\u{11236}', + '\u{11237}', NSM), ('\u{11238}', '\u{1123d}', L), ('\u{1123e}', '\u{1123e}', NSM), ('\u{1123f}', + '\u{11240}', L), ('\u{11241}', '\u{11241}', NSM), ('\u{11280}', '\u{11286}', L), ('\u{11288}', + '\u{11288}', L), ('\u{1128a}', '\u{1128d}', L), ('\u{1128f}', '\u{1129d}', L), ('\u{1129f}', + '\u{112a9}', L), ('\u{112b0}', '\u{112de}', L), ('\u{112df}', '\u{112df}', NSM), ('\u{112e0}', + '\u{112e2}', L), ('\u{112e3}', '\u{112ea}', NSM), ('\u{112f0}', '\u{112f9}', L), ('\u{11300}', + '\u{11301}', NSM), ('\u{11302}', '\u{11303}', L), ('\u{11305}', '\u{1130c}', L), ('\u{1130f}', + '\u{11310}', L), ('\u{11313}', '\u{11328}', L), ('\u{1132a}', '\u{11330}', L), ('\u{11332}', + '\u{11333}', L), ('\u{11335}', '\u{11339}', L), ('\u{1133b}', '\u{1133c}', NSM), ('\u{1133d}', + '\u{1133f}', L), ('\u{11340}', '\u{11340}', NSM), ('\u{11341}', '\u{11344}', L), ('\u{11347}', + '\u{11348}', L), ('\u{1134b}', '\u{1134d}', L), ('\u{11350}', '\u{11350}', L), ('\u{11357}', + '\u{11357}', L), ('\u{1135d}', '\u{11363}', L), ('\u{11366}', '\u{1136c}', NSM), ('\u{11370}', + '\u{11374}', NSM), ('\u{11400}', '\u{11437}', L), ('\u{11438}', '\u{1143f}', NSM), ('\u{11440}', + '\u{11441}', L), ('\u{11442}', '\u{11444}', NSM), ('\u{11445}', '\u{11445}', L), ('\u{11446}', + '\u{11446}', NSM), ('\u{11447}', '\u{1145b}', L), ('\u{1145d}', '\u{1145d}', L), ('\u{1145e}', + '\u{1145e}', NSM), ('\u{1145f}', '\u{11461}', L), ('\u{11480}', '\u{114b2}', L), ('\u{114b3}', + '\u{114b8}', NSM), ('\u{114b9}', '\u{114b9}', L), ('\u{114ba}', '\u{114ba}', NSM), ('\u{114bb}', + '\u{114be}', L), ('\u{114bf}', '\u{114c0}', NSM), ('\u{114c1}', '\u{114c1}', L), ('\u{114c2}', + '\u{114c3}', NSM), ('\u{114c4}', '\u{114c7}', L), ('\u{114d0}', '\u{114d9}', L), ('\u{11580}', + '\u{115b1}', L), ('\u{115b2}', '\u{115b5}', NSM), ('\u{115b8}', '\u{115bb}', L), ('\u{115bc}', + '\u{115bd}', NSM), ('\u{115be}', '\u{115be}', L), ('\u{115bf}', '\u{115c0}', NSM), ('\u{115c1}', + '\u{115db}', L), ('\u{115dc}', '\u{115dd}', NSM), ('\u{11600}', '\u{11632}', L), ('\u{11633}', + '\u{1163a}', NSM), ('\u{1163b}', '\u{1163c}', L), ('\u{1163d}', '\u{1163d}', NSM), ('\u{1163e}', + '\u{1163e}', L), ('\u{1163f}', '\u{11640}', NSM), ('\u{11641}', '\u{11644}', L), ('\u{11650}', + '\u{11659}', L), ('\u{11660}', '\u{1166c}', ON), ('\u{11680}', '\u{116aa}', L), ('\u{116ab}', + '\u{116ab}', NSM), ('\u{116ac}', '\u{116ac}', L), ('\u{116ad}', '\u{116ad}', NSM), ('\u{116ae}', + '\u{116af}', L), ('\u{116b0}', '\u{116b5}', NSM), ('\u{116b6}', '\u{116b6}', L), ('\u{116b7}', + '\u{116b7}', NSM), ('\u{116b8}', '\u{116b9}', L), ('\u{116c0}', '\u{116c9}', L), ('\u{11700}', + '\u{1171a}', L), ('\u{1171d}', '\u{1171f}', NSM), ('\u{11720}', '\u{11721}', L), ('\u{11722}', + '\u{11725}', NSM), ('\u{11726}', '\u{11726}', L), ('\u{11727}', '\u{1172b}', NSM), ('\u{11730}', + '\u{11746}', L), ('\u{11800}', '\u{1182e}', L), ('\u{1182f}', '\u{11837}', NSM), ('\u{11838}', + '\u{11838}', L), ('\u{11839}', '\u{1183a}', NSM), ('\u{1183b}', '\u{1183b}', L), ('\u{118a0}', + '\u{118f2}', L), ('\u{118ff}', '\u{11906}', L), ('\u{11909}', '\u{11909}', L), ('\u{1190c}', + '\u{11913}', L), ('\u{11915}', '\u{11916}', L), ('\u{11918}', '\u{11935}', L), ('\u{11937}', + '\u{11938}', L), ('\u{1193b}', '\u{1193c}', NSM), ('\u{1193d}', '\u{1193d}', L), ('\u{1193e}', + '\u{1193e}', NSM), ('\u{1193f}', '\u{11942}', L), ('\u{11943}', '\u{11943}', NSM), ('\u{11944}', + '\u{11946}', L), ('\u{11950}', '\u{11959}', L), ('\u{119a0}', '\u{119a7}', L), ('\u{119aa}', + '\u{119d3}', L), ('\u{119d4}', '\u{119d7}', NSM), ('\u{119da}', '\u{119db}', NSM), ('\u{119dc}', + '\u{119df}', L), ('\u{119e0}', '\u{119e0}', NSM), ('\u{119e1}', '\u{119e4}', L), ('\u{11a00}', + '\u{11a00}', L), ('\u{11a01}', '\u{11a06}', NSM), ('\u{11a07}', '\u{11a08}', L), ('\u{11a09}', + '\u{11a0a}', NSM), ('\u{11a0b}', '\u{11a32}', L), ('\u{11a33}', '\u{11a38}', NSM), ('\u{11a39}', + '\u{11a3a}', L), ('\u{11a3b}', '\u{11a3e}', NSM), ('\u{11a3f}', '\u{11a46}', L), ('\u{11a47}', + '\u{11a47}', NSM), ('\u{11a50}', '\u{11a50}', L), ('\u{11a51}', '\u{11a56}', NSM), ('\u{11a57}', + '\u{11a58}', L), ('\u{11a59}', '\u{11a5b}', NSM), ('\u{11a5c}', '\u{11a89}', L), ('\u{11a8a}', + '\u{11a96}', NSM), ('\u{11a97}', '\u{11a97}', L), ('\u{11a98}', '\u{11a99}', NSM), ('\u{11a9a}', + '\u{11aa2}', L), ('\u{11ab0}', '\u{11af8}', L), ('\u{11b00}', '\u{11b09}', L), ('\u{11c00}', + '\u{11c08}', L), ('\u{11c0a}', '\u{11c2f}', L), ('\u{11c30}', '\u{11c36}', NSM), ('\u{11c38}', + '\u{11c3d}', NSM), ('\u{11c3e}', '\u{11c45}', L), ('\u{11c50}', '\u{11c6c}', L), ('\u{11c70}', + '\u{11c8f}', L), ('\u{11c92}', '\u{11ca7}', NSM), ('\u{11ca9}', '\u{11ca9}', L), ('\u{11caa}', + '\u{11cb0}', NSM), ('\u{11cb1}', '\u{11cb1}', L), ('\u{11cb2}', '\u{11cb3}', NSM), ('\u{11cb4}', + '\u{11cb4}', L), ('\u{11cb5}', '\u{11cb6}', NSM), ('\u{11d00}', '\u{11d06}', L), ('\u{11d08}', + '\u{11d09}', L), ('\u{11d0b}', '\u{11d30}', L), ('\u{11d31}', '\u{11d36}', NSM), ('\u{11d3a}', + '\u{11d3a}', NSM), ('\u{11d3c}', '\u{11d3d}', NSM), ('\u{11d3f}', '\u{11d45}', NSM), + ('\u{11d46}', '\u{11d46}', L), ('\u{11d47}', '\u{11d47}', NSM), ('\u{11d50}', '\u{11d59}', L), + ('\u{11d60}', '\u{11d65}', L), ('\u{11d67}', '\u{11d68}', L), ('\u{11d6a}', '\u{11d8e}', L), + ('\u{11d90}', '\u{11d91}', NSM), ('\u{11d93}', '\u{11d94}', L), ('\u{11d95}', '\u{11d95}', NSM), + ('\u{11d96}', '\u{11d96}', L), ('\u{11d97}', '\u{11d97}', NSM), ('\u{11d98}', '\u{11d98}', L), + ('\u{11da0}', '\u{11da9}', L), ('\u{11ee0}', '\u{11ef2}', L), ('\u{11ef3}', '\u{11ef4}', NSM), + ('\u{11ef5}', '\u{11ef8}', L), ('\u{11f00}', '\u{11f01}', NSM), ('\u{11f02}', '\u{11f10}', L), + ('\u{11f12}', '\u{11f35}', L), ('\u{11f36}', '\u{11f3a}', NSM), ('\u{11f3e}', '\u{11f3f}', L), + ('\u{11f40}', '\u{11f40}', NSM), ('\u{11f41}', '\u{11f41}', L), ('\u{11f42}', '\u{11f42}', NSM), + ('\u{11f43}', '\u{11f59}', L), ('\u{11fb0}', '\u{11fb0}', L), ('\u{11fc0}', '\u{11fd4}', L), + ('\u{11fd5}', '\u{11fdc}', ON), ('\u{11fdd}', '\u{11fe0}', ET), ('\u{11fe1}', '\u{11ff1}', ON), + ('\u{11fff}', '\u{12399}', L), ('\u{12400}', '\u{1246e}', L), ('\u{12470}', '\u{12474}', L), + ('\u{12480}', '\u{12543}', L), ('\u{12f90}', '\u{12ff2}', L), ('\u{13000}', '\u{1343f}', L), + ('\u{13440}', '\u{13440}', NSM), ('\u{13441}', '\u{13446}', L), ('\u{13447}', '\u{13455}', NSM), + ('\u{14400}', '\u{14646}', L), ('\u{16800}', '\u{16a38}', L), ('\u{16a40}', '\u{16a5e}', L), + ('\u{16a60}', '\u{16a69}', L), ('\u{16a6e}', '\u{16abe}', L), ('\u{16ac0}', '\u{16ac9}', L), + ('\u{16ad0}', '\u{16aed}', L), ('\u{16af0}', '\u{16af4}', NSM), ('\u{16af5}', '\u{16af5}', L), + ('\u{16b00}', '\u{16b2f}', L), ('\u{16b30}', '\u{16b36}', NSM), ('\u{16b37}', '\u{16b45}', L), + ('\u{16b50}', '\u{16b59}', L), ('\u{16b5b}', '\u{16b61}', L), ('\u{16b63}', '\u{16b77}', L), + ('\u{16b7d}', '\u{16b8f}', L), ('\u{16e40}', '\u{16e9a}', L), ('\u{16f00}', '\u{16f4a}', L), + ('\u{16f4f}', '\u{16f4f}', NSM), ('\u{16f50}', '\u{16f87}', L), ('\u{16f8f}', '\u{16f92}', NSM), + ('\u{16f93}', '\u{16f9f}', L), ('\u{16fe0}', '\u{16fe1}', L), ('\u{16fe2}', '\u{16fe2}', ON), + ('\u{16fe3}', '\u{16fe3}', L), ('\u{16fe4}', '\u{16fe4}', NSM), ('\u{16ff0}', '\u{16ff1}', L), + ('\u{17000}', '\u{187f7}', L), ('\u{18800}', '\u{18cd5}', L), ('\u{18d00}', '\u{18d08}', L), + ('\u{1aff0}', '\u{1aff3}', L), ('\u{1aff5}', '\u{1affb}', L), ('\u{1affd}', '\u{1affe}', L), + ('\u{1b000}', '\u{1b122}', L), ('\u{1b132}', '\u{1b132}', L), ('\u{1b150}', '\u{1b152}', L), + ('\u{1b155}', '\u{1b155}', L), ('\u{1b164}', '\u{1b167}', L), ('\u{1b170}', '\u{1b2fb}', L), ('\u{1bc00}', '\u{1bc6a}', L), ('\u{1bc70}', '\u{1bc7c}', L), ('\u{1bc80}', '\u{1bc88}', L), ('\u{1bc90}', '\u{1bc99}', L), ('\u{1bc9c}', '\u{1bc9c}', L), ('\u{1bc9d}', '\u{1bc9e}', NSM), ('\u{1bc9f}', '\u{1bc9f}', L), ('\u{1bca0}', '\u{1bca3}', BN), ('\u{1cf00}', '\u{1cf2d}', NSM), @@ -460,51 +466,78 @@ pub const bidi_class_table: &'static [(char, char, BidiClass)] = &[ ('\u{1d183}', '\u{1d184}', L), ('\u{1d185}', '\u{1d18b}', NSM), ('\u{1d18c}', '\u{1d1a9}', L), ('\u{1d1aa}', '\u{1d1ad}', NSM), ('\u{1d1ae}', '\u{1d1e8}', L), ('\u{1d1e9}', '\u{1d1ea}', ON), ('\u{1d200}', '\u{1d241}', ON), ('\u{1d242}', '\u{1d244}', NSM), ('\u{1d245}', '\u{1d245}', ON), - ('\u{1d2e0}', '\u{1d2f3}', L), ('\u{1d300}', '\u{1d356}', ON), ('\u{1d360}', '\u{1d378}', L), - ('\u{1d400}', '\u{1d454}', L), ('\u{1d456}', '\u{1d49c}', L), ('\u{1d49e}', '\u{1d49f}', L), - ('\u{1d4a2}', '\u{1d4a2}', L), ('\u{1d4a5}', '\u{1d4a6}', L), ('\u{1d4a9}', '\u{1d4ac}', L), - ('\u{1d4ae}', '\u{1d4b9}', L), ('\u{1d4bb}', '\u{1d4bb}', L), ('\u{1d4bd}', '\u{1d4c3}', L), - ('\u{1d4c5}', '\u{1d505}', L), ('\u{1d507}', '\u{1d50a}', L), ('\u{1d50d}', '\u{1d514}', L), - ('\u{1d516}', '\u{1d51c}', L), ('\u{1d51e}', '\u{1d539}', L), ('\u{1d53b}', '\u{1d53e}', L), - ('\u{1d540}', '\u{1d544}', L), ('\u{1d546}', '\u{1d546}', L), ('\u{1d54a}', '\u{1d550}', L), - ('\u{1d552}', '\u{1d6a5}', L), ('\u{1d6a8}', '\u{1d6da}', L), ('\u{1d6db}', '\u{1d6db}', ON), - ('\u{1d6dc}', '\u{1d714}', L), ('\u{1d715}', '\u{1d715}', ON), ('\u{1d716}', '\u{1d74e}', L), - ('\u{1d74f}', '\u{1d74f}', ON), ('\u{1d750}', '\u{1d788}', L), ('\u{1d789}', '\u{1d789}', ON), - ('\u{1d78a}', '\u{1d7c2}', L), ('\u{1d7c3}', '\u{1d7c3}', ON), ('\u{1d7c4}', '\u{1d7cb}', L), - ('\u{1d7ce}', '\u{1d7ff}', EN), ('\u{1d800}', '\u{1d9ff}', L), ('\u{1da00}', '\u{1da36}', NSM), - ('\u{1da37}', '\u{1da3a}', L), ('\u{1da3b}', '\u{1da6c}', NSM), ('\u{1da6d}', '\u{1da74}', L), - ('\u{1da75}', '\u{1da75}', NSM), ('\u{1da76}', '\u{1da83}', L), ('\u{1da84}', '\u{1da84}', NSM), - ('\u{1da85}', '\u{1da8b}', L), ('\u{1da9b}', '\u{1da9f}', NSM), ('\u{1daa1}', '\u{1daaf}', NSM), - ('\u{1df00}', '\u{1df1e}', L), ('\u{1e000}', '\u{1e006}', NSM), ('\u{1e008}', '\u{1e018}', NSM), - ('\u{1e01b}', '\u{1e021}', NSM), ('\u{1e023}', '\u{1e024}', NSM), ('\u{1e026}', '\u{1e02a}', - NSM), ('\u{1e100}', '\u{1e12c}', L), ('\u{1e130}', '\u{1e136}', NSM), ('\u{1e137}', '\u{1e13d}', - L), ('\u{1e140}', '\u{1e149}', L), ('\u{1e14e}', '\u{1e14f}', L), ('\u{1e290}', '\u{1e2ad}', L), - ('\u{1e2ae}', '\u{1e2ae}', NSM), ('\u{1e2c0}', '\u{1e2eb}', L), ('\u{1e2ec}', '\u{1e2ef}', NSM), - ('\u{1e2f0}', '\u{1e2f9}', L), ('\u{1e2ff}', '\u{1e2ff}', ET), ('\u{1e7e0}', '\u{1e7e6}', L), - ('\u{1e7e8}', '\u{1e7eb}', L), ('\u{1e7ed}', '\u{1e7ee}', L), ('\u{1e7f0}', '\u{1e7fe}', L), - ('\u{1e800}', '\u{1e8cf}', R), ('\u{1e8d0}', '\u{1e8d6}', NSM), ('\u{1e8d7}', '\u{1e943}', R), - ('\u{1e944}', '\u{1e94a}', NSM), ('\u{1e94b}', '\u{1ec70}', R), ('\u{1ec71}', '\u{1ecb4}', AL), - ('\u{1ecb5}', '\u{1ed00}', R), ('\u{1ed01}', '\u{1ed3d}', AL), ('\u{1ed3e}', '\u{1edff}', R), - ('\u{1ee00}', '\u{1eeef}', AL), ('\u{1eef0}', '\u{1eef1}', ON), ('\u{1eef2}', '\u{1eeff}', AL), - ('\u{1ef00}', '\u{1efff}', R), ('\u{1f000}', '\u{1f02b}', ON), ('\u{1f030}', '\u{1f093}', ON), - ('\u{1f0a0}', '\u{1f0ae}', ON), ('\u{1f0b1}', '\u{1f0bf}', ON), ('\u{1f0c1}', '\u{1f0cf}', ON), - ('\u{1f0d1}', '\u{1f0f5}', ON), ('\u{1f100}', '\u{1f10a}', EN), ('\u{1f10b}', '\u{1f10f}', ON), - ('\u{1f110}', '\u{1f12e}', L), ('\u{1f12f}', '\u{1f12f}', ON), ('\u{1f130}', '\u{1f169}', L), - ('\u{1f16a}', '\u{1f16f}', ON), ('\u{1f170}', '\u{1f1ac}', L), ('\u{1f1ad}', '\u{1f1ad}', ON), - ('\u{1f1e6}', '\u{1f202}', L), ('\u{1f210}', '\u{1f23b}', L), ('\u{1f240}', '\u{1f248}', L), - ('\u{1f250}', '\u{1f251}', L), ('\u{1f260}', '\u{1f265}', ON), ('\u{1f300}', '\u{1f6d7}', ON), - ('\u{1f6dd}', '\u{1f6ec}', ON), ('\u{1f6f0}', '\u{1f6fc}', ON), ('\u{1f700}', '\u{1f773}', ON), - ('\u{1f780}', '\u{1f7d8}', ON), ('\u{1f7e0}', '\u{1f7eb}', ON), ('\u{1f7f0}', '\u{1f7f0}', ON), - ('\u{1f800}', '\u{1f80b}', ON), ('\u{1f810}', '\u{1f847}', ON), ('\u{1f850}', '\u{1f859}', ON), - ('\u{1f860}', '\u{1f887}', ON), ('\u{1f890}', '\u{1f8ad}', ON), ('\u{1f8b0}', '\u{1f8b1}', ON), - ('\u{1f900}', '\u{1fa53}', ON), ('\u{1fa60}', '\u{1fa6d}', ON), ('\u{1fa70}', '\u{1fa74}', ON), - ('\u{1fa78}', '\u{1fa7c}', ON), ('\u{1fa80}', '\u{1fa86}', ON), ('\u{1fa90}', '\u{1faac}', ON), - ('\u{1fab0}', '\u{1faba}', ON), ('\u{1fac0}', '\u{1fac5}', ON), ('\u{1fad0}', '\u{1fad9}', ON), - ('\u{1fae0}', '\u{1fae7}', ON), ('\u{1faf0}', '\u{1faf6}', ON), ('\u{1fb00}', '\u{1fb92}', ON), - ('\u{1fb94}', '\u{1fbca}', ON), ('\u{1fbf0}', '\u{1fbf9}', EN), ('\u{20000}', '\u{2a6df}', L), - ('\u{2a700}', '\u{2b738}', L), ('\u{2b740}', '\u{2b81d}', L), ('\u{2b820}', '\u{2cea1}', L), - ('\u{2ceb0}', '\u{2ebe0}', L), ('\u{2f800}', '\u{2fa1d}', L), ('\u{30000}', '\u{3134a}', L), - ('\u{e0001}', '\u{e0001}', BN), ('\u{e0020}', '\u{e007f}', BN), ('\u{e0100}', '\u{e01ef}', NSM), - ('\u{f0000}', '\u{ffffd}', L), ('\u{100000}', '\u{10fffd}', L) + ('\u{1d2c0}', '\u{1d2d3}', L), ('\u{1d2e0}', '\u{1d2f3}', L), ('\u{1d300}', '\u{1d356}', ON), + ('\u{1d360}', '\u{1d378}', L), ('\u{1d400}', '\u{1d454}', L), ('\u{1d456}', '\u{1d49c}', L), + ('\u{1d49e}', '\u{1d49f}', L), ('\u{1d4a2}', '\u{1d4a2}', L), ('\u{1d4a5}', '\u{1d4a6}', L), + ('\u{1d4a9}', '\u{1d4ac}', L), ('\u{1d4ae}', '\u{1d4b9}', L), ('\u{1d4bb}', '\u{1d4bb}', L), + ('\u{1d4bd}', '\u{1d4c3}', L), ('\u{1d4c5}', '\u{1d505}', L), ('\u{1d507}', '\u{1d50a}', L), + ('\u{1d50d}', '\u{1d514}', L), ('\u{1d516}', '\u{1d51c}', L), ('\u{1d51e}', '\u{1d539}', L), + ('\u{1d53b}', '\u{1d53e}', L), ('\u{1d540}', '\u{1d544}', L), ('\u{1d546}', '\u{1d546}', L), + ('\u{1d54a}', '\u{1d550}', L), ('\u{1d552}', '\u{1d6a5}', L), ('\u{1d6a8}', '\u{1d6da}', L), + ('\u{1d6db}', '\u{1d6db}', ON), ('\u{1d6dc}', '\u{1d714}', L), ('\u{1d715}', '\u{1d715}', ON), + ('\u{1d716}', '\u{1d74e}', L), ('\u{1d74f}', '\u{1d74f}', ON), ('\u{1d750}', '\u{1d788}', L), + ('\u{1d789}', '\u{1d789}', ON), ('\u{1d78a}', '\u{1d7c2}', L), ('\u{1d7c3}', '\u{1d7c3}', ON), + ('\u{1d7c4}', '\u{1d7cb}', L), ('\u{1d7ce}', '\u{1d7ff}', EN), ('\u{1d800}', '\u{1d9ff}', L), + ('\u{1da00}', '\u{1da36}', NSM), ('\u{1da37}', '\u{1da3a}', L), ('\u{1da3b}', '\u{1da6c}', NSM), + ('\u{1da6d}', '\u{1da74}', L), ('\u{1da75}', '\u{1da75}', NSM), ('\u{1da76}', '\u{1da83}', L), + ('\u{1da84}', '\u{1da84}', NSM), ('\u{1da85}', '\u{1da8b}', L), ('\u{1da9b}', '\u{1da9f}', NSM), + ('\u{1daa1}', '\u{1daaf}', NSM), ('\u{1df00}', '\u{1df1e}', L), ('\u{1df25}', '\u{1df2a}', L), + ('\u{1e000}', '\u{1e006}', NSM), ('\u{1e008}', '\u{1e018}', NSM), ('\u{1e01b}', '\u{1e021}', + NSM), ('\u{1e023}', '\u{1e024}', NSM), ('\u{1e026}', '\u{1e02a}', NSM), ('\u{1e030}', + '\u{1e06d}', L), ('\u{1e08f}', '\u{1e08f}', NSM), ('\u{1e100}', '\u{1e12c}', L), ('\u{1e130}', + '\u{1e136}', NSM), ('\u{1e137}', '\u{1e13d}', L), ('\u{1e140}', '\u{1e149}', L), ('\u{1e14e}', + '\u{1e14f}', L), ('\u{1e290}', '\u{1e2ad}', L), ('\u{1e2ae}', '\u{1e2ae}', NSM), ('\u{1e2c0}', + '\u{1e2eb}', L), ('\u{1e2ec}', '\u{1e2ef}', NSM), ('\u{1e2f0}', '\u{1e2f9}', L), ('\u{1e2ff}', + '\u{1e2ff}', ET), ('\u{1e4d0}', '\u{1e4eb}', L), ('\u{1e4ec}', '\u{1e4ef}', NSM), ('\u{1e4f0}', + '\u{1e4f9}', L), ('\u{1e7e0}', '\u{1e7e6}', L), ('\u{1e7e8}', '\u{1e7eb}', L), ('\u{1e7ed}', + '\u{1e7ee}', L), ('\u{1e7f0}', '\u{1e7fe}', L), ('\u{1e800}', '\u{1e8cf}', R), ('\u{1e8d0}', + '\u{1e8d6}', NSM), ('\u{1e8d7}', '\u{1e943}', R), ('\u{1e944}', '\u{1e94a}', NSM), ('\u{1e94b}', + '\u{1ec70}', R), ('\u{1ec71}', '\u{1ecb4}', AL), ('\u{1ecb5}', '\u{1ed00}', R), ('\u{1ed01}', + '\u{1ed3d}', AL), ('\u{1ed3e}', '\u{1edff}', R), ('\u{1ee00}', '\u{1eeef}', AL), ('\u{1eef0}', + '\u{1eef1}', ON), ('\u{1eef2}', '\u{1eeff}', AL), ('\u{1ef00}', '\u{1efff}', R), ('\u{1f000}', + '\u{1f02b}', ON), ('\u{1f030}', '\u{1f093}', ON), ('\u{1f0a0}', '\u{1f0ae}', ON), ('\u{1f0b1}', + '\u{1f0bf}', ON), ('\u{1f0c1}', '\u{1f0cf}', ON), ('\u{1f0d1}', '\u{1f0f5}', ON), ('\u{1f100}', + '\u{1f10a}', EN), ('\u{1f10b}', '\u{1f10f}', ON), ('\u{1f110}', '\u{1f12e}', L), ('\u{1f12f}', + '\u{1f12f}', ON), ('\u{1f130}', '\u{1f169}', L), ('\u{1f16a}', '\u{1f16f}', ON), ('\u{1f170}', + '\u{1f1ac}', L), ('\u{1f1ad}', '\u{1f1ad}', ON), ('\u{1f1e6}', '\u{1f202}', L), ('\u{1f210}', + '\u{1f23b}', L), ('\u{1f240}', '\u{1f248}', L), ('\u{1f250}', '\u{1f251}', L), ('\u{1f260}', + '\u{1f265}', ON), ('\u{1f300}', '\u{1f6d7}', ON), ('\u{1f6dc}', '\u{1f6ec}', ON), ('\u{1f6f0}', + '\u{1f6fc}', ON), ('\u{1f700}', '\u{1f776}', ON), ('\u{1f77b}', '\u{1f7d9}', ON), ('\u{1f7e0}', + '\u{1f7eb}', ON), ('\u{1f7f0}', '\u{1f7f0}', ON), ('\u{1f800}', '\u{1f80b}', ON), ('\u{1f810}', + '\u{1f847}', ON), ('\u{1f850}', '\u{1f859}', ON), ('\u{1f860}', '\u{1f887}', ON), ('\u{1f890}', + '\u{1f8ad}', ON), ('\u{1f8b0}', '\u{1f8b1}', ON), ('\u{1f900}', '\u{1fa53}', ON), ('\u{1fa60}', + '\u{1fa6d}', ON), ('\u{1fa70}', '\u{1fa7c}', ON), ('\u{1fa80}', '\u{1fa88}', ON), ('\u{1fa90}', + '\u{1fabd}', ON), ('\u{1fabf}', '\u{1fac5}', ON), ('\u{1face}', '\u{1fadb}', ON), ('\u{1fae0}', + '\u{1fae8}', ON), ('\u{1faf0}', '\u{1faf8}', ON), ('\u{1fb00}', '\u{1fb92}', ON), ('\u{1fb94}', + '\u{1fbca}', ON), ('\u{1fbf0}', '\u{1fbf9}', EN), ('\u{20000}', '\u{2a6df}', L), ('\u{2a700}', + '\u{2b739}', L), ('\u{2b740}', '\u{2b81d}', L), ('\u{2b820}', '\u{2cea1}', L), ('\u{2ceb0}', + '\u{2ebe0}', L), ('\u{2f800}', '\u{2fa1d}', L), ('\u{30000}', '\u{3134a}', L), ('\u{31350}', + '\u{323af}', L), ('\u{e0001}', '\u{e0001}', BN), ('\u{e0020}', '\u{e007f}', BN), ('\u{e0100}', + '\u{e01ef}', NSM), ('\u{f0000}', '\u{ffffd}', L), ('\u{100000}', '\u{10fffd}', L) +]; + +pub const bidi_pairs_table: &'static [(char, char, Option)] = &[ + ('\u{28}', '\u{29}', None), ('\u{5b}', '\u{5d}', None), ('\u{7b}', '\u{7d}', None), ('\u{f3a}', + '\u{f3b}', None), ('\u{f3c}', '\u{f3d}', None), ('\u{169b}', '\u{169c}', None), ('\u{2045}', + '\u{2046}', None), ('\u{207d}', '\u{207e}', None), ('\u{208d}', '\u{208e}', None), ('\u{2308}', + '\u{2309}', None), ('\u{230a}', '\u{230b}', None), ('\u{2329}', '\u{232a}', Some('\u{3008}')), + ('\u{2768}', '\u{2769}', None), ('\u{276a}', '\u{276b}', None), ('\u{276c}', '\u{276d}', None), + ('\u{276e}', '\u{276f}', None), ('\u{2770}', '\u{2771}', None), ('\u{2772}', '\u{2773}', None), + ('\u{2774}', '\u{2775}', None), ('\u{27c5}', '\u{27c6}', None), ('\u{27e6}', '\u{27e7}', None), + ('\u{27e8}', '\u{27e9}', None), ('\u{27ea}', '\u{27eb}', None), ('\u{27ec}', '\u{27ed}', None), + ('\u{27ee}', '\u{27ef}', None), ('\u{2983}', '\u{2984}', None), ('\u{2985}', '\u{2986}', None), + ('\u{2987}', '\u{2988}', None), ('\u{2989}', '\u{298a}', None), ('\u{298b}', '\u{298c}', None), + ('\u{298d}', '\u{2990}', None), ('\u{298f}', '\u{298e}', None), ('\u{2991}', '\u{2992}', None), + ('\u{2993}', '\u{2994}', None), ('\u{2995}', '\u{2996}', None), ('\u{2997}', '\u{2998}', None), + ('\u{29d8}', '\u{29d9}', None), ('\u{29da}', '\u{29db}', None), ('\u{29fc}', '\u{29fd}', None), + ('\u{2e22}', '\u{2e23}', None), ('\u{2e24}', '\u{2e25}', None), ('\u{2e26}', '\u{2e27}', None), + ('\u{2e28}', '\u{2e29}', None), ('\u{2e55}', '\u{2e56}', None), ('\u{2e57}', '\u{2e58}', None), + ('\u{2e59}', '\u{2e5a}', None), ('\u{2e5b}', '\u{2e5c}', None), ('\u{3008}', '\u{3009}', None), + ('\u{300a}', '\u{300b}', None), ('\u{300c}', '\u{300d}', None), ('\u{300e}', '\u{300f}', None), + ('\u{3010}', '\u{3011}', None), ('\u{3014}', '\u{3015}', None), ('\u{3016}', '\u{3017}', None), + ('\u{3018}', '\u{3019}', None), ('\u{301a}', '\u{301b}', None), ('\u{fe59}', '\u{fe5a}', None), + ('\u{fe5b}', '\u{fe5c}', None), ('\u{fe5d}', '\u{fe5e}', None), ('\u{ff08}', '\u{ff09}', None), + ('\u{ff3b}', '\u{ff3d}', None), ('\u{ff5b}', '\u{ff5d}', None), ('\u{ff5f}', '\u{ff60}', None), + ('\u{ff62}', '\u{ff63}', None) ]; diff --git a/vendor/unicode-bidi/src/data_source.rs b/vendor/unicode-bidi/src/data_source.rs index 3958a255e..319ad53b0 100644 --- a/vendor/unicode-bidi/src/data_source.rs +++ b/vendor/unicode-bidi/src/data_source.rs @@ -9,8 +9,38 @@ use crate::BidiClass; +/// This is the return value of [`BidiDataSource::bidi_matched_opening_bracket()`]. +/// +/// It represents the matching *normalized* opening bracket for a given bracket in a bracket pair, +/// and whether or not that bracket is opening. +#[derive(Debug, Copy, Clone)] +pub struct BidiMatchedOpeningBracket { + /// The corresponding opening bracket in this bracket pair, normalized + /// + /// In case of opening brackets, this will be the bracket itself, except for when the bracket + /// is not normalized, in which case it will be the normalized form. + pub opening: char, + /// Whether or not the requested bracket was an opening bracket. True for opening + pub is_open: bool, +} + /// This trait abstracts over a data source that is able to produce the Unicode Bidi class for a given /// character pub trait BidiDataSource { fn bidi_class(&self, c: char) -> BidiClass; + /// If this character is a bracket according to BidiBrackets.txt, + /// return the corresponding *normalized* *opening bracket* of the pair, + /// and whether or not it itself is an opening bracket. + /// + /// This effectively buckets brackets into equivalence classes keyed on the + /// normalized opening bracket. + /// + /// The default implementation will pull in a small amount of hardcoded data, + /// regardless of the `hardcoded-data` feature. This is in part for convenience + /// (since this data is small and changes less often), and in part so that this method can be + /// added without needing a breaking version bump. + /// Override this method in your custom data source to prevent the use of hardcoded data. + fn bidi_matched_opening_bracket(&self, c: char) -> Option { + crate::char_data::bidi_matched_opening_bracket(c) + } } diff --git a/vendor/unicode-bidi/src/explicit.rs b/vendor/unicode-bidi/src/explicit.rs index e9d579fd6..a9b13e89c 100644 --- a/vendor/unicode-bidi/src/explicit.rs +++ b/vendor/unicode-bidi/src/explicit.rs @@ -47,13 +47,17 @@ pub fn compute( RLE | LRE | RLO | LRO | RLI | LRI | FSI => { let last_level = stack.last().level; + // + levels[i] = last_level; + // X5a-X5c: Isolate initiators get the level of the last entry on the stack. let is_isolate = match original_classes[i] { RLI | LRI | FSI => true, _ => false, }; if is_isolate { - levels[i] = last_level; + // Redundant due to "Retaining explicit formatting characters" step. + // levels[i] = last_level; match stack.last().status { OverrideStatus::RTL => processing_classes[i] = R, OverrideStatus::LTR => processing_classes[i] = L, @@ -90,6 +94,13 @@ pub fn compute( } else if overflow_isolate_count == 0 { overflow_embedding_count += 1; } + + if !is_isolate { + // X9 + + // + // (PDF handled below) + processing_classes[i] = BN; + } } // @@ -123,31 +134,34 @@ pub fn compute( // PDF => { if overflow_isolate_count > 0 { - continue; - } - if overflow_embedding_count > 0 { + // do nothing + } else if overflow_embedding_count > 0 { overflow_embedding_count -= 1; - continue; - } - if stack.last().status != OverrideStatus::Isolate && stack.vec.len() >= 2 { + } else if stack.last().status != OverrideStatus::Isolate && stack.vec.len() >= 2 { stack.vec.pop(); } - // The spec doesn't explicitly mention this step, but it is necessary. - // See the reference implementations for comparison. + // levels[i] = stack.last().level; + // X9 part of retaining explicit formatting characters. + processing_classes[i] = BN; } - // Nothing - B | BN => {} + // Nothing. + // BN case moved down to X6, see + B => {} // _ => { let last = stack.last(); levels[i] = last.level; - match last.status { - OverrideStatus::RTL => processing_classes[i] = R, - OverrideStatus::LTR => processing_classes[i] = L, - _ => {} + // This condition is not in the spec, but I am pretty sure that is a spec bug. + // https://www.unicode.org/L2/L2023/23014-amd-to-uax9.pdf + if original_classes[i] != BN { + match last.status { + OverrideStatus::RTL => processing_classes[i] = R, + OverrideStatus::LTR => processing_classes[i] = L, + _ => {} + } } } } diff --git a/vendor/unicode-bidi/src/implicit.rs b/vendor/unicode-bidi/src/implicit.rs index bf37f17e6..294af7cbd 100644 --- a/vendor/unicode-bidi/src/implicit.rs +++ b/vendor/unicode-bidi/src/implicit.rs @@ -14,104 +14,213 @@ use core::cmp::max; use super::char_data::BidiClass::{self, *}; use super::level::Level; -use super::prepare::{not_removed_by_x9, removed_by_x9, IsolatingRunSequence, LevelRun}; +use super::prepare::{not_removed_by_x9, removed_by_x9, IsolatingRunSequence}; +use super::BidiDataSource; /// 3.3.4 Resolving Weak Types /// /// #[cfg_attr(feature = "flame_it", flamer::flame)] -pub fn resolve_weak(sequence: &IsolatingRunSequence, processing_classes: &mut [BidiClass]) { - // FIXME (#8): This function applies steps W1-W6 in a single pass. This can produce - // incorrect results in cases where a "later" rule changes the value of `prev_class` seen - // by an "earlier" rule. We should either split this into separate passes, or preserve - // extra state so each rule can see the correct previous class. - - // FIXME: Also, this could be the cause of increased failure for using longer-UTF-8 chars in - // conformance tests, like BidiTest:69635 (AL ET EN) +pub fn resolve_weak( + text: &str, + sequence: &IsolatingRunSequence, + processing_classes: &mut [BidiClass], +) { + // Note: The spec treats these steps as individual passes that are applied one after the other + // on the entire IsolatingRunSequence at once. We instead collapse it into a single iteration, + // which is straightforward for rules that are based on the state of the current character, but not + // for rules that care about surrounding characters. To deal with them, we retain additional state + // about previous character classes that may have since been changed by later rules. - let mut prev_class = sequence.sos; + // The previous class for the purposes of rule W4/W6, not tracking changes made after or during W4. + let mut prev_class_before_w4 = sequence.sos; + // The previous class for the purposes of rule W5. + let mut prev_class_before_w5 = sequence.sos; + // The previous class for the purposes of rule W1, not tracking changes from any other rules. + let mut prev_class_before_w1 = sequence.sos; let mut last_strong_is_al = false; let mut et_run_indices = Vec::new(); // for W5 + let mut bn_run_indices = Vec::new(); // for W5 + + + for (run_index, level_run) in sequence.runs.iter().enumerate() { + for i in &mut level_run.clone() { + if processing_classes[i] == BN { + // + // Keeps track of bn runs for W5 in case we see an ET. + bn_run_indices.push(i); + // BNs aren't real, skip over them. + continue; + } + + // Store the processing class of all rules before W2/W1. + // Used to keep track of the last strong character for W2. W3 is able to insert new strong + // characters, so we don't want to be misled by it. + let mut w2_processing_class = processing_classes[i]; - // Like sequence.runs.iter().flat_map(Clone::clone), but make indices itself clonable. - fn id(x: LevelRun) -> LevelRun { - x - } - let mut indices = sequence - .runs - .iter() - .cloned() - .flat_map(id as fn(LevelRun) -> LevelRun); - - while let Some(i) = indices.next() { - match processing_classes[i] { // - NSM => { - processing_classes[i] = match prev_class { + // + + if processing_classes[i] == NSM { + processing_classes[i] = match prev_class_before_w1 { RLI | LRI | FSI | PDI => ON, - _ => prev_class, + _ => prev_class_before_w1, }; + // W1 occurs before W2, update this. + w2_processing_class = processing_classes[i]; } - EN => { - if last_strong_is_al { - // W2. If previous strong char was AL, change EN to AN. - processing_classes[i] = AN; - } else { + + prev_class_before_w1 = processing_classes[i]; + + // + // + // + match processing_classes[i] { + EN => { + if last_strong_is_al { + // W2. If previous strong char was AL, change EN to AN. + processing_classes[i] = AN; + } + } + // W3. + AL => processing_classes[i] = R, + _ => {} + } + + // update last_strong_is_al. + match w2_processing_class { + L | R => { + last_strong_is_al = false; + } + AL => { + last_strong_is_al = true; + } + _ => {} + } + + let class_before_w456 = processing_classes[i]; + + // + // + // (separators only) + // (see below for W6 terminator code) + // + match processing_classes[i] { + // + EN => { // W5. If a run of ETs is adjacent to an EN, change the ETs to EN. for j in &et_run_indices { processing_classes[*j] = EN; } et_run_indices.clear(); } - } - // - AL => processing_classes[i] = R, - // - ES | CS => { - let next_class = indices - .clone() - .map(|j| processing_classes[j]) - .find(not_removed_by_x9) - .unwrap_or(sequence.eos); - processing_classes[i] = match (prev_class, processing_classes[i], next_class) { - (EN, ES, EN) | (EN, CS, EN) => EN, - (AN, CS, AN) => AN, - (_, _, _) => ON, + // + // + ES | CS => { + // See https://github.com/servo/unicode-bidi/issues/86 for improving this. + // We want to make sure we check the correct next character by skipping past the rest + // of this one. + if let Some(ch) = text.get(i..).and_then(|s| s.chars().next()) { + let mut next_class = sequence + .iter_forwards_from(i + ch.len_utf8(), run_index) + .map(|j| processing_classes[j]) + // + .find(not_removed_by_x9) + .unwrap_or(sequence.eos); + if next_class == EN && last_strong_is_al { + // Apply W2 to next_class. We know that last_strong_is_al + // has no chance of changing on this character so we can still assume its value + // will be the same by the time we get to it. + next_class = AN; + } + processing_classes[i] = + match (prev_class_before_w4, processing_classes[i], next_class) { + // W4 + (EN, ES, EN) | (EN, CS, EN) => EN, + // W4 + (AN, CS, AN) => AN, + // W6 (separators only) + (_, _, _) => ON, + }; + + // W6 + + // We have to do this before W5 gets its grubby hands on these characters and thinks + // they're part of an ET run. + // We check for ON to ensure that we had hit the W6 branch above, since this `ES | CS` match + // arm handles both W4 and W6. + if processing_classes[i] == ON { + for idx in sequence.iter_backwards_from(i, run_index) { + let class = &mut processing_classes[idx]; + if *class != BN { + break; + } + *class = ON; + } + for idx in sequence.iter_forwards_from(i + ch.len_utf8(), run_index) { + let class = &mut processing_classes[idx]; + if *class != BN { + break; + } + *class = ON; + } + } + } else { + // We're in the middle of a character, copy over work done for previous bytes + // since it's going to be the same answer. + processing_classes[i] = processing_classes[i - 1]; + } } - } - // - ET => { - match prev_class { - EN => processing_classes[i] = EN, - _ => et_run_indices.push(i), // In case this is followed by an EN. + // + ET => { + match prev_class_before_w5 { + EN => processing_classes[i] = EN, + _ => { + // + // If there was a BN run before this, that's now a part of this ET run. + et_run_indices.extend(&bn_run_indices); + + // In case this is followed by an EN. + et_run_indices.push(i); + } + } } + _ => {} } - class => { - if removed_by_x9(class) { - continue; + + // Common loop iteration code + // + + // + // BN runs would have already continued the loop, clear them before we get to the next one. + bn_run_indices.clear(); + + // W6 above only deals with separators, so it doesn't change anything W5 cares about, + // so we still can update this after running that part of W6. + prev_class_before_w5 = processing_classes[i]; + + // (terminators only) + // (see above for W6 separator code) + // + if prev_class_before_w5 != ET { + // W6. If we didn't find an adjacent EN, turn any ETs into ON instead. + for j in &et_run_indices { + processing_classes[*j] = ON; } + et_run_indices.clear(); } - } - prev_class = processing_classes[i]; - match prev_class { - L | R => { - last_strong_is_al = false; - } - AL => { - last_strong_is_al = true; - } - _ => {} - } - if prev_class != ET { - // W6. If we didn't find an adjacent EN, turn any ETs into ON instead. - for j in &et_run_indices { - processing_classes[*j] = ON; - } - et_run_indices.clear(); + // We stashed this before W4/5/6 could get their grubby hands on it, and it's not + // used in the W6 terminator code below so we can update it now. + prev_class_before_w4 = class_before_w456; } } + // Rerun this check in case we ended with a sequence of BNs (i.e., we'd never + // hit the end of the for loop above). + // W6. If we didn't find an adjacent EN, turn any ETs into ON instead. + for j in &et_run_indices { + processing_classes[*j] = ON; + } + et_run_indices.clear(); // W7. If the previous strong char was L, change EN to L. let mut last_strong_is_l = sequence.sos == L; @@ -127,6 +236,8 @@ pub fn resolve_weak(sequence: &IsolatingRunSequence, processing_classes: &mut [B R | AL => { last_strong_is_l = false; } + // + // Already scanning past BN here. _ => {} } } @@ -137,22 +248,172 @@ pub fn resolve_weak(sequence: &IsolatingRunSequence, processing_classes: &mut [B /// /// #[cfg_attr(feature = "flame_it", flamer::flame)] -pub fn resolve_neutral( +pub fn resolve_neutral( + text: &str, + data_source: &D, sequence: &IsolatingRunSequence, levels: &[Level], + original_classes: &[BidiClass], processing_classes: &mut [BidiClass], ) { + // e = embedding direction let e: BidiClass = levels[sequence.runs[0].start].bidi_class(); + let not_e = if e == BidiClass::L { + BidiClass::R + } else { + BidiClass::L + }; + // N0. Process bracket pairs. + + // > Identify the bracket pairs in the current isolating run sequence according to BD16. + // We use processing_classes, not original_classes, due to BD14/BD15 + let bracket_pairs = identify_bracket_pairs(text, data_source, sequence, processing_classes); + + // > For each bracket-pair element in the list of pairs of text positions + // + // Note: Rust ranges are interpreted as [start..end), be careful using `pair` directly + // for indexing as it will include the opening bracket pair but not the closing one. + for pair in bracket_pairs { + #[cfg(feature = "std")] + debug_assert!( + pair.start < processing_classes.len(), + "identify_bracket_pairs returned a range that is out of bounds!" + ); + #[cfg(feature = "std")] + debug_assert!( + pair.end < processing_classes.len(), + "identify_bracket_pairs returned a range that is out of bounds!" + ); + let mut found_e = false; + let mut found_not_e = false; + let mut class_to_set = None; + + let start_len_utf8 = text[pair.start..].chars().next().unwrap().len_utf8(); + // > Inspect the bidirectional types of the characters enclosed within the bracket pair. + // + // `pair` is [start, end) so we will end up processing the opening character but not the closing one. + // + for enclosed_i in sequence.iter_forwards_from(pair.start + start_len_utf8, pair.start_run) { + if enclosed_i >= pair.end { + #[cfg(feature = "std")] + debug_assert!( + enclosed_i == pair.end, + "If we skipped past this, the iterator is broken" + ); + break; + } + let class = processing_classes[enclosed_i]; + if class == e { + found_e = true; + } else if class == not_e { + found_not_e = true; + } else if class == BidiClass::EN || class == BidiClass::AN { + // > Within this scope, bidirectional types EN and AN are treated as R. + if e == BidiClass::L { + found_not_e = true; + } else { + found_e = true; + } + } + + // If we have found a character with the class of the embedding direction + // we can bail early. + if found_e { + break; + } + } + // > If any strong type (either L or R) matching the embedding direction is found + if found_e { + // > .. set the type for both brackets in the pair to match the embedding direction + class_to_set = Some(e); + // > Otherwise, if there is a strong type it must be opposite the embedding direction + } else if found_not_e { + // > Therefore, test for an established context with a preceding strong type by + // > checking backwards before the opening paired bracket + // > until the first strong type (L, R, or sos) is found. + // (see note above about processing_classes and character boundaries) + let mut previous_strong = sequence + .iter_backwards_from(pair.start, pair.start_run) + .map(|i| processing_classes[i]) + .find(|class| { + *class == BidiClass::L + || *class == BidiClass::R + || *class == BidiClass::EN + || *class == BidiClass::AN + }) + .unwrap_or(sequence.sos); + + // > Within this scope, bidirectional types EN and AN are treated as R. + if previous_strong == BidiClass::EN || previous_strong == BidiClass::AN { + previous_strong = BidiClass::R; + } + + // > If the preceding strong type is also opposite the embedding direction, + // > context is established, + // > so set the type for both brackets in the pair to that direction. + // AND + // > Otherwise set the type for both brackets in the pair to the embedding direction. + // > Either way it gets set to previous_strong + // + // Both branches amount to setting the type to the strong type. + class_to_set = Some(previous_strong); + } + + if let Some(class_to_set) = class_to_set { + // Update all processing classes corresponding to the start and end elements, as requested. + // We should include all bytes of the character, not the first one. + let end_len_utf8 = text[pair.end..].chars().next().unwrap().len_utf8(); + for class in &mut processing_classes[pair.start..pair.start + start_len_utf8] { + *class = class_to_set; + } + for class in &mut processing_classes[pair.end..pair.end + end_len_utf8] { + *class = class_to_set; + } + // + for idx in sequence.iter_backwards_from(pair.start, pair.start_run) { + let class = &mut processing_classes[idx]; + if *class != BN { + break; + } + *class = class_to_set; + } + // > Any number of characters that had original bidirectional character type NSM prior to the application of + // > W1 that immediately follow a paired bracket which changed to L or R under N0 should change to match the type of their preceding bracket. + + // This rule deals with sequences of NSMs, so we can just update them all at once, we don't need to worry + // about character boundaries. We do need to be careful to skip the full set of bytes for the parentheses characters. + let nsm_start = pair.start + start_len_utf8; + for idx in sequence.iter_forwards_from(nsm_start, pair.start_run) { + let class = original_classes[idx]; + if class == BidiClass::NSM || processing_classes[idx] == BN { + processing_classes[idx] = class_to_set; + } else { + break; + } + } + let nsm_end = pair.end + end_len_utf8; + for idx in sequence.iter_forwards_from(nsm_end, pair.end_run) { + let class = original_classes[idx]; + if class == BidiClass::NSM || processing_classes[idx] == BN { + processing_classes[idx] = class_to_set; + } else { + break; + } + } + } + // > Otherwise, there are no strong types within the bracket pair + // > Therefore, do not set the type for that bracket pair + } + + // N1 and N2. + // Indices of every byte in this isolating run sequence let mut indices = sequence.runs.iter().flat_map(Clone::clone); let mut prev_class = sequence.sos; - while let Some(mut i) = indices.next() { - // N0. Process bracket pairs. - // TODO - // Process sequences of NI characters. let mut ni_run = Vec::new(); - if is_NI(processing_classes[i]) { + // The BN is for + if is_NI(processing_classes[i]) || processing_classes[i] == BN { // Consume a run of consecutive NI characters. ni_run.push(i); let mut next_class; @@ -160,11 +421,9 @@ pub fn resolve_neutral( match indices.next() { Some(j) => { i = j; - if removed_by_x9(processing_classes[i]) { - continue; - } next_class = processing_classes[j]; - if is_NI(next_class) { + // The BN is for + if is_NI(next_class) || next_class == BN { ni_run.push(i); } else { break; @@ -176,7 +435,6 @@ pub fn resolve_neutral( } }; } - // N1-N2. // // @@ -203,6 +461,105 @@ pub fn resolve_neutral( } } +struct BracketPair { + /// The text-relative index of the opening bracket. + start: usize, + /// The text-relative index of the closing bracket. + end: usize, + /// The index of the run (in the run sequence) that the opening bracket is in. + start_run: usize, + /// The index of the run (in the run sequence) that the closing bracket is in. + end_run: usize, +} +/// 3.1.3 Identifying Bracket Pairs +/// +/// Returns all paired brackets in the source, as indices into the +/// text source. +/// +/// +fn identify_bracket_pairs( + text: &str, + data_source: &D, + run_sequence: &IsolatingRunSequence, + original_classes: &[BidiClass], +) -> Vec { + let mut ret = vec![]; + let mut stack = vec![]; + + for (run_index, level_run) in run_sequence.runs.iter().enumerate() { + let slice = if let Some(slice) = text.get(level_run.clone()) { + slice + } else { + #[cfg(feature = "std")] + std::debug_assert!( + false, + "Found broken indices in level run: found indices {}..{} for string of length {}", + level_run.start, + level_run.end, + text.len() + ); + return ret; + }; + + for (i, ch) in slice.char_indices() { + let actual_index = level_run.start + i; + // All paren characters are ON. + // From BidiBrackets.txt: + // > The Unicode property value stability policy guarantees that characters + // > which have bpt=o or bpt=c also have bc=ON and Bidi_M=Y + if original_classes[level_run.start + i] != BidiClass::ON { + continue; + } + + if let Some(matched) = data_source.bidi_matched_opening_bracket(ch) { + if matched.is_open { + // > If an opening paired bracket is found ... + + // > ... and there is no room in the stack, + // > stop processing BD16 for the remainder of the isolating run sequence. + if stack.len() >= 63 { + break; + } + // > ... push its Bidi_Paired_Bracket property value and its text position onto the stack + stack.push((matched.opening, actual_index, run_index)) + } else { + // > If a closing paired bracket is found, do the following + + // > Declare a variable that holds a reference to the current stack element + // > and initialize it with the top element of the stack. + // AND + // > Else, if the current stack element is not at the bottom of the stack + for (stack_index, element) in stack.iter().enumerate().rev() { + // > Compare the closing paired bracket being inspected or its canonical + // > equivalent to the bracket in the current stack element. + if element.0 == matched.opening { + // > If the values match, meaning the two characters form a bracket pair, then + + // > Append the text position in the current stack element together with the + // > text position of the closing paired bracket to the list. + let pair = BracketPair { + start: element.1, + end: actual_index, + start_run: element.2, + end_run: run_index, + }; + ret.push(pair); + + // > Pop the stack through the current stack element inclusively. + stack.truncate(stack_index); + break; + } + } + } + } + } + } + // > Sort the list of pairs of text positions in ascending order based on + // > the text position of the opening paired bracket. + ret.sort_by_key(|r| r.start); + ret +} + /// 3.3.6 Resolving Implicit Levels /// /// Returns the maximum embedding level in the paragraph. @@ -211,7 +568,6 @@ pub fn resolve_neutral( #[cfg_attr(feature = "flame_it", flamer::flame)] pub fn resolve_levels(original_classes: &[BidiClass], levels: &mut [Level]) -> Level { let mut max_level = Level::ltr(); - assert_eq!(original_classes.len(), levels.len()); for i in 0..levels.len() { match (levels[i].is_rtl(), original_classes[i]) { @@ -219,6 +575,7 @@ pub fn resolve_levels(original_classes: &[BidiClass], levels: &mut [Level]) -> L (false, R) | (true, L) | (true, EN) | (true, AN) => { levels[i].raise(1).expect("Level number error") } + // handled here (_, _) => {} } max_level = max(max_level, levels[i]); diff --git a/vendor/unicode-bidi/src/lib.rs b/vendor/unicode-bidi/src/lib.rs index bda9dd8ec..81d4fb5f5 100644 --- a/vendor/unicode-bidi/src/lib.rs +++ b/vendor/unicode-bidi/src/lib.rs @@ -354,8 +354,15 @@ impl<'text> BidiInfo<'text> { let sequences = prepare::isolating_run_sequences(para.level, original_classes, levels); for sequence in &sequences { - implicit::resolve_weak(sequence, processing_classes); - implicit::resolve_neutral(sequence, levels, processing_classes); + implicit::resolve_weak(text, sequence, processing_classes); + implicit::resolve_neutral( + text, + data_source, + sequence, + levels, + original_classes, + processing_classes, + ); } implicit::resolve_levels(processing_classes, levels); @@ -411,6 +418,71 @@ impl<'text> BidiInfo<'text> { result.into() } + /// Reorders pre-calculated levels of a sequence of characters. + /// + /// NOTE: This is a convenience method that does not use a `Paragraph` object. It is + /// intended to be used when an application has determined the levels of the objects (character sequences) + /// and just needs to have them reordered. + /// + /// the index map will result in `indexMap[visualIndex]==logicalIndex`. + /// + /// # # Example + /// ``` + /// use unicode_bidi::BidiInfo; + /// use unicode_bidi::Level; + /// + /// let l0 = Level::from(0); + /// let l1 = Level::from(1); + /// let l2 = Level::from(2); + /// + /// let levels = vec![l0, l0, l0, l0]; + /// let index_map = BidiInfo::reorder_visual(&levels); + /// assert_eq!(levels.len(), index_map.len()); + /// assert_eq!(index_map, [0, 1, 2, 3]); + /// + /// let levels: Vec = vec![l0, l0, l0, l1, l1, l1, l2, l2]; + /// let index_map = BidiInfo::reorder_visual(&levels); + /// assert_eq!(levels.len(), index_map.len()); + /// assert_eq!(index_map, [0, 1, 2, 5, 4, 3, 6, 7]); + /// ``` + pub fn reorder_visual(levels: &[Level]) -> Vec { + // Gets the next range + fn next_range(levels: &[level::Level], start_index: usize) -> Range { + if levels.is_empty() || start_index >= levels.len() { + return start_index..start_index; + } + + let mut end_index = start_index + 1; + while end_index < levels.len() { + if levels[start_index] != levels[end_index] { + return start_index..end_index; + } + end_index += 1; + } + + start_index..end_index + } + + if levels.is_empty() { + return vec![]; + } + let mut result: Vec = (0..levels.len()).collect(); + + let mut range: Range = 0..0; + loop { + range = next_range(levels, range.end); + if levels[range.start].is_rtl() { + result[range.clone()].reverse(); + } + + if range.end >= levels.len() { + break; + } + } + + result + } + /// Find the level runs within a line and return them in visual order. /// /// `line` is a range of bytes indices within `levels`. @@ -434,10 +506,9 @@ impl<'text> BidiInfo<'text> { let line_str: &str = &self.text[line.clone()]; let mut reset_from: Option = Some(0); let mut reset_to: Option = None; + let mut prev_level = para.level; for (i, c) in line_str.char_indices() { match line_classes[i] { - // Ignored by X9 - RLE | LRE | RLO | LRO | PDF | BN => {} // Segment separator, Paragraph separator B | S => { assert_eq!(reset_to, None); @@ -452,6 +523,15 @@ impl<'text> BidiInfo<'text> { reset_from = Some(i); } } + // + // same as above + set the level + RLE | LRE | RLO | LRO | PDF | BN => { + if reset_from == None { + reset_from = Some(i); + } + // also set the level to previous + line_levels[i] = prev_level; + } _ => { reset_from = None; } @@ -463,6 +543,7 @@ impl<'text> BidiInfo<'text> { reset_from = None; reset_to = None; } + prev_level = line_levels[i]; } if let Some(from) = reset_from { for level in &mut line_levels[from..] { @@ -874,7 +955,7 @@ mod tests { assert_eq!(reorder_paras("א(ב)ג."), vec![".ג)ב(א"]); // With mirrorable characters on level boundry - assert_eq!(reorder_paras("אב(גד[&ef].)gh"), vec!["ef].)gh&[דג(בא"]); + assert_eq!(reorder_paras("אב(גד[&ef].)gh"), vec!["gh).]ef&[דג(בא"]); } fn reordered_levels_for_paras(text: &str) -> Vec> { @@ -1023,7 +1104,7 @@ mod tests { } } -#[cfg(all(feature = "serde", test))] +#[cfg(all(feature = "serde", feature = "hardcoded-data", test))] mod serde_tests { use super::*; use serde_test::{assert_tokens, Token}; diff --git a/vendor/unicode-bidi/src/prepare.rs b/vendor/unicode-bidi/src/prepare.rs index 7b952361a..21675e6d1 100644 --- a/vendor/unicode-bidi/src/prepare.rs +++ b/vendor/unicode-bidi/src/prepare.rs @@ -89,12 +89,35 @@ pub fn isolating_run_sequences( .map(|sequence: Vec| { assert!(!sequence.is_empty()); - let start_of_seq = sequence[0].start; - let end_of_seq = sequence[sequence.len() - 1].end; - let seq_level = levels[start_of_seq]; + let mut result = IsolatingRunSequence { + runs: sequence, + sos: L, + eos: L, + }; + + let start_of_seq = result.runs[0].start; + let runs_len = result.runs.len(); + let end_of_seq = result.runs[runs_len - 1].end; + + // > (not counting characters removed by X9) + let seq_level = result + .iter_forwards_from(start_of_seq, 0) + .filter(|i| not_removed_by_x9(&original_classes[*i])) + .map(|i| levels[i]) + .next() + .unwrap_or(levels[start_of_seq]); + + // XXXManishearth the spec talks of a start and end level, + // but for a given IRS the two should be equivalent, yes? + let end_level = result + .iter_backwards_from(end_of_seq, runs_len - 1) + .filter(|i| not_removed_by_x9(&original_classes[*i])) + .map(|i| levels[i]) + .next() + .unwrap_or(levels[end_of_seq - 1]); #[cfg(test)] - for run in sequence.clone() { + for run in result.runs.clone() { for idx in run { if not_removed_by_x9(&original_classes[idx]) { assert_eq!(seq_level, levels[idx]); @@ -111,8 +134,19 @@ pub fn isolating_run_sequences( None => para_level, }; + // Get the last non-removed character to check if it is an isolate initiator. + // The spec calls for an unmatched one, but matched isolate initiators + // will never be at the end of a level run (otherwise there would be more to the run). + // We unwrap_or(BN) because BN marks removed classes and it won't matter for the check. + let last_non_removed = original_classes[..end_of_seq] + .iter() + .copied() + .rev() + .find(not_removed_by_x9) + .unwrap_or(BN); + // Get the level of the next non-removed char after the runs. - let succ_level = if let RLI | LRI | FSI = original_classes[end_of_seq - 1] { + let succ_level = if let RLI | LRI | FSI = last_non_removed { para_level } else { match original_classes[end_of_seq..] @@ -124,15 +158,63 @@ pub fn isolating_run_sequences( } }; - IsolatingRunSequence { - runs: sequence, - sos: max(seq_level, pred_level).bidi_class(), - eos: max(seq_level, succ_level).bidi_class(), - } + result.sos = max(seq_level, pred_level).bidi_class(); + result.eos = max(end_level, succ_level).bidi_class(); + result }) .collect() } +impl IsolatingRunSequence { + /// Returns the full range of text represented by this isolating run sequence + pub(crate) fn text_range(&self) -> Range { + if let (Some(start), Some(end)) = (self.runs.first(), self.runs.last()) { + start.start..end.end + } else { + return 0..0; + } + } + + /// Given a text-relative position `pos` and an index of the level run it is in, + /// produce an iterator of all characters after and pos (`pos..`) that are in this + /// run sequence + pub(crate) fn iter_forwards_from( + &self, + pos: usize, + level_run_index: usize, + ) -> impl Iterator + '_ { + let runs = &self.runs[level_run_index..]; + + // Check that it is in range + // (we can't use contains() since we want an inclusive range) + #[cfg(feature = "std")] + debug_assert!(runs[0].start <= pos && pos <= runs[0].end); + + (pos..runs[0].end).chain(runs[1..].iter().flat_map(Clone::clone)) + } + + /// Given a text-relative position `pos` and an index of the level run it is in, + /// produce an iterator of all characters before and excludingpos (`..pos`) that are in this + /// run sequence + pub(crate) fn iter_backwards_from( + &self, + pos: usize, + level_run_index: usize, + ) -> impl Iterator + '_ { + let prev_runs = &self.runs[..level_run_index]; + let current = &self.runs[level_run_index]; + + // Check that it is in range + // (we can't use contains() since we want an inclusive range) + #[cfg(feature = "std")] + debug_assert!(current.start <= pos && pos <= current.end); + + (current.start..pos) + .rev() + .chain(prev_runs.iter().rev().flat_map(Clone::clone)) + } +} + /// Finds the level runs in a paragraph. /// /// -- cgit v1.2.3