From 2be6a7be48abac356b4c99459306408c049482a3 Mon Sep 17 00:00:00 2001 From: Serge Bazanski Date: Sat, 3 Apr 2021 16:35:31 +0000 Subject: [PATCH] third_party/cargo: add mlua --- third_party/cargo/BUILD.bazel | 9 + third_party/cargo/Cargo.lock | 23 + third_party/cargo/Cargo.toml | 4 + .../vendor/bstr-0.2.15/.cargo-checksum.json | 1 + .../cargo/vendor/bstr-0.2.15/BUILD.bazel | 71 + third_party/cargo/vendor/bstr-0.2.15/COPYING | 8 + .../cargo/vendor/bstr-0.2.15/Cargo.lock | 134 + .../cargo/vendor/bstr-0.2.15/Cargo.toml | 68 + .../cargo/vendor/bstr-0.2.15/LICENSE-APACHE | 201 + .../cargo/vendor/bstr-0.2.15/LICENSE-MIT | 21 + .../cargo/vendor/bstr-0.2.15/README.md | 254 ++ .../bstr-0.2.15/examples/graphemes-std.rs | 28 + .../vendor/bstr-0.2.15/examples/graphemes.rs | 24 + .../vendor/bstr-0.2.15/examples/lines-std.rs | 17 + .../vendor/bstr-0.2.15/examples/lines.rs | 19 + .../bstr-0.2.15/examples/uppercase-std.rs | 15 + .../vendor/bstr-0.2.15/examples/uppercase.rs | 20 + .../vendor/bstr-0.2.15/examples/words-std.rs | 20 + .../vendor/bstr-0.2.15/examples/words.rs | 17 + .../cargo/vendor/bstr-0.2.15/rustfmt.toml | 2 + .../bstr-0.2.15/scripts/generate-unicode-data | 149 + .../bstr-0.2.15/scripts/regex/grapheme.sh | 50 + .../bstr-0.2.15/scripts/regex/sentence.sh | 176 + .../vendor/bstr-0.2.15/scripts/regex/word.sh | 111 + .../cargo/vendor/bstr-0.2.15/src/ascii.rs | 336 ++ .../cargo/vendor/bstr-0.2.15/src/bstr.rs | 74 + .../cargo/vendor/bstr-0.2.15/src/bstring.rs | 59 + .../vendor/bstr-0.2.15/src/byteset/mod.rs | 115 + .../vendor/bstr-0.2.15/src/byteset/scalar.rs | 295 ++ .../cargo/vendor/bstr-0.2.15/src/cow.rs | 84 + .../cargo/vendor/bstr-0.2.15/src/ext_slice.rs | 3695 +++++++++++++++++ .../cargo/vendor/bstr-0.2.15/src/ext_vec.rs | 1108 +++++ .../cargo/vendor/bstr-0.2.15/src/impls.rs | 984 +++++ .../cargo/vendor/bstr-0.2.15/src/io.rs | 514 +++ .../cargo/vendor/bstr-0.2.15/src/lib.rs | 456 ++ .../src/search/byte_frequencies.rs | 258 ++ .../vendor/bstr-0.2.15/src/search/mod.rs | 8 + .../bstr-0.2.15/src/search/prefilter.rs | 424 ++ .../vendor/bstr-0.2.15/src/search/tests.rs | 225 + .../vendor/bstr-0.2.15/src/search/twoway.rs | 871 ++++ .../cargo/vendor/bstr-0.2.15/src/tests.rs | 32 + .../src/unicode/data/GraphemeBreakTest.txt | 630 +++ .../src/unicode/data/LICENSE-UNICODE | 45 + .../src/unicode/data/SentenceBreakTest.txt | 530 +++ .../src/unicode/data/WordBreakTest.txt | 1851 +++++++++ .../fsm/grapheme_break_fwd.bigendian.dfa | Bin 0 -> 10589 bytes .../fsm/grapheme_break_fwd.littleendian.dfa | Bin 0 -> 10589 bytes .../src/unicode/fsm/grapheme_break_fwd.rs | 41 + .../fsm/grapheme_break_rev.bigendian.dfa | Bin 0 -> 53905 bytes .../fsm/grapheme_break_rev.littleendian.dfa | Bin 0 -> 53905 bytes .../src/unicode/fsm/grapheme_break_rev.rs | 41 + .../vendor/bstr-0.2.15/src/unicode/fsm/mod.rs | 8 + .../fsm/regional_indicator_rev.bigendian.dfa | Bin 0 -> 366 bytes .../regional_indicator_rev.littleendian.dfa | Bin 0 -> 366 bytes .../src/unicode/fsm/regional_indicator_rev.rs | 41 + .../fsm/sentence_break_fwd.bigendian.dfa | Bin 0 -> 149903 bytes .../fsm/sentence_break_fwd.littleendian.dfa | Bin 0 -> 149903 bytes .../src/unicode/fsm/sentence_break_fwd.rs | 41 + .../unicode/fsm/simple_word_fwd.bigendian.dfa | Bin 0 -> 8975 bytes .../fsm/simple_word_fwd.littleendian.dfa | Bin 0 -> 8975 bytes .../src/unicode/fsm/simple_word_fwd.rs | 41 + .../fsm/whitespace_anchored_fwd.bigendian.dfa | Bin 0 -> 572 bytes .../whitespace_anchored_fwd.littleendian.dfa | Bin 0 -> 572 bytes .../unicode/fsm/whitespace_anchored_fwd.rs | 41 + .../fsm/whitespace_anchored_rev.bigendian.dfa | Bin 0 -> 598 bytes .../whitespace_anchored_rev.littleendian.dfa | Bin 0 -> 598 bytes .../unicode/fsm/whitespace_anchored_rev.rs | 41 + .../unicode/fsm/word_break_fwd.bigendian.dfa | Bin 0 -> 229739 bytes .../fsm/word_break_fwd.littleendian.dfa | Bin 0 -> 229739 bytes .../src/unicode/fsm/word_break_fwd.rs | 41 + .../bstr-0.2.15/src/unicode/grapheme.rs | 355 ++ .../vendor/bstr-0.2.15/src/unicode/mod.rs | 12 + .../bstr-0.2.15/src/unicode/sentence.rs | 220 + .../bstr-0.2.15/src/unicode/whitespace.rs | 14 + .../vendor/bstr-0.2.15/src/unicode/word.rs | 406 ++ .../cargo/vendor/bstr-0.2.15/src/utf8.rs | 1370 ++++++ .../vendor/mlua-0.5.3/.cargo-checksum.json | 1 + .../cargo/vendor/mlua-0.5.3/BUILD.bazel | 135 + .../cargo/vendor/mlua-0.5.3/CHANGELOG.md | 45 + .../cargo/vendor/mlua-0.5.3/Cargo.lock | 1685 ++++++++ .../cargo/vendor/mlua-0.5.3/Cargo.toml | 143 + third_party/cargo/vendor/mlua-0.5.3/LICENSE | 25 + third_party/cargo/vendor/mlua-0.5.3/README.md | 239 ++ .../vendor/mlua-0.5.3/benches/benchmark.rs | 283 ++ .../vendor/mlua-0.5.3/build/find_dummy.rs | 5 + .../vendor/mlua-0.5.3/build/find_normal.rs | 138 + .../vendor/mlua-0.5.3/build/find_vendored.rs | 19 + .../cargo/vendor/mlua-0.5.3/build/main.rs | 240 ++ .../mlua-0.5.3/examples/async_http_client.rs | 83 + .../mlua-0.5.3/examples/async_http_reqwest.rs | 41 + .../mlua-0.5.3/examples/async_http_server.rs | 101 + .../mlua-0.5.3/examples/async_tcp_server.rs | 128 + .../vendor/mlua-0.5.3/examples/guided_tour.rs | 201 + .../cargo/vendor/mlua-0.5.3/examples/repl.rs | 48 + .../vendor/mlua-0.5.3/examples/serialize.rs | 66 + .../cargo/vendor/mlua-0.5.3/src/conversion.rs | 569 +++ .../cargo/vendor/mlua-0.5.3/src/error.rs | 329 ++ .../vendor/mlua-0.5.3/src/ffi/compat53.rs | 809 ++++ .../vendor/mlua-0.5.3/src/ffi/glue/glue.c | 289 ++ .../vendor/mlua-0.5.3/src/ffi/lauxlib.rs | 306 ++ .../cargo/vendor/mlua-0.5.3/src/ffi/lua.rs | 808 ++++ .../vendor/mlua-0.5.3/src/ffi/luaconf.rs | 36 + .../cargo/vendor/mlua-0.5.3/src/ffi/lualib.rs | 67 + .../cargo/vendor/mlua-0.5.3/src/ffi/mod.rs | 290 ++ .../cargo/vendor/mlua-0.5.3/src/function.rs | 251 ++ .../cargo/vendor/mlua-0.5.3/src/hook.rs | 195 + .../cargo/vendor/mlua-0.5.3/src/lib.rs | 133 + .../cargo/vendor/mlua-0.5.3/src/lua.rs | 2445 +++++++++++ .../cargo/vendor/mlua-0.5.3/src/macros.rs | 96 + .../cargo/vendor/mlua-0.5.3/src/multi.rs | 215 + .../cargo/vendor/mlua-0.5.3/src/prelude.rs | 16 + .../cargo/vendor/mlua-0.5.3/src/scope.rs | 648 +++ .../cargo/vendor/mlua-0.5.3/src/serde/de.rs | 329 ++ .../cargo/vendor/mlua-0.5.3/src/serde/mod.rs | 200 + .../cargo/vendor/mlua-0.5.3/src/serde/ser.rs | 366 ++ .../cargo/vendor/mlua-0.5.3/src/stdlib.rs | 99 + .../cargo/vendor/mlua-0.5.3/src/string.rs | 126 + .../cargo/vendor/mlua-0.5.3/src/table.rs | 778 ++++ .../cargo/vendor/mlua-0.5.3/src/thread.rs | 366 ++ .../cargo/vendor/mlua-0.5.3/src/types.rs | 128 + .../cargo/vendor/mlua-0.5.3/src/userdata.rs | 662 +++ .../cargo/vendor/mlua-0.5.3/src/util.rs | 767 ++++ .../cargo/vendor/mlua-0.5.3/src/value.rs | 255 ++ .../cargo/vendor/mlua-0.5.3/tests/async.rs | 448 ++ .../vendor/mlua-0.5.3/tests/byte_string.rs | 108 + .../cargo/vendor/mlua-0.5.3/tests/compile.rs | 24 + .../tests/compile/async_nonstatic_userdata.rs | 17 + .../compile/async_nonstatic_userdata.stderr | 36 + .../tests/compile/function_borrow.rs | 12 + .../tests/compile/function_borrow.stderr | 20 + .../tests/compile/lua_norefunwindsafe.rs | 8 + .../tests/compile/lua_norefunwindsafe.stderr | 16 + .../mlua-0.5.3/tests/compile/non_send.rs | 17 + .../mlua-0.5.3/tests/compile/non_send.stderr | 14 + .../tests/compile/ref_nounwindsafe.rs | 9 + .../tests/compile/ref_nounwindsafe.stderr | 18 + .../tests/compile/scope_callback_capture.rs | 18 + .../compile/scope_callback_capture.stderr | 26 + .../tests/compile/scope_callback_inner.rs | 15 + .../tests/compile/scope_callback_inner.stderr | 42 + .../tests/compile/scope_callback_outer.rs | 15 + .../tests/compile/scope_callback_outer.stderr | 30 + .../tests/compile/scope_invariance.rs | 23 + .../tests/compile/scope_invariance.stderr | 25 + .../tests/compile/scope_mutable_aliasing.rs | 15 + .../compile/scope_mutable_aliasing.stderr | 9 + .../tests/compile/scope_userdata_borrow.rs | 19 + .../compile/scope_userdata_borrow.stderr | 13 + .../tests/compile/static_callback_args.rs | 32 + .../tests/compile/static_callback_args.stderr | 35 + .../tests/compile/userdata_borrow.rs | 19 + .../tests/compile/userdata_borrow.stderr | 13 + .../cargo/vendor/mlua-0.5.3/tests/function.rs | 103 + .../cargo/vendor/mlua-0.5.3/tests/hooks.rs | 261 ++ .../cargo/vendor/mlua-0.5.3/tests/memory.rs | 103 + .../cargo/vendor/mlua-0.5.3/tests/scope.rs | 240 ++ .../cargo/vendor/mlua-0.5.3/tests/serde.rs | 341 ++ .../cargo/vendor/mlua-0.5.3/tests/string.rs | 77 + .../cargo/vendor/mlua-0.5.3/tests/table.rs | 311 ++ .../cargo/vendor/mlua-0.5.3/tests/tests.rs | 967 +++++ .../cargo/vendor/mlua-0.5.3/tests/thread.rs | 147 + .../cargo/vendor/mlua-0.5.3/tests/types.rs | 38 + .../cargo/vendor/mlua-0.5.3/tests/userdata.rs | 349 ++ .../cargo/vendor/mlua-0.5.3/tests/value.rs | 69 + 164 files changed, 36055 insertions(+) create mode 100644 third_party/cargo/vendor/bstr-0.2.15/.cargo-checksum.json create mode 100644 third_party/cargo/vendor/bstr-0.2.15/BUILD.bazel create mode 100644 third_party/cargo/vendor/bstr-0.2.15/COPYING create mode 100644 third_party/cargo/vendor/bstr-0.2.15/Cargo.lock create mode 100644 third_party/cargo/vendor/bstr-0.2.15/Cargo.toml create mode 100644 third_party/cargo/vendor/bstr-0.2.15/LICENSE-APACHE create mode 100644 third_party/cargo/vendor/bstr-0.2.15/LICENSE-MIT create mode 100644 third_party/cargo/vendor/bstr-0.2.15/README.md create mode 100644 third_party/cargo/vendor/bstr-0.2.15/examples/graphemes-std.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/examples/graphemes.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/examples/lines-std.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/examples/lines.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/examples/uppercase-std.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/examples/uppercase.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/examples/words-std.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/examples/words.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/rustfmt.toml create mode 100755 third_party/cargo/vendor/bstr-0.2.15/scripts/generate-unicode-data create mode 100644 third_party/cargo/vendor/bstr-0.2.15/scripts/regex/grapheme.sh create mode 100644 third_party/cargo/vendor/bstr-0.2.15/scripts/regex/sentence.sh create mode 100644 third_party/cargo/vendor/bstr-0.2.15/scripts/regex/word.sh create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/ascii.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/bstr.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/bstring.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/byteset/mod.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/byteset/scalar.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/cow.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/ext_slice.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/ext_vec.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/impls.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/io.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/lib.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/search/byte_frequencies.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/search/mod.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/search/prefilter.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/search/tests.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/search/twoway.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/tests.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/data/GraphemeBreakTest.txt create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/data/LICENSE-UNICODE create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/data/SentenceBreakTest.txt create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/data/WordBreakTest.txt create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/grapheme_break_fwd.bigendian.dfa create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/grapheme_break_fwd.littleendian.dfa create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/grapheme_break_fwd.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/grapheme_break_rev.bigendian.dfa create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/grapheme_break_rev.littleendian.dfa create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/grapheme_break_rev.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/mod.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/regional_indicator_rev.bigendian.dfa create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/regional_indicator_rev.littleendian.dfa create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/regional_indicator_rev.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/sentence_break_fwd.bigendian.dfa create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/sentence_break_fwd.littleendian.dfa create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/sentence_break_fwd.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/simple_word_fwd.bigendian.dfa create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/simple_word_fwd.littleendian.dfa create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/simple_word_fwd.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/whitespace_anchored_fwd.bigendian.dfa create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/whitespace_anchored_fwd.littleendian.dfa create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/whitespace_anchored_fwd.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/whitespace_anchored_rev.bigendian.dfa create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/whitespace_anchored_rev.littleendian.dfa create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/whitespace_anchored_rev.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/word_break_fwd.bigendian.dfa create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/word_break_fwd.littleendian.dfa create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/word_break_fwd.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/grapheme.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/mod.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/sentence.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/whitespace.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/unicode/word.rs create mode 100644 third_party/cargo/vendor/bstr-0.2.15/src/utf8.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/.cargo-checksum.json create mode 100644 third_party/cargo/vendor/mlua-0.5.3/BUILD.bazel create mode 100644 third_party/cargo/vendor/mlua-0.5.3/CHANGELOG.md create mode 100644 third_party/cargo/vendor/mlua-0.5.3/Cargo.lock create mode 100644 third_party/cargo/vendor/mlua-0.5.3/Cargo.toml create mode 100644 third_party/cargo/vendor/mlua-0.5.3/LICENSE create mode 100644 third_party/cargo/vendor/mlua-0.5.3/README.md create mode 100644 third_party/cargo/vendor/mlua-0.5.3/benches/benchmark.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/build/find_dummy.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/build/find_normal.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/build/find_vendored.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/build/main.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/examples/async_http_client.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/examples/async_http_reqwest.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/examples/async_http_server.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/examples/async_tcp_server.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/examples/guided_tour.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/examples/repl.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/examples/serialize.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/src/conversion.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/src/error.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/src/ffi/compat53.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/src/ffi/glue/glue.c create mode 100644 third_party/cargo/vendor/mlua-0.5.3/src/ffi/lauxlib.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/src/ffi/lua.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/src/ffi/luaconf.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/src/ffi/lualib.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/src/ffi/mod.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/src/function.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/src/hook.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/src/lib.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/src/lua.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/src/macros.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/src/multi.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/src/prelude.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/src/scope.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/src/serde/de.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/src/serde/mod.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/src/serde/ser.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/src/stdlib.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/src/string.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/src/table.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/src/thread.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/src/types.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/src/userdata.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/src/util.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/src/value.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/async.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/byte_string.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/compile.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/compile/async_nonstatic_userdata.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/compile/async_nonstatic_userdata.stderr create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/compile/function_borrow.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/compile/function_borrow.stderr create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/compile/lua_norefunwindsafe.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/compile/lua_norefunwindsafe.stderr create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/compile/non_send.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/compile/non_send.stderr create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/compile/ref_nounwindsafe.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/compile/ref_nounwindsafe.stderr create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_callback_capture.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_callback_capture.stderr create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_callback_inner.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_callback_inner.stderr create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_callback_outer.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_callback_outer.stderr create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_invariance.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_invariance.stderr create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_mutable_aliasing.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_mutable_aliasing.stderr create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_userdata_borrow.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_userdata_borrow.stderr create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/compile/static_callback_args.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/compile/static_callback_args.stderr create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/compile/userdata_borrow.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/compile/userdata_borrow.stderr create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/function.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/hooks.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/memory.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/scope.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/serde.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/string.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/table.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/tests.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/thread.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/types.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/userdata.rs create mode 100644 third_party/cargo/vendor/mlua-0.5.3/tests/value.rs diff --git a/third_party/cargo/BUILD.bazel b/third_party/cargo/BUILD.bazel index ce75c69..fdc3ff0 100644 --- a/third_party/cargo/BUILD.bazel +++ b/third_party/cargo/BUILD.bazel @@ -57,6 +57,15 @@ alias( ], ) +alias( + name = "mlua", + actual = "//third_party/cargo/vendor/mlua-0.5.3:mlua", + tags = [ + "cargo-raze", + "manual", + ], +) + alias( name = "proc_macro2", actual = "//third_party/cargo/vendor/proc-macro2-1.0.26:proc_macro2", diff --git a/third_party/cargo/Cargo.lock b/third_party/cargo/Cargo.lock index 009cb0a..ab0c45a 100644 --- a/third_party/cargo/Cargo.lock +++ b/third_party/cargo/Cargo.lock @@ -78,6 +78,15 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" +[[package]] +name = "bstr" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a40b47ad93e1a5404e6c18dec46b628214fee441c70f4ab5d6942142cc268a3d" +dependencies = [ + "memchr", +] + [[package]] name = "bytemuck" version = "1.5.1" @@ -189,6 +198,7 @@ dependencies = [ "flatbuffers", "image", "log", + "mlua", "proc-macro2", "quote", "syn", @@ -839,6 +849,19 @@ dependencies = [ "ws2_32-sys", ] +[[package]] +name = "mlua" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f2fc8e1085d53b72898c59ceee1980b5826b0c98ce99886b7518f0ead00e5cb" +dependencies = [ + "bstr", + "cc", + "lazy_static", + "num-traits", + "pkg-config", +] + [[package]] name = "ndk" version = "0.2.1" diff --git a/third_party/cargo/Cargo.toml b/third_party/cargo/Cargo.toml index 7d9ce8d..5efa61d 100644 --- a/third_party/cargo/Cargo.toml +++ b/third_party/cargo/Cargo.toml @@ -19,6 +19,7 @@ flatbuffers = "0.6.1" quote = "1.0.8" syn = "1.0.58" proc-macro2 = "1" +mlua = { version = "0.5", features = [ "luajit" ] } [workspace.metadata.raze] workspace_path = "//third_party/cargo" @@ -72,3 +73,6 @@ gen_buildrs = true [workspace.metadata.raze.crates.proc-macro2.'1.0.26'] gen_buildrs = true + +[workspace.metadata.raze.crates.mlua.'0.5.3'] +gen_buildrs = true diff --git a/third_party/cargo/vendor/bstr-0.2.15/.cargo-checksum.json b/third_party/cargo/vendor/bstr-0.2.15/.cargo-checksum.json new file mode 100644 index 0000000..8d29b86 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"COPYING":"13361f93b3db60ddb43f8fdc97ba469461019bbf7589f6bde833eb3d995d2497","Cargo.lock":"9f7cf1723aeddda5e807e935a648b55f23c0d915540aa99a47c748009b5ec27f","Cargo.toml":"3442fc6c3d5db00d04e48621c3c201adafca89c3c58bce24cf232b0b1a749193","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6b7374c39a57e57fc2c38eb529c4c88340152b10f51dd5ae2d819dfa67f61715","README.md":"e4221484a420af69d0b3dea2b036bcee46c1af86d2d3cb9b08acca0d4806fa6c","examples/graphemes-std.rs":"eb3e1f3a02bb4b1c280b0551a962910991073e0b063b8926de6787112542ec70","examples/graphemes.rs":"60fe5a739e6574f92595d4cd5782e46982d9b77c9421be056c42144a3f793090","examples/lines-std.rs":"094a48bfd483ec01f80f9c937ddfe6f0bdbf09f960ba822215ec8ed9862624df","examples/lines.rs":"016f1b40a4e4ce014762ac7f2b87883276b54b0a953f64c2dce219fd6ac4fd08","examples/uppercase-std.rs":"33aed88e38483aa303625757304a974594476a3a659d8bdd4877aceb90ff8be3","examples/uppercase.rs":"20eec94b1450011590b1c9d5c128627b39bf530bc0cb7f6a0431a08e6618e8be","examples/words-std.rs":"9307bd97d08a9415034865b9ae165f25cfb3f0cd57c7d2930bf61a346550088e","examples/words.rs":"5684f31ab3325078a7c0243f8acceaee64605e29d3bb40ac204df9d23a2b3251","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","scripts/generate-unicode-data":"c42f0b50acdbaf757a4a947c918907419f8d04a453ae43e6388f4aefbcde7d40","scripts/regex/grapheme.sh":"d796bca73278f6ab04d65f285b2dc72efcad76874f98f4bfa22bf38f2eaeece7","scripts/regex/sentence.sh":"7892e07ac9e450967bd79279558cbef2f0fc0b0aefab24217910937ed6330f06","scripts/regex/word.sh":"b3f53e2331e9e50a1a7232b7d278aaecace6a42ef6c16dd0b8d0ec59fd2aaf4f","src/ascii.rs":"19bdd85083467382c5bcc31345aa7ce731cc0dbfad3db21cbf09ee86a4ef8327","src/bstr.rs":"10e8af4cf7f39226da45bfb4836bd9da3694edf963d20f34b19574efc9bdbd58","src/bstring.rs":"d8d8019d946ad1ff5633a0cf711e635b84c96833cb56697cc663a3fcf19f1c47","src/byteset/mod.rs":"a806119a7268e63303039d49b574521304a79f48a216b90b225eae0d9446b695","src/byteset/scalar.rs":"72bfb5b38b08bf6045ec7dbf117e1f5a255707371b5d3d222f732eae4e725ad8","src/cow.rs":"904254e403d53da6b49edbab22eb5bde2513508f7ccd5ce1cabebdb67b438156","src/ext_slice.rs":"3ec4b936cf3ab54132311343b21746efd981030f3227188ff64bcb89de88335e","src/ext_vec.rs":"0bf1b901afdb5a75351f5c99f141aedd89fe2d9122e35ebb10c5e017049b48ae","src/impls.rs":"158e81ce89b032573da938c26ce16ee458ad7d9d9b09aa662fc40cf78bce1429","src/io.rs":"0a33c14848d897645e87f1078bc6f8fea67aba268b85d5c9dd9a9b5ffefa8ca3","src/lib.rs":"cca133b2bdf6966cac345dcb32d65cd76e1f7e994664e68bd62b278c053f500f","src/search/byte_frequencies.rs":"2fb85b381c038c1e44ce94294531cdcd339dca48b1e61f41455666e802cbbc9e","src/search/mod.rs":"11a978f770530fd4c49fa482ec2ec470d946aa88f87c9daebf4dcbd5adb319f8","src/search/prefilter.rs":"33e11d05ad23b1f74bcd9feba2cd3727f96e4259365d83d5f310706994a9788d","src/search/tests.rs":"a4da61ba75e0bc413dc65afba19557c0ea383281568284c3c418ecac34e7af51","src/search/twoway.rs":"40525c8b721429e4643164d501948d67395cf1232ff498d73fdaa954f2cc9720","src/tests.rs":"9e50757473b50273ae3a8aeaed924282ffab82ded7134c15745f3b798b16e574","src/unicode/data/GraphemeBreakTest.txt":"95bd55cf803b93eb0b4990cf0e1d70ede263b36412d9c6921fd6f15cef058961","src/unicode/data/LICENSE-UNICODE":"8b9babb256418ec15761d635a49f973424939affba7a0a88de2fc2690e454a23","src/unicode/data/SentenceBreakTest.txt":"7d6c909af97d0ab545a132d412f6e4e65c7eb5158514a7feb9bf00bcd05875f9","src/unicode/data/WordBreakTest.txt":"3e3320bbbe775de7f1a0b9a30021eb949116a9b05cb461c90596c5ecf1743831","src/unicode/fsm/grapheme_break_fwd.bigendian.dfa":"6daed7530f9e0798b51fbd758ea4626ce53d889bdc7d64dd7d2124b3d0c065db","src/unicode/fsm/grapheme_break_fwd.littleendian.dfa":"f24e7d3fd1fe702811e315611fbe5be24746f7f30e5fd30cf578ade55ae2ac15","src/unicode/fsm/grapheme_break_fwd.rs":"ffaef88bcf3fb183cf3745b4335bfb2c1d4d2ff2d11036b5017e1a6727b52be5","src/unicode/fsm/grapheme_break_rev.bigendian.dfa":"58544096b5209e438d65000d481ad8bdab4c1ee21f1af70247fafd2a0638b712","src/unicode/fsm/grapheme_break_rev.littleendian.dfa":"9895471633472d48ad3280f436c63b5ae08989c1816cd511428c0dc01d32e7f2","src/unicode/fsm/grapheme_break_rev.rs":"109f55e19c4b29520a418d25a65f429b9e2a7e9d235eee8ae7f0cd5ce2a2d74e","src/unicode/fsm/mod.rs":"50b8baa692e83f909a0fe62eced9666b712a68b6c7bf42976c8cc37e49dd9b64","src/unicode/fsm/regional_indicator_rev.bigendian.dfa":"db9db4c86bced5f4aaf68d5e475e13e5d4976c237deec13c192111a399aa5858","src/unicode/fsm/regional_indicator_rev.littleendian.dfa":"0905f70acddd423c1b53bfbeb73299009f724400029d7f9a987d63c32d36e36c","src/unicode/fsm/regional_indicator_rev.rs":"80bd9be781905e5026e2db9035b0142042a5eaa54e24b36bb8b53b9168bccacb","src/unicode/fsm/sentence_break_fwd.bigendian.dfa":"3c1966fb1edd143264dc98e59b5c907b383dc20a957ae3e3982c38fbfac7d5a2","src/unicode/fsm/sentence_break_fwd.littleendian.dfa":"855249a618cb57d3403a449883a925e6d6cd4dfc5d316f473038f258ea890b3f","src/unicode/fsm/sentence_break_fwd.rs":"262a9afbf806970037738f64d9c8a4c9c678bd7d5174428fdf53abe631df1ef5","src/unicode/fsm/simple_word_fwd.bigendian.dfa":"8092da9a59d903bdee43fd73a95f32bb61e611e46528c676aeb42b3810bce085","src/unicode/fsm/simple_word_fwd.littleendian.dfa":"c79d90294aa00f4915295d13d13eb3743cb202066088c9407a6a3690f4b172d4","src/unicode/fsm/simple_word_fwd.rs":"20a1ec830dbb68271e9b4035724e429049bb39e31e8577d07a9aaed5c42efd2a","src/unicode/fsm/whitespace_anchored_fwd.bigendian.dfa":"593c8ad059ab0bee60a2ea25f4c1fc89c105cb19a9bda3fa98d1464b8e87cfc0","src/unicode/fsm/whitespace_anchored_fwd.littleendian.dfa":"a04ed70d5dbd969c0af0e12bec5033ca910161c486f741dd0a792d2e5b0cc6f6","src/unicode/fsm/whitespace_anchored_fwd.rs":"6819588c68ec864e33f8f900849e22360485b5d6d6fe174c874963404ee73278","src/unicode/fsm/whitespace_anchored_rev.bigendian.dfa":"44bb1cf58f5c86f807f4d023a390f0610c31de0c27149a12ab9b40d136f51471","src/unicode/fsm/whitespace_anchored_rev.littleendian.dfa":"0933c1651d9cb6cbc55ab849c071e13aaea3221f636c93e830ff810c84389dff","src/unicode/fsm/whitespace_anchored_rev.rs":"38248b042ec55e8a005fa3705c67e8bc42c0bd7a434092f49f761c9219d4b0b7","src/unicode/fsm/word_break_fwd.bigendian.dfa":"5ec979ebe17f0d0b85805625c5b9206476a518d89c707c869dcbe24f422367c8","src/unicode/fsm/word_break_fwd.littleendian.dfa":"28e1b3e13a4ff4b0c7660b611f9e5dd0a087bb3b9a9b63b27cd2eb69a8412a31","src/unicode/fsm/word_break_fwd.rs":"e2aa3b71f6b0b124566f6a1104df9fb03965118f1a8723c8f993a58c6f9a9352","src/unicode/grapheme.rs":"6fdc10a25074a779f92270371a63933267273177b772bbdda6e4af54d7f10f72","src/unicode/mod.rs":"93340dcadca5a4f01a0a993d40e283e98015065098a7b1d076ab966ee591736d","src/unicode/sentence.rs":"ce56007aa1ee395aa174121d8f23828f35b879880bc1684b383b3b9abb99b001","src/unicode/whitespace.rs":"4e13e258cb67821c36fd1edd20b65b87f4e0127f288d8546a86ad7f5f390c267","src/unicode/word.rs":"000c6f5ec17e9f6d5cbe8a1c60a14abe14cba5a29c5868731c4e6d03efdae4e7","src/utf8.rs":"65d5e2602912b98d800fe97b3c997c6791a9ff070559d0270db0eead3dee05ce"},"package":"a40b47ad93e1a5404e6c18dec46b628214fee441c70f4ab5d6942142cc268a3d"} \ No newline at end of file diff --git a/third_party/cargo/vendor/bstr-0.2.15/BUILD.bazel b/third_party/cargo/vendor/bstr-0.2.15/BUILD.bazel new file mode 100644 index 0000000..8aa9bea --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/BUILD.bazel @@ -0,0 +1,71 @@ +""" +@generated +cargo-raze crate build file. + +DO NOT EDIT! Replaced on runs of cargo-raze +""" + +# buildifier: disable=load +load( + "@rules_rust//rust:rust.bzl", + "rust_binary", + "rust_library", + "rust_test", +) + +# buildifier: disable=load +load("@bazel_skylib//lib:selects.bzl", "selects") + +package(default_visibility = [ + # Public for visibility by "@raze__crate__version//" targets. + # + # Prefer access through "//third_party/cargo", which limits external + # visibility to explicit Cargo.toml dependencies. + "//visibility:public", +]) + +licenses([ + "notice", # MIT from expression "MIT OR Apache-2.0" +]) + +# Generated Targets + +# Unsupported target "graphemes" with type "example" omitted + +# Unsupported target "graphemes-std" with type "example" omitted + +# Unsupported target "lines" with type "example" omitted + +# Unsupported target "lines-std" with type "example" omitted + +# Unsupported target "uppercase" with type "example" omitted + +# Unsupported target "uppercase-std" with type "example" omitted + +# Unsupported target "words" with type "example" omitted + +# Unsupported target "words-std" with type "example" omitted + +rust_library( + name = "bstr", + srcs = glob(["**/*.rs"]), + crate_features = [ + "std", + ], + crate_root = "src/lib.rs", + crate_type = "lib", + data = [], + edition = "2015", + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-raze", + "manual", + ], + version = "0.2.15", + # buildifier: leave-alone + deps = [ + "//third_party/cargo/vendor/memchr-2.3.4:memchr", + ], +) diff --git a/third_party/cargo/vendor/bstr-0.2.15/COPYING b/third_party/cargo/vendor/bstr-0.2.15/COPYING new file mode 100644 index 0000000..d5a7d7e --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/COPYING @@ -0,0 +1,8 @@ +This project is licensed under either of + + * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or + http://www.apache.org/licenses/LICENSE-2.0) + * MIT license ([LICENSE-MIT](LICENSE-MIT) or + http://opensource.org/licenses/MIT) + +at your option. diff --git a/third_party/cargo/vendor/bstr-0.2.15/Cargo.lock b/third_party/cargo/vendor/bstr-0.2.15/Cargo.lock new file mode 100644 index 0000000..2978201 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/Cargo.lock @@ -0,0 +1,134 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "bstr" +version = "0.2.15" +dependencies = [ + "lazy_static", + "memchr", + "quickcheck", + "regex-automata", + "serde", + "ucd-parse", + "unicode-segmentation", +] + +[[package]] +name = "byteorder" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "getrandom" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ccac4b00700875e6a07c6cde370d44d32fa01c5a65cdd2fca6858c479d28bb3" + +[[package]] +name = "memchr" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" + +[[package]] +name = "quickcheck" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6" +dependencies = [ + "rand", +] + +[[package]] +name = "rand" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c026d7df8b298d90ccbbc5190bd04d85e159eaf5576caeacf8741da93ccbd2e5" +dependencies = [ + "getrandom", +] + +[[package]] +name = "regex" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4" +dependencies = [ + "byteorder", +] + +[[package]] +name = "regex-syntax" +version = "0.6.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" + +[[package]] +name = "serde" +version = "1.0.123" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae" + +[[package]] +name = "ucd-parse" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5269f8d35df6b8b60758343a6d742ecf09e4bca13faee32af5503aebd1e11b7c" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "unicode-segmentation" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796" + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" diff --git a/third_party/cargo/vendor/bstr-0.2.15/Cargo.toml b/third_party/cargo/vendor/bstr-0.2.15/Cargo.toml new file mode 100644 index 0000000..f02d695 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/Cargo.toml @@ -0,0 +1,68 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +name = "bstr" +version = "0.2.15" +authors = ["Andrew Gallant "] +exclude = ["/.github"] +description = "A string type that is not required to be valid UTF-8." +homepage = "https://github.com/BurntSushi/bstr" +documentation = "https://docs.rs/bstr" +readme = "README.md" +keywords = ["string", "str", "byte", "bytes", "text"] +categories = ["text-processing", "encoding"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/BurntSushi/bstr" +[profile.release] +debug = true + +[lib] +bench = false +[dependencies.lazy_static] +version = "1.2" +optional = true + +[dependencies.memchr] +version = "2.1.2" +default-features = false + +[dependencies.regex-automata] +version = "0.1.5" +optional = true +default-features = false + +[dependencies.serde] +version = "1.0.85" +optional = true +default-features = false +[dev-dependencies.quickcheck] +version = "1" +default-features = false + +[dev-dependencies.ucd-parse] +version = "0.1.3" + +[dev-dependencies.unicode-segmentation] +version = "1.2.1" + +[features] +default = ["std", "unicode"] +serde1 = ["std", "serde1-nostd", "serde/std"] +serde1-nostd = ["serde"] +std = ["memchr/use_std"] +unicode = ["lazy_static", "regex-automata"] +[badges.appveyor] +repository = "BurntSushi/bstr" + +[badges.travis-ci] +repository = "BurntSushi/bstr" diff --git a/third_party/cargo/vendor/bstr-0.2.15/LICENSE-APACHE b/third_party/cargo/vendor/bstr-0.2.15/LICENSE-APACHE new file mode 100644 index 0000000..16fe87b --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +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. diff --git a/third_party/cargo/vendor/bstr-0.2.15/LICENSE-MIT b/third_party/cargo/vendor/bstr-0.2.15/LICENSE-MIT new file mode 100644 index 0000000..17d6873 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/LICENSE-MIT @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2018-2019 Andrew Gallant + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/third_party/cargo/vendor/bstr-0.2.15/README.md b/third_party/cargo/vendor/bstr-0.2.15/README.md new file mode 100644 index 0000000..3e4ef8b --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/README.md @@ -0,0 +1,254 @@ +bstr +==== +This crate provides extension traits for `&[u8]` and `Vec` that enable +their use as byte strings, where byte strings are _conventionally_ UTF-8. This +differs from the standard library's `String` and `str` types in that they are +not required to be valid UTF-8, but may be fully or partially valid UTF-8. + +[![Build status](https://github.com/BurntSushi/bstr/workflows/ci/badge.svg)](https://github.com/BurntSushi/bstr/actions) +[![](https://meritbadge.herokuapp.com/bstr)](https://crates.io/crates/bstr) + + +### Documentation + +https://docs.rs/bstr + + +### When should I use byte strings? + +See this part of the documentation for more details: +https://docs.rs/bstr/0.2.*/bstr/#when-should-i-use-byte-strings. + +The short story is that byte strings are useful when it is inconvenient or +incorrect to require valid UTF-8. + + +### Usage + +Add this to your `Cargo.toml`: + +```toml +[dependencies] +bstr = "0.2" +``` + + +### Examples + +The following two examples exhibit both the API features of byte strings and +the I/O convenience functions provided for reading line-by-line quickly. + +This first example simply shows how to efficiently iterate over lines in +stdin, and print out lines containing a particular substring: + +```rust +use std::error::Error; +use std::io::{self, Write}; + +use bstr::{ByteSlice, io::BufReadExt}; + +fn main() -> Result<(), Box> { + let stdin = io::stdin(); + let mut stdout = io::BufWriter::new(io::stdout()); + + stdin.lock().for_byte_line_with_terminator(|line| { + if line.contains_str("Dimension") { + stdout.write_all(line)?; + } + Ok(true) + })?; + Ok(()) +} +``` + +This example shows how to count all of the words (Unicode-aware) in stdin, +line-by-line: + +```rust +use std::error::Error; +use std::io; + +use bstr::{ByteSlice, io::BufReadExt}; + +fn main() -> Result<(), Box> { + let stdin = io::stdin(); + let mut words = 0; + stdin.lock().for_byte_line_with_terminator(|line| { + words += line.words().count(); + Ok(true) + })?; + println!("{}", words); + Ok(()) +} +``` + +This example shows how to convert a stream on stdin to uppercase without +performing UTF-8 validation _and_ amortizing allocation. On standard ASCII +text, this is quite a bit faster than what you can (easily) do with standard +library APIs. (N.B. Any invalid UTF-8 bytes are passed through unchanged.) + +```rust +use std::error::Error; +use std::io::{self, Write}; + +use bstr::{ByteSlice, io::BufReadExt}; + +fn main() -> Result<(), Box> { + let stdin = io::stdin(); + let mut stdout = io::BufWriter::new(io::stdout()); + + let mut upper = vec![]; + stdin.lock().for_byte_line_with_terminator(|line| { + upper.clear(); + line.to_uppercase_into(&mut upper); + stdout.write_all(&upper)?; + Ok(true) + })?; + Ok(()) +} +``` + +This example shows how to extract the first 10 visual characters (as grapheme +clusters) from each line, where invalid UTF-8 sequences are generally treated +as a single character and are passed through correctly: + +```rust +use std::error::Error; +use std::io::{self, Write}; + +use bstr::{ByteSlice, io::BufReadExt}; + +fn main() -> Result<(), Box> { + let stdin = io::stdin(); + let mut stdout = io::BufWriter::new(io::stdout()); + + stdin.lock().for_byte_line_with_terminator(|line| { + let end = line + .grapheme_indices() + .map(|(_, end, _)| end) + .take(10) + .last() + .unwrap_or(line.len()); + stdout.write_all(line[..end].trim_end())?; + stdout.write_all(b"\n")?; + Ok(true) + })?; + Ok(()) +} +``` + + +### Cargo features + +This crates comes with a few features that control standard library, serde +and Unicode support. + +* `std` - **Enabled** by default. This provides APIs that require the standard + library, such as `Vec`. +* `unicode` - **Enabled** by default. This provides APIs that require sizable + Unicode data compiled into the binary. This includes, but is not limited to, + grapheme/word/sentence segmenters. When this is disabled, basic support such + as UTF-8 decoding is still included. +* `serde1` - **Disabled** by default. Enables implementations of serde traits + for the `BStr` and `BString` types. +* `serde1-nostd` - **Disabled** by default. Enables implementations of serde + traits for the `BStr` type only, intended for use without the standard + library. Generally, you either want `serde1` or `serde1-nostd`, not both. + + +### Minimum Rust version policy + +This crate's minimum supported `rustc` version (MSRV) is `1.28.0`. + +In general, this crate will be conservative with respect to the minimum +supported version of Rust. MSRV may be bumped in minor version releases. + + +### Future work + +Since this is meant to be a core crate, getting a `1.0` release is a priority. +My hope is to move to `1.0` within the next year and commit to its API so that +`bstr` can be used as a public dependency. + +A large part of the API surface area was taken from the standard library, so +from an API design perspective, a good portion of this crate should be mature. +The main differences from the standard library are in how the various substring +search routines work. The standard library provides generic infrastructure for +supporting different types of searches with a single method, where as this +library prefers to define new methods for each type of search and drop the +generic infrastructure. + +Some _probable_ future considerations for APIs include, but are not limited to: + +* A convenience layer on top of the `aho-corasick` crate. +* Unicode normalization. +* More sophisticated support for dealing with Unicode case, perhaps by + combining the use cases supported by [`caseless`](https://docs.rs/caseless) + and [`unicase`](https://docs.rs/unicase). +* Add facilities for dealing with OS strings and file paths, probably via + simple conversion routines. + +Here are some examples that are _probably_ out of scope for this crate: + +* Regular expressions. +* Unicode collation. + +The exact scope isn't quite clear, but I expect we can iterate on it. + +In general, as stated below, this crate is an experiment in bringing lots of +related APIs together into a single crate while simultaneously attempting to +keep the total number of dependencies low. Indeed, every dependency of `bstr`, +except for `memchr`, is optional. + + +### High level motivation + +Strictly speaking, the `bstr` crate provides very little that can't already be +achieved with the standard library `Vec`/`&[u8]` APIs and the ecosystem of +library crates. For example: + +* The standard library's + [`Utf8Error`](https://doc.rust-lang.org/std/str/struct.Utf8Error.html) + can be used for incremental lossy decoding of `&[u8]`. +* The + [`unicode-segmentation`](https://unicode-rs.github.io/unicode-segmentation/unicode_segmentation/index.html) + crate can be used for iterating over graphemes (or words), but is only + implemented for `&str` types. One could use `Utf8Error` above to implement + grapheme iteration with the same semantics as what `bstr` provides (automatic + Unicode replacement codepoint substitution). +* The [`twoway`](https://docs.rs/twoway) crate can be used for + fast substring searching on `&[u8]`. + +So why create `bstr`? Part of the point of the `bstr` crate is to provide a +uniform API of coupled components instead of relying on users to piece together +loosely coupled components from the crate ecosystem. For example, if you wanted +to perform a search and replace in a `Vec`, then writing the code to do +that with the `twoway` crate is not that difficult, but it's still additional +glue code you have to write. This work adds up depending on what you're doing. +Consider, for example, trimming and splitting, along with their different +variants. + +In other words, `bstr` is partially a way of pushing back against the +micro-crate ecosystem that appears to be evolving. It's not clear to me whether +this experiment will be successful or not, but it is definitely a goal of +`bstr` to keep its dependency list lightweight. For example, `serde` is an +optional dependency because there is no feasible alternative, but `twoway` is +not, where we instead prefer to implement our own substring search. In service +of this philosophy, currently, the only required dependency of `bstr` is +`memchr`. + + +### License + +This project is licensed under either of + + * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or + https://www.apache.org/licenses/LICENSE-2.0) + * MIT license ([LICENSE-MIT](LICENSE-MIT) or + https://opensource.org/licenses/MIT) + +at your option. + +The data in `src/unicode/data/` is licensed under the Unicode License Agreement +([LICENSE-UNICODE](https://www.unicode.org/copyright.html#License)), although +this data is only used in tests. diff --git a/third_party/cargo/vendor/bstr-0.2.15/examples/graphemes-std.rs b/third_party/cargo/vendor/bstr-0.2.15/examples/graphemes-std.rs new file mode 100644 index 0000000..3522736 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/examples/graphemes-std.rs @@ -0,0 +1,28 @@ +extern crate unicode_segmentation; + +use std::error::Error; +use std::io::{self, BufRead, Write}; + +use unicode_segmentation::UnicodeSegmentation; + +fn main() -> Result<(), Box> { + let stdin = io::stdin(); + let mut stdin = stdin.lock(); + let mut stdout = io::BufWriter::new(io::stdout()); + + let mut line = String::new(); + while stdin.read_line(&mut line)? > 0 { + let end = line + .grapheme_indices(true) + .map(|(start, g)| start + g.len()) + .take(10) + .last() + .unwrap_or(line.len()); + #[allow(deprecated)] // for Rust 1.28.0 + stdout.write_all(line[..end].trim_right().as_bytes())?; + stdout.write_all(b"\n")?; + + line.clear(); + } + Ok(()) +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/examples/graphemes.rs b/third_party/cargo/vendor/bstr-0.2.15/examples/graphemes.rs new file mode 100644 index 0000000..2372490 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/examples/graphemes.rs @@ -0,0 +1,24 @@ +extern crate bstr; + +use std::error::Error; +use std::io::{self, Write}; + +use bstr::{io::BufReadExt, ByteSlice}; + +fn main() -> Result<(), Box> { + let stdin = io::stdin(); + let mut stdout = io::BufWriter::new(io::stdout()); + + stdin.lock().for_byte_line_with_terminator(|line| { + let end = line + .grapheme_indices() + .map(|(_, end, _)| end) + .take(10) + .last() + .unwrap_or(line.len()); + stdout.write_all(line[..end].trim_end())?; + stdout.write_all(b"\n")?; + Ok(true) + })?; + Ok(()) +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/examples/lines-std.rs b/third_party/cargo/vendor/bstr-0.2.15/examples/lines-std.rs new file mode 100644 index 0000000..69fc6a5 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/examples/lines-std.rs @@ -0,0 +1,17 @@ +use std::error::Error; +use std::io::{self, BufRead, Write}; + +fn main() -> Result<(), Box> { + let stdin = io::stdin(); + let mut stdin = stdin.lock(); + let mut stdout = io::BufWriter::new(io::stdout()); + + let mut line = String::new(); + while stdin.read_line(&mut line)? > 0 { + if line.contains("Dimension") { + stdout.write_all(line.as_bytes())?; + } + line.clear(); + } + Ok(()) +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/examples/lines.rs b/third_party/cargo/vendor/bstr-0.2.15/examples/lines.rs new file mode 100644 index 0000000..4b1045f --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/examples/lines.rs @@ -0,0 +1,19 @@ +extern crate bstr; + +use std::error::Error; +use std::io::{self, Write}; + +use bstr::{io::BufReadExt, ByteSlice}; + +fn main() -> Result<(), Box> { + let stdin = io::stdin(); + let mut stdout = io::BufWriter::new(io::stdout()); + + stdin.lock().for_byte_line_with_terminator(|line| { + if line.contains_str("Dimension") { + stdout.write_all(line)?; + } + Ok(true) + })?; + Ok(()) +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/examples/uppercase-std.rs b/third_party/cargo/vendor/bstr-0.2.15/examples/uppercase-std.rs new file mode 100644 index 0000000..672bd71 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/examples/uppercase-std.rs @@ -0,0 +1,15 @@ +use std::error::Error; +use std::io::{self, BufRead, Write}; + +fn main() -> Result<(), Box> { + let stdin = io::stdin(); + let mut stdin = stdin.lock(); + let mut stdout = io::BufWriter::new(io::stdout()); + + let mut line = String::new(); + while stdin.read_line(&mut line)? > 0 { + stdout.write_all(line.to_uppercase().as_bytes())?; + line.clear(); + } + Ok(()) +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/examples/uppercase.rs b/third_party/cargo/vendor/bstr-0.2.15/examples/uppercase.rs new file mode 100644 index 0000000..f9771e0 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/examples/uppercase.rs @@ -0,0 +1,20 @@ +extern crate bstr; + +use std::error::Error; +use std::io::{self, Write}; + +use bstr::{io::BufReadExt, ByteSlice}; + +fn main() -> Result<(), Box> { + let stdin = io::stdin(); + let mut stdout = io::BufWriter::new(io::stdout()); + + let mut upper = vec![]; + stdin.lock().for_byte_line_with_terminator(|line| { + upper.clear(); + line.to_uppercase_into(&mut upper); + stdout.write_all(&upper)?; + Ok(true) + })?; + Ok(()) +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/examples/words-std.rs b/third_party/cargo/vendor/bstr-0.2.15/examples/words-std.rs new file mode 100644 index 0000000..7eae116 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/examples/words-std.rs @@ -0,0 +1,20 @@ +extern crate unicode_segmentation; + +use std::error::Error; +use std::io::{self, BufRead}; + +use unicode_segmentation::UnicodeSegmentation; + +fn main() -> Result<(), Box> { + let stdin = io::stdin(); + let mut stdin = stdin.lock(); + + let mut words = 0; + let mut line = String::new(); + while stdin.read_line(&mut line)? > 0 { + words += line.unicode_words().count(); + line.clear(); + } + println!("{}", words); + Ok(()) +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/examples/words.rs b/third_party/cargo/vendor/bstr-0.2.15/examples/words.rs new file mode 100644 index 0000000..eb20c0d --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/examples/words.rs @@ -0,0 +1,17 @@ +extern crate bstr; + +use std::error::Error; +use std::io; + +use bstr::{io::BufReadExt, ByteSlice}; + +fn main() -> Result<(), Box> { + let stdin = io::stdin(); + let mut words = 0; + stdin.lock().for_byte_line_with_terminator(|line| { + words += line.words().count(); + Ok(true) + })?; + println!("{}", words); + Ok(()) +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/rustfmt.toml b/third_party/cargo/vendor/bstr-0.2.15/rustfmt.toml new file mode 100644 index 0000000..aa37a21 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/rustfmt.toml @@ -0,0 +1,2 @@ +max_width = 79 +use_small_heuristics = "max" diff --git a/third_party/cargo/vendor/bstr-0.2.15/scripts/generate-unicode-data b/third_party/cargo/vendor/bstr-0.2.15/scripts/generate-unicode-data new file mode 100755 index 0000000..6b59fae --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/scripts/generate-unicode-data @@ -0,0 +1,149 @@ +#!/bin/sh + +set -e +D="$(dirname "$0")" + +# Convenience function for checking that a command exists. +requires() { + cmd="$1" + if ! command -v "$cmd" > /dev/null 2>&1; then + echo "DEPENDENCY MISSING: $cmd must be installed" >&2 + exit 1 + fi +} + +# Test if an array ($2) contains a particular element ($1). +array_exists() { + needle="$1" + shift + + for el in "$@"; do + if [ "$el" = "$needle" ]; then + return 0 + fi + done + return 1 +} + +graphemes() { + regex="$(sh "$D/regex/grapheme.sh")" + + echo "generating forward grapheme DFA" + ucd-generate dfa \ + --name GRAPHEME_BREAK_FWD \ + --sparse --minimize --anchored --state-size 2 \ + src/unicode/fsm/ \ + "$regex" + + echo "generating reverse grapheme DFA" + ucd-generate dfa \ + --name GRAPHEME_BREAK_REV \ + --reverse --longest \ + --sparse --minimize --anchored --state-size 2 \ + src/unicode/fsm/ \ + "$regex" +} + +words() { + regex="$(sh "$D/regex/word.sh")" + + echo "generating forward word DFA (this can take a while)" + ucd-generate dfa \ + --name WORD_BREAK_FWD \ + --sparse --minimize --anchored --state-size 4 \ + src/unicode/fsm/ \ + "$regex" +} + +sentences() { + regex="$(sh "$D/regex/sentence.sh")" + + echo "generating forward sentence DFA (this can take a while)" + ucd-generate dfa \ + --name SENTENCE_BREAK_FWD \ + --minimize \ + --sparse --anchored --state-size 4 \ + src/unicode/fsm/ \ + "$regex" +} + +regional_indicator() { + # For finding all occurrences of region indicators. This is used to handle + # regional indicators as a special case for the reverse grapheme iterator + # and the reverse word iterator. + echo "generating regional indicator DFA" + ucd-generate dfa \ + --name REGIONAL_INDICATOR_REV \ + --reverse \ + --classes --minimize --anchored --premultiply --state-size 1 \ + src/unicode/fsm/ \ + "\p{gcb=Regional_Indicator}" +} + +simple_word() { + echo "generating forward simple word DFA" + ucd-generate dfa \ + --name SIMPLE_WORD_FWD \ + --sparse --minimize --state-size 2 \ + src/unicode/fsm/ \ + "\w" +} + +whitespace() { + echo "generating forward whitespace DFA" + ucd-generate dfa \ + --name WHITESPACE_ANCHORED_FWD \ + --anchored --classes --premultiply --minimize --state-size 1 \ + src/unicode/fsm/ \ + "\s+" + + echo "generating reverse whitespace DFA" + ucd-generate dfa \ + --name WHITESPACE_ANCHORED_REV \ + --reverse \ + --anchored --classes --premultiply --minimize --state-size 1 \ + src/unicode/fsm/ \ + "\s+" +} + +main() { + if array_exists "-h" "$@" || array_exists "--help" "$@"; then + echo "Usage: $(basename "$0") [--list-commands] [] ..." >&2 + exit + fi + + commands=" + graphemes + sentences + words + regional-indicator + simple-word + whitespace + " + if array_exists "--list-commands" "$@"; then + for cmd in $commands; do + echo "$cmd" + done + exit + fi + + # ucd-generate is used to compile regexes into DFAs. + requires ucd-generate + + mkdir -p src/unicode/fsm/ + + cmds=$* + if [ $# -eq 0 ] || array_exists "all" "$@"; then + cmds=$commands + fi + for cmd in $cmds; do + if array_exists "$cmd" $commands; then + fun="$(echo "$cmd" | sed 's/-/_/g')" + eval "$fun" + else + echo "unrecognized command: $cmd" >&2 + fi + done +} + +main "$@" diff --git a/third_party/cargo/vendor/bstr-0.2.15/scripts/regex/grapheme.sh b/third_party/cargo/vendor/bstr-0.2.15/scripts/regex/grapheme.sh new file mode 100644 index 0000000..0b2b54d --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/scripts/regex/grapheme.sh @@ -0,0 +1,50 @@ +#!/bin/sh + +# vim: indentexpr= nosmartindent autoindent +# vim: tabstop=2 shiftwidth=2 softtabstop=2 + +# This regex was manually written, derived from the rules in UAX #29. +# Particularly, from Table 1c, which lays out a regex for grapheme clusters. + +CR="\p{gcb=CR}" +LF="\p{gcb=LF}" +Control="\p{gcb=Control}" +Prepend="\p{gcb=Prepend}" +L="\p{gcb=L}" +V="\p{gcb=V}" +LV="\p{gcb=LV}" +LVT="\p{gcb=LVT}" +T="\p{gcb=T}" +RI="\p{gcb=RI}" +Extend="\p{gcb=Extend}" +ZWJ="\p{gcb=ZWJ}" +SpacingMark="\p{gcb=SpacingMark}" + +Any="\p{any}" +ExtendPict="\p{Extended_Pictographic}" + +echo "(?x) +$CR $LF +| +$Control +| +$Prepend* +( + ( + ($L* ($V+ | $LV $V* | $LVT) $T*) + | + $L+ + | + $T+ + ) + | + $RI $RI + | + $ExtendPict ($Extend* $ZWJ $ExtendPict)* + | + [^$Control $CR $LF] +) +[$Extend $ZWJ $SpacingMark]* +| +$Any +" diff --git a/third_party/cargo/vendor/bstr-0.2.15/scripts/regex/sentence.sh b/third_party/cargo/vendor/bstr-0.2.15/scripts/regex/sentence.sh new file mode 100644 index 0000000..689d184 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/scripts/regex/sentence.sh @@ -0,0 +1,176 @@ +#!/bin/sh + +# vim: indentexpr= nosmartindent autoindent +# vim: tabstop=2 shiftwidth=2 softtabstop=2 + +# This is a regex that I reverse engineered from the sentence boundary chain +# rules in UAX #29. Unlike the grapheme regex, which is essentially provided +# for us in UAX #29, no such sentence regex exists. +# +# I looked into how ICU achieves this, since UAX #29 hints that producing +# finite state machines for grapheme/sentence/word/line breaking is possible, +# but only easy to do for graphemes. ICU does this by implementing their own +# DSL for describing the break algorithms in terms of the chaining rules +# directly. You can see an example for sentences in +# icu4c/source/data/brkitr/rules/sent.txt. ICU then builds a finite state +# machine from those rules in a mostly standard way, but implements the +# "chaining" aspect of the rules by connecting overlapping end and start +# states. For example, given SB7: +# +# (Upper | Lower) ATerm x Upper +# +# Then the naive way to convert this into a regex would be something like +# +# [\p{sb=Upper}\p{sb=Lower}]\p{sb=ATerm}\p{sb=Upper} +# +# Unfortunately, this is incorrect. Why? Well, consider an example like so: +# +# U.S.A. +# +# A correct implementation of the sentence breaking algorithm should not insert +# any breaks here, exactly in accordance with repeatedly applying rule SB7 as +# given above. Our regex fails to do this because it will first match `U.S` +# without breaking them---which is correct---but will then start looking for +# its next rule beginning with a full stop (in ATerm) and followed by an +# uppercase letter (A). This will wind up triggering rule SB11 (without +# matching `A`), which inserts a break. +# +# The reason why this happens is because our initial application of rule SB7 +# "consumes" the next uppercase letter (S), which we want to reuse as a prefix +# in the next rule application. A natural way to express this would be with +# look-around, although it's not clear that works in every case since you +# ultimately might want to consume that ending uppercase letter. In any case, +# we can't use look-around in our truly regular regexes, so we must fix this. +# The approach we take is to explicitly repeat rules when a suffix of a rule +# is a prefix of another rule. In the case of SB7, the end of the rule, an +# uppercase letter, also happens to match the beginning of the rule. This can +# in turn be repeated indefinitely. Thus, our actual translation to a regex is: +# +# [\p{sb=Upper}\p{sb=Lower}]\p{sb=ATerm}\p{sb=Upper}(\p{sb=ATerm}\p{sb=Upper}* +# +# It turns out that this is exactly what ICU does, but in their case, they do +# it automatically. In our case, we connect the chaining rules manually. It's +# tedious. With that said, we do no implement Unicode line breaking with this +# approach, which is a far scarier beast. In that case, it would probably be +# worth writing the code to do what ICU does. +# +# In the case of sentence breaks, there aren't *too* many overlaps of this +# nature. We list them out exhaustively to make this clear, because it's +# essentially impossible to easily observe this in the regex. (It took me a +# full day to figure all of this out.) Rules marked with N/A mean that they +# specify a break, and this strategy only really applies to stringing together +# non-breaks. +# +# SB1 - N/A +# SB2 - N/A +# SB3 - None +# SB4 - N/A +# SB5 - None +# SB6 - None +# SB7 - End overlaps with beginning of SB7 +# SB8 - End overlaps with beginning of SB7 +# SB8a - End overlaps with beginning of SB6, SB8, SB8a, SB9, SB10, SB11 +# SB9 - None +# SB10 - None +# SB11 - None +# SB998 - N/A +# +# SB8a is in particular quite tricky to get right without look-ahead, since it +# allows ping-ponging between match rules SB8a and SB9-11, where SB9-11 +# otherwise indicate that a break has been found. In the regex below, we tackle +# this by only permitting part of SB8a to match inside our core non-breaking +# repetition. In particular, we only allow the parts of SB8a to match that +# permit the non-breaking components to continue. If a part of SB8a matches +# that guarantees a pop out to SB9-11, (like `STerm STerm`), then we let it +# happen. This still isn't correct because an SContinue might be seen which +# would allow moving back into SB998 and thus the non-breaking repetition, so +# we handle that case as well. +# +# Finally, the last complication here is the sprinkling of $Ex* everywhere. +# This essentially corresponds to the implementation of SB5 by following +# UAX #29's recommendation in S6.2. Essentially, we use it avoid ever breaking +# in the middle of a grapheme cluster. + +CR="\p{sb=CR}" +LF="\p{sb=LF}" +Sep="\p{sb=Sep}" +Close="\p{sb=Close}" +Sp="\p{sb=Sp}" +STerm="\p{sb=STerm}" +ATerm="\p{sb=ATerm}" +SContinue="\p{sb=SContinue}" +Numeric="\p{sb=Numeric}" +Upper="\p{sb=Upper}" +Lower="\p{sb=Lower}" +OLetter="\p{sb=OLetter}" + +Ex="[\p{sb=Extend}\p{sb=Format}]" +ParaSep="[$Sep $CR $LF]" +SATerm="[$STerm $ATerm]" + +LetterSepTerm="[$OLetter $Upper $Lower $ParaSep $SATerm]" + +echo "(?x) +( + # SB6 + $ATerm $Ex* + $Numeric + | + # SB7 + [$Upper $Lower] $Ex* $ATerm $Ex* + $Upper $Ex* + # overlap with SB7 + ($ATerm $Ex* $Upper $Ex*)* + | + # SB8 + $ATerm $Ex* $Close* $Ex* $Sp* $Ex* + ([^$LetterSepTerm] $Ex*)* $Lower $Ex* + # overlap with SB7 + ($ATerm $Ex* $Upper $Ex*)* + | + # SB8a + $SATerm $Ex* $Close* $Ex* $Sp* $Ex* + ( + $SContinue + | + $ATerm $Ex* + # Permit repetition of SB8a + (($Close $Ex*)* ($Sp $Ex*)* $SATerm)* + # In order to continue non-breaking matching, we now must observe + # a match with a rule that keeps us in SB6-8a. Otherwise, we've entered + # one of SB9-11 and know that a break must follow. + ( + # overlap with SB6 + $Numeric + | + # overlap with SB8 + ($Close $Ex*)* ($Sp $Ex*)* + ([^$LetterSepTerm] $Ex*)* $Lower $Ex* + # overlap with SB7 + ($ATerm $Ex* $Upper $Ex*)* + | + # overlap with SB8a + ($Close $Ex*)* ($Sp $Ex*)* $SContinue + ) + | + $STerm $Ex* + # Permit repetition of SB8a + (($Close $Ex*)* ($Sp $Ex*)* $SATerm)* + # As with ATerm above, in order to continue non-breaking matching, we + # must now observe a match with a rule that keeps us out of SB9-11. + # For STerm, the only such possibility is to see an SContinue. Anything + # else will result in a break. + ($Close $Ex*)* ($Sp $Ex*)* $SContinue + ) + | + # SB998 + # The logic behind this catch-all is that if we get to this point and + # see a Sep, CR, LF, STerm or ATerm, then it has to fall into one of + # SB9, SB10 or SB11. In the cases of SB9-11, we always find a break since + # SB11 acts as a catch-all to induce a break following a SATerm that isn't + # handled by rules SB6-SB8a. + [^$ParaSep $SATerm] +)* +# The following collapses rules SB3, SB4, part of SB8a, SB9, SB10 and SB11. +($SATerm $Ex* ($Close $Ex*)* ($Sp $Ex*)*)* ($CR $LF | $ParaSep)? +" diff --git a/third_party/cargo/vendor/bstr-0.2.15/scripts/regex/word.sh b/third_party/cargo/vendor/bstr-0.2.15/scripts/regex/word.sh new file mode 100644 index 0000000..78c7a05 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/scripts/regex/word.sh @@ -0,0 +1,111 @@ +#!/bin/sh + +# vim: indentexpr= nosmartindent autoindent +# vim: tabstop=2 shiftwidth=2 softtabstop=2 + +# See the comments in regex/sentence.sh for the general approach to how this +# regex was written. +# +# Writing the regex for this was *hard*. It took me two days of hacking to get +# this far, and that was after I had finished the sentence regex, so my brain +# was fully cached on this. Unlike the sentence regex, the rules in the regex +# below don't correspond as nicely to the rules in UAX #29. In particular, the +# UAX #29 rules have a ton of overlap with each other, which requires crazy +# stuff in the regex. I'm not even sure the regex below is 100% correct or even +# minimal, however, I did compare this with the ICU word segmenter on a few +# different corpora, and it produces identical results. (In addition to of +# course passing the UCD tests.) +# +# In general, I consider this approach to be a failure. Firstly, this is +# clearly a write-only regex. Secondly, building the minimized DFA for this is +# incredibly slow. Thirdly, the DFA is itself very large (~240KB). Fourthly, +# reversing this regex (for reverse word iteration) results in a >19MB DFA. +# Yes. That's MB. Wat. And it took 5 minutes to build. +# +# I think we might consider changing our approach to this problem. The normal +# path I've seen, I think, is to decode codepoints one at a time, and then +# thread them through a state machine in the code itself. We could take this +# approach, or possibly combine it with a DFA that tells us which Word_Break +# value a codepoint has. I'd prefer the latter approach, but it requires adding +# RegexSet support to regex-automata. Something that should definitely be done, +# but is a fair amount of work. +# +# Gah. + +CR="\p{wb=CR}" +LF="\p{wb=LF}" +Newline="\p{wb=Newline}" +ZWJ="\p{wb=ZWJ}" +RI="\p{wb=Regional_Indicator}" +Katakana="\p{wb=Katakana}" +HebrewLet="\p{wb=HebrewLetter}" +ALetter="\p{wb=ALetter}" +SingleQuote="\p{wb=SingleQuote}" +DoubleQuote="\p{wb=DoubleQuote}" +MidNumLet="\p{wb=MidNumLet}" +MidLetter="\p{wb=MidLetter}" +MidNum="\p{wb=MidNum}" +Numeric="\p{wb=Numeric}" +ExtendNumLet="\p{wb=ExtendNumLet}" +WSegSpace="\p{wb=WSegSpace}" + +Any="\p{any}" +Ex="[\p{wb=Extend} \p{wb=Format} $ZWJ]" +ExtendPict="\p{Extended_Pictographic}" +AHLetter="[$ALetter $HebrewLet]" +MidNumLetQ="[$MidNumLet $SingleQuote]" + +AHLetterRepeat="$AHLetter $Ex* ([$MidLetter $MidNumLetQ] $Ex* $AHLetter $Ex*)*" +NumericRepeat="$Numeric $Ex* ([$MidNum $MidNumLetQ] $Ex* $Numeric $Ex*)*" + +echo "(?x) +$CR $LF +| +[$Newline $CR $LF] +| +$WSegSpace $WSegSpace+ +| +( + ([^$Newline $CR $LF]? $Ex* $ZWJ $ExtendPict $Ex*)+ + | + ($ExtendNumLet $Ex*)* $AHLetter $Ex* + ( + ( + ($NumericRepeat | $ExtendNumLet $Ex*)* + | + [$MidLetter $MidNumLetQ] $Ex* + ) + $AHLetter $Ex* + )+ + ($NumericRepeat | $ExtendNumLet $Ex*)* + | + ($ExtendNumLet $Ex*)* $AHLetter $Ex* ($NumericRepeat | $ExtendNumLet $Ex*)+ + | + ($ExtendNumLet $Ex*)* $Numeric $Ex* + ( + ( + ($AHLetterRepeat | $ExtendNumLet $Ex*)* + | + [$MidNum $MidNumLetQ] $Ex* + ) + $Numeric $Ex* + )+ + ($AHLetterRepeat | $ExtendNumLet $Ex*)* + | + ($ExtendNumLet $Ex*)* $Numeric $Ex* ($AHLetterRepeat | $ExtendNumLet $Ex*)+ + | + $Katakana $Ex* + (($Katakana | $ExtendNumLet) $Ex*)+ + | + $ExtendNumLet $Ex* + (($ExtendNumLet | $AHLetter | $Numeric | $Katakana) $Ex*)+ +)+ +| +$HebrewLet $Ex* $SingleQuote $Ex* +| +($HebrewLet $Ex* $DoubleQuote $Ex*)+ $HebrewLet $Ex* +| +$RI $Ex* $RI $Ex* +| +$Any $Ex* +" diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/ascii.rs b/third_party/cargo/vendor/bstr-0.2.15/src/ascii.rs new file mode 100644 index 0000000..bb2b679 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/ascii.rs @@ -0,0 +1,336 @@ +use core::mem; + +// The following ~400 lines of code exists for exactly one purpose, which is +// to optimize this code: +// +// byte_slice.iter().position(|&b| b > 0x7F).unwrap_or(byte_slice.len()) +// +// Yes... Overengineered is a word that comes to mind, but this is effectively +// a very similar problem to memchr, and virtually nobody has been able to +// resist optimizing the crap out of that (except for perhaps the BSD and MUSL +// folks). In particular, this routine makes a very common case (ASCII) very +// fast, which seems worth it. We do stop short of adding AVX variants of the +// code below in order to retain our sanity and also to avoid needing to deal +// with runtime target feature detection. RESIST! +// +// In order to understand the SIMD version below, it would be good to read this +// comment describing how my memchr routine works: +// https://github.com/BurntSushi/rust-memchr/blob/b0a29f267f4a7fad8ffcc8fe8377a06498202883/src/x86/sse2.rs#L19-L106 +// +// The primary difference with memchr is that for ASCII, we can do a bit less +// work. In particular, we don't need to detect the presence of a specific +// byte, but rather, whether any byte has its most significant bit set. That +// means we can effectively skip the _mm_cmpeq_epi8 step and jump straight to +// _mm_movemask_epi8. + +#[cfg(any(test, not(target_arch = "x86_64")))] +const USIZE_BYTES: usize = mem::size_of::(); +#[cfg(any(test, not(target_arch = "x86_64")))] +const FALLBACK_LOOP_SIZE: usize = 2 * USIZE_BYTES; + +// This is a mask where the most significant bit of each byte in the usize +// is set. We test this bit to determine whether a character is ASCII or not. +// Namely, a single byte is regarded as an ASCII codepoint if and only if it's +// most significant bit is not set. +#[cfg(any(test, not(target_arch = "x86_64")))] +const ASCII_MASK_U64: u64 = 0x8080808080808080; +#[cfg(any(test, not(target_arch = "x86_64")))] +const ASCII_MASK: usize = ASCII_MASK_U64 as usize; + +/// Returns the index of the first non ASCII byte in the given slice. +/// +/// If slice only contains ASCII bytes, then the length of the slice is +/// returned. +pub fn first_non_ascii_byte(slice: &[u8]) -> usize { + #[cfg(not(target_arch = "x86_64"))] + { + first_non_ascii_byte_fallback(slice) + } + + #[cfg(target_arch = "x86_64")] + { + first_non_ascii_byte_sse2(slice) + } +} + +#[cfg(any(test, not(target_arch = "x86_64")))] +fn first_non_ascii_byte_fallback(slice: &[u8]) -> usize { + let align = USIZE_BYTES - 1; + let start_ptr = slice.as_ptr(); + let end_ptr = slice[slice.len()..].as_ptr(); + let mut ptr = start_ptr; + + unsafe { + if slice.len() < USIZE_BYTES { + return first_non_ascii_byte_slow(start_ptr, end_ptr, ptr); + } + + let chunk = read_unaligned_usize(ptr); + let mask = chunk & ASCII_MASK; + if mask != 0 { + return first_non_ascii_byte_mask(mask); + } + + ptr = ptr_add(ptr, USIZE_BYTES - (start_ptr as usize & align)); + debug_assert!(ptr > start_ptr); + debug_assert!(ptr_sub(end_ptr, USIZE_BYTES) >= start_ptr); + if slice.len() >= FALLBACK_LOOP_SIZE { + while ptr <= ptr_sub(end_ptr, FALLBACK_LOOP_SIZE) { + debug_assert_eq!(0, (ptr as usize) % USIZE_BYTES); + + let a = *(ptr as *const usize); + let b = *(ptr_add(ptr, USIZE_BYTES) as *const usize); + if (a | b) & ASCII_MASK != 0 { + // What a kludge. We wrap the position finding code into + // a non-inlineable function, which makes the codegen in + // the tight loop above a bit better by avoiding a + // couple extra movs. We pay for it by two additional + // stores, but only in the case of finding a non-ASCII + // byte. + #[inline(never)] + unsafe fn findpos( + start_ptr: *const u8, + ptr: *const u8, + ) -> usize { + let a = *(ptr as *const usize); + let b = *(ptr_add(ptr, USIZE_BYTES) as *const usize); + + let mut at = sub(ptr, start_ptr); + let maska = a & ASCII_MASK; + if maska != 0 { + return at + first_non_ascii_byte_mask(maska); + } + + at += USIZE_BYTES; + let maskb = b & ASCII_MASK; + debug_assert!(maskb != 0); + return at + first_non_ascii_byte_mask(maskb); + } + return findpos(start_ptr, ptr); + } + ptr = ptr_add(ptr, FALLBACK_LOOP_SIZE); + } + } + first_non_ascii_byte_slow(start_ptr, end_ptr, ptr) + } +} + +#[cfg(target_arch = "x86_64")] +fn first_non_ascii_byte_sse2(slice: &[u8]) -> usize { + use core::arch::x86_64::*; + + const VECTOR_SIZE: usize = mem::size_of::<__m128i>(); + const VECTOR_ALIGN: usize = VECTOR_SIZE - 1; + const VECTOR_LOOP_SIZE: usize = 4 * VECTOR_SIZE; + + let start_ptr = slice.as_ptr(); + let end_ptr = slice[slice.len()..].as_ptr(); + let mut ptr = start_ptr; + + unsafe { + if slice.len() < VECTOR_SIZE { + return first_non_ascii_byte_slow(start_ptr, end_ptr, ptr); + } + + let chunk = _mm_loadu_si128(ptr as *const __m128i); + let mask = _mm_movemask_epi8(chunk); + if mask != 0 { + return mask.trailing_zeros() as usize; + } + + ptr = ptr.add(VECTOR_SIZE - (start_ptr as usize & VECTOR_ALIGN)); + debug_assert!(ptr > start_ptr); + debug_assert!(end_ptr.sub(VECTOR_SIZE) >= start_ptr); + if slice.len() >= VECTOR_LOOP_SIZE { + while ptr <= ptr_sub(end_ptr, VECTOR_LOOP_SIZE) { + debug_assert_eq!(0, (ptr as usize) % VECTOR_SIZE); + + let a = _mm_load_si128(ptr as *const __m128i); + let b = _mm_load_si128(ptr.add(VECTOR_SIZE) as *const __m128i); + let c = + _mm_load_si128(ptr.add(2 * VECTOR_SIZE) as *const __m128i); + let d = + _mm_load_si128(ptr.add(3 * VECTOR_SIZE) as *const __m128i); + + let or1 = _mm_or_si128(a, b); + let or2 = _mm_or_si128(c, d); + let or3 = _mm_or_si128(or1, or2); + if _mm_movemask_epi8(or3) != 0 { + let mut at = sub(ptr, start_ptr); + let mask = _mm_movemask_epi8(a); + if mask != 0 { + return at + mask.trailing_zeros() as usize; + } + + at += VECTOR_SIZE; + let mask = _mm_movemask_epi8(b); + if mask != 0 { + return at + mask.trailing_zeros() as usize; + } + + at += VECTOR_SIZE; + let mask = _mm_movemask_epi8(c); + if mask != 0 { + return at + mask.trailing_zeros() as usize; + } + + at += VECTOR_SIZE; + let mask = _mm_movemask_epi8(d); + debug_assert!(mask != 0); + return at + mask.trailing_zeros() as usize; + } + ptr = ptr_add(ptr, VECTOR_LOOP_SIZE); + } + } + while ptr <= end_ptr.sub(VECTOR_SIZE) { + debug_assert!(sub(end_ptr, ptr) >= VECTOR_SIZE); + + let chunk = _mm_loadu_si128(ptr as *const __m128i); + let mask = _mm_movemask_epi8(chunk); + if mask != 0 { + return sub(ptr, start_ptr) + mask.trailing_zeros() as usize; + } + ptr = ptr.add(VECTOR_SIZE); + } + first_non_ascii_byte_slow(start_ptr, end_ptr, ptr) + } +} + +#[inline(always)] +unsafe fn first_non_ascii_byte_slow( + start_ptr: *const u8, + end_ptr: *const u8, + mut ptr: *const u8, +) -> usize { + debug_assert!(start_ptr <= ptr); + debug_assert!(ptr <= end_ptr); + + while ptr < end_ptr { + if *ptr > 0x7F { + return sub(ptr, start_ptr); + } + ptr = ptr.offset(1); + } + sub(end_ptr, start_ptr) +} + +/// Compute the position of the first ASCII byte in the given mask. +/// +/// The mask should be computed by `chunk & ASCII_MASK`, where `chunk` is +/// 8 contiguous bytes of the slice being checked where *at least* one of those +/// bytes is not an ASCII byte. +/// +/// The position returned is always in the inclusive range [0, 7]. +#[cfg(any(test, not(target_arch = "x86_64")))] +fn first_non_ascii_byte_mask(mask: usize) -> usize { + #[cfg(target_endian = "little")] + { + mask.trailing_zeros() as usize / 8 + } + #[cfg(target_endian = "big")] + { + mask.leading_zeros() as usize / 8 + } +} + +/// Increment the given pointer by the given amount. +unsafe fn ptr_add(ptr: *const u8, amt: usize) -> *const u8 { + debug_assert!(amt < ::core::isize::MAX as usize); + ptr.offset(amt as isize) +} + +/// Decrement the given pointer by the given amount. +unsafe fn ptr_sub(ptr: *const u8, amt: usize) -> *const u8 { + debug_assert!(amt < ::core::isize::MAX as usize); + ptr.offset((amt as isize).wrapping_neg()) +} + +#[cfg(any(test, not(target_arch = "x86_64")))] +unsafe fn read_unaligned_usize(ptr: *const u8) -> usize { + use core::ptr; + + let mut n: usize = 0; + ptr::copy_nonoverlapping(ptr, &mut n as *mut _ as *mut u8, USIZE_BYTES); + n +} + +/// Subtract `b` from `a` and return the difference. `a` should be greater than +/// or equal to `b`. +fn sub(a: *const u8, b: *const u8) -> usize { + debug_assert!(a >= b); + (a as usize) - (b as usize) +} + +#[cfg(test)] +mod tests { + use super::*; + + // Our testing approach here is to try and exhaustively test every case. + // This includes the position at which a non-ASCII byte occurs in addition + // to the alignment of the slice that we're searching. + + #[test] + fn positive_fallback_forward() { + for i in 0..517 { + let s = "a".repeat(i); + assert_eq!( + i, + first_non_ascii_byte_fallback(s.as_bytes()), + "i: {:?}, len: {:?}, s: {:?}", + i, + s.len(), + s + ); + } + } + + #[test] + #[cfg(target_arch = "x86_64")] + fn positive_sse2_forward() { + for i in 0..517 { + let b = "a".repeat(i).into_bytes(); + assert_eq!(b.len(), first_non_ascii_byte_sse2(&b)); + } + } + + #[test] + fn negative_fallback_forward() { + for i in 0..517 { + for align in 0..65 { + let mut s = "a".repeat(i); + s.push_str("☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃"); + let s = s.get(align..).unwrap_or(""); + assert_eq!( + i.saturating_sub(align), + first_non_ascii_byte_fallback(s.as_bytes()), + "i: {:?}, align: {:?}, len: {:?}, s: {:?}", + i, + align, + s.len(), + s + ); + } + } + } + + #[test] + #[cfg(target_arch = "x86_64")] + fn negative_sse2_forward() { + for i in 0..517 { + for align in 0..65 { + let mut s = "a".repeat(i); + s.push_str("☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃"); + let s = s.get(align..).unwrap_or(""); + assert_eq!( + i.saturating_sub(align), + first_non_ascii_byte_sse2(s.as_bytes()), + "i: {:?}, align: {:?}, len: {:?}, s: {:?}", + i, + align, + s.len(), + s + ); + } + } + } +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/bstr.rs b/third_party/cargo/vendor/bstr-0.2.15/src/bstr.rs new file mode 100644 index 0000000..1e3c91b --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/bstr.rs @@ -0,0 +1,74 @@ +use core::mem; + +/// A wrapper for `&[u8]` that provides convenient string oriented trait impls. +/// +/// If you need ownership or a growable byte string buffer, then use +/// [`BString`](struct.BString.html). +/// +/// Using a `&BStr` is just like using a `&[u8]`, since `BStr` +/// implements `Deref` to `[u8]`. So all methods available on `[u8]` +/// are also available on `BStr`. +/// +/// # Representation +/// +/// A `&BStr` has the same representation as a `&str`. That is, a `&BStr` is +/// a fat pointer which consists of a pointer to some bytes and a length. +/// +/// # Trait implementations +/// +/// The `BStr` type has a number of trait implementations, and in particular, +/// defines equality and ordinal comparisons between `&BStr`, `&str` and +/// `&[u8]` for convenience. +/// +/// The `Debug` implementation for `BStr` shows its bytes as a normal string. +/// For invalid UTF-8, hex escape sequences are used. +/// +/// The `Display` implementation behaves as if `BStr` were first lossily +/// converted to a `str`. Invalid UTF-8 bytes are substituted with the Unicode +/// replacement codepoint, which looks like this: �. +#[derive(Hash)] +#[repr(transparent)] +pub struct BStr { + pub(crate) bytes: [u8], +} + +impl BStr { + #[inline] + pub(crate) fn new>(bytes: &B) -> &BStr { + BStr::from_bytes(bytes.as_ref()) + } + + #[inline] + pub(crate) fn new_mut>( + bytes: &mut B, + ) -> &mut BStr { + BStr::from_bytes_mut(bytes.as_mut()) + } + + #[inline] + pub(crate) fn from_bytes(slice: &[u8]) -> &BStr { + unsafe { mem::transmute(slice) } + } + + #[inline] + pub(crate) fn from_bytes_mut(slice: &mut [u8]) -> &mut BStr { + unsafe { mem::transmute(slice) } + } + + #[inline] + #[cfg(feature = "std")] + pub(crate) fn from_boxed_bytes(slice: Box<[u8]>) -> Box { + unsafe { Box::from_raw(Box::into_raw(slice) as _) } + } + + #[inline] + #[cfg(feature = "std")] + pub(crate) fn into_boxed_bytes(slice: Box) -> Box<[u8]> { + unsafe { Box::from_raw(Box::into_raw(slice) as _) } + } + + #[inline] + pub(crate) fn as_bytes(&self) -> &[u8] { + &self.bytes + } +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/bstring.rs b/third_party/cargo/vendor/bstr-0.2.15/src/bstring.rs new file mode 100644 index 0000000..f04c651 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/bstring.rs @@ -0,0 +1,59 @@ +use bstr::BStr; + +/// A wrapper for `Vec` that provides convenient string oriented trait +/// impls. +/// +/// A `BString` has ownership over its contents and corresponds to +/// a growable or shrinkable buffer. Its borrowed counterpart is a +/// [`BStr`](struct.BStr.html), called a byte string slice. +/// +/// Using a `BString` is just like using a `Vec`, since `BString` +/// implements `Deref` to `Vec`. So all methods available on `Vec` +/// are also available on `BString`. +/// +/// # Examples +/// +/// You can create a new `BString` from a `Vec` via a `From` impl: +/// +/// ``` +/// use bstr::BString; +/// +/// let s = BString::from("Hello, world!"); +/// ``` +/// +/// # Deref +/// +/// The `BString` type implements `Deref` and `DerefMut`, where the target +/// types are `&Vec` and `&mut Vec`, respectively. `Deref` permits all of the +/// methods defined on `Vec` to be implicitly callable on any `BString`. +/// +/// For more information about how deref works, see the documentation for the +/// [`std::ops::Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html) +/// trait. +/// +/// # Representation +/// +/// A `BString` has the same representation as a `Vec` and a `String`. +/// That is, it is made up of three word sized components: a pointer to a +/// region of memory containing the bytes, a length and a capacity. +#[derive(Clone, Hash)] +pub struct BString { + pub(crate) bytes: Vec, +} + +impl BString { + #[inline] + pub(crate) fn as_bytes(&self) -> &[u8] { + &self.bytes + } + + #[inline] + pub(crate) fn as_bstr(&self) -> &BStr { + BStr::new(&self.bytes) + } + + #[inline] + pub(crate) fn as_mut_bstr(&mut self) -> &mut BStr { + BStr::new_mut(&mut self.bytes) + } +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/byteset/mod.rs b/third_party/cargo/vendor/bstr-0.2.15/src/byteset/mod.rs new file mode 100644 index 0000000..969b0e3 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/byteset/mod.rs @@ -0,0 +1,115 @@ +use memchr::{memchr, memchr2, memchr3, memrchr, memrchr2, memrchr3}; +mod scalar; + +#[inline] +fn build_table(byteset: &[u8]) -> [u8; 256] { + let mut table = [0u8; 256]; + for &b in byteset { + table[b as usize] = 1; + } + table +} + +#[inline] +pub(crate) fn find(haystack: &[u8], byteset: &[u8]) -> Option { + match byteset.len() { + 0 => return None, + 1 => memchr(byteset[0], haystack), + 2 => memchr2(byteset[0], byteset[1], haystack), + 3 => memchr3(byteset[0], byteset[1], byteset[2], haystack), + _ => { + let table = build_table(byteset); + scalar::forward_search_bytes(haystack, |b| table[b as usize] != 0) + } + } +} + +#[inline] +pub(crate) fn rfind(haystack: &[u8], byteset: &[u8]) -> Option { + match byteset.len() { + 0 => return None, + 1 => memrchr(byteset[0], haystack), + 2 => memrchr2(byteset[0], byteset[1], haystack), + 3 => memrchr3(byteset[0], byteset[1], byteset[2], haystack), + _ => { + let table = build_table(byteset); + scalar::reverse_search_bytes(haystack, |b| table[b as usize] != 0) + } + } +} + +#[inline] +pub(crate) fn find_not(haystack: &[u8], byteset: &[u8]) -> Option { + if haystack.is_empty() { + return None; + } + match byteset.len() { + 0 => return Some(0), + 1 => scalar::inv_memchr(byteset[0], haystack), + 2 => scalar::forward_search_bytes(haystack, |b| { + b != byteset[0] && b != byteset[1] + }), + 3 => scalar::forward_search_bytes(haystack, |b| { + b != byteset[0] && b != byteset[1] && b != byteset[2] + }), + _ => { + let table = build_table(byteset); + scalar::forward_search_bytes(haystack, |b| table[b as usize] == 0) + } + } +} +#[inline] +pub(crate) fn rfind_not(haystack: &[u8], byteset: &[u8]) -> Option { + if haystack.is_empty() { + return None; + } + match byteset.len() { + 0 => return Some(haystack.len() - 1), + 1 => scalar::inv_memrchr(byteset[0], haystack), + 2 => scalar::reverse_search_bytes(haystack, |b| { + b != byteset[0] && b != byteset[1] + }), + 3 => scalar::reverse_search_bytes(haystack, |b| { + b != byteset[0] && b != byteset[1] && b != byteset[2] + }), + _ => { + let table = build_table(byteset); + scalar::reverse_search_bytes(haystack, |b| table[b as usize] == 0) + } + } +} + +#[cfg(test)] +mod tests { + + quickcheck! { + fn qc_byteset_forward_matches_naive( + haystack: Vec, + needles: Vec + ) -> bool { + super::find(&haystack, &needles) + == haystack.iter().position(|b| needles.contains(b)) + } + fn qc_byteset_backwards_matches_naive( + haystack: Vec, + needles: Vec + ) -> bool { + super::rfind(&haystack, &needles) + == haystack.iter().rposition(|b| needles.contains(b)) + } + fn qc_byteset_forward_not_matches_naive( + haystack: Vec, + needles: Vec + ) -> bool { + super::find_not(&haystack, &needles) + == haystack.iter().position(|b| !needles.contains(b)) + } + fn qc_byteset_backwards_not_matches_naive( + haystack: Vec, + needles: Vec + ) -> bool { + super::rfind_not(&haystack, &needles) + == haystack.iter().rposition(|b| !needles.contains(b)) + } + } +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/byteset/scalar.rs b/third_party/cargo/vendor/bstr-0.2.15/src/byteset/scalar.rs new file mode 100644 index 0000000..3fe1f53 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/byteset/scalar.rs @@ -0,0 +1,295 @@ +// This is adapted from `fallback.rs` from rust-memchr. It's modified to return +// the 'inverse' query of memchr, e.g. finding the first byte not in the provided +// set. This is simple for the 1-byte case. + +use core::cmp; +use core::usize; + +#[cfg(target_pointer_width = "32")] +const USIZE_BYTES: usize = 4; + +#[cfg(target_pointer_width = "64")] +const USIZE_BYTES: usize = 8; + +// The number of bytes to loop at in one iteration of memchr/memrchr. +const LOOP_SIZE: usize = 2 * USIZE_BYTES; + +/// Repeat the given byte into a word size number. That is, every 8 bits +/// is equivalent to the given byte. For example, if `b` is `\x4E` or +/// `01001110` in binary, then the returned value on a 32-bit system would be: +/// `01001110_01001110_01001110_01001110`. +#[inline(always)] +fn repeat_byte(b: u8) -> usize { + (b as usize) * (usize::MAX / 255) +} + +pub fn inv_memchr(n1: u8, haystack: &[u8]) -> Option { + let vn1 = repeat_byte(n1); + let confirm = |byte| byte != n1; + let loop_size = cmp::min(LOOP_SIZE, haystack.len()); + let align = USIZE_BYTES - 1; + let start_ptr = haystack.as_ptr(); + let end_ptr = haystack[haystack.len()..].as_ptr(); + let mut ptr = start_ptr; + + unsafe { + if haystack.len() < USIZE_BYTES { + return forward_search(start_ptr, end_ptr, ptr, confirm); + } + + let chunk = read_unaligned_usize(ptr); + if (chunk ^ vn1) != 0 { + return forward_search(start_ptr, end_ptr, ptr, confirm); + } + + ptr = ptr.add(USIZE_BYTES - (start_ptr as usize & align)); + debug_assert!(ptr > start_ptr); + debug_assert!(end_ptr.sub(USIZE_BYTES) >= start_ptr); + while loop_size == LOOP_SIZE && ptr <= end_ptr.sub(loop_size) { + debug_assert_eq!(0, (ptr as usize) % USIZE_BYTES); + + let a = *(ptr as *const usize); + let b = *(ptr.add(USIZE_BYTES) as *const usize); + let eqa = (a ^ vn1) != 0; + let eqb = (b ^ vn1) != 0; + if eqa || eqb { + break; + } + ptr = ptr.add(LOOP_SIZE); + } + forward_search(start_ptr, end_ptr, ptr, confirm) + } +} + +/// Return the last index not matching the byte `x` in `text`. +pub fn inv_memrchr(n1: u8, haystack: &[u8]) -> Option { + let vn1 = repeat_byte(n1); + let confirm = |byte| byte != n1; + let loop_size = cmp::min(LOOP_SIZE, haystack.len()); + let align = USIZE_BYTES - 1; + let start_ptr = haystack.as_ptr(); + let end_ptr = haystack[haystack.len()..].as_ptr(); + let mut ptr = end_ptr; + + unsafe { + if haystack.len() < USIZE_BYTES { + return reverse_search(start_ptr, end_ptr, ptr, confirm); + } + + let chunk = read_unaligned_usize(ptr.sub(USIZE_BYTES)); + if (chunk ^ vn1) != 0 { + return reverse_search(start_ptr, end_ptr, ptr, confirm); + } + + ptr = (end_ptr as usize & !align) as *const u8; + debug_assert!(start_ptr <= ptr && ptr <= end_ptr); + while loop_size == LOOP_SIZE && ptr >= start_ptr.add(loop_size) { + debug_assert_eq!(0, (ptr as usize) % USIZE_BYTES); + + let a = *(ptr.sub(2 * USIZE_BYTES) as *const usize); + let b = *(ptr.sub(1 * USIZE_BYTES) as *const usize); + let eqa = (a ^ vn1) != 0; + let eqb = (b ^ vn1) != 0; + if eqa || eqb { + break; + } + ptr = ptr.sub(loop_size); + } + reverse_search(start_ptr, end_ptr, ptr, confirm) + } +} + +#[inline(always)] +unsafe fn forward_search bool>( + start_ptr: *const u8, + end_ptr: *const u8, + mut ptr: *const u8, + confirm: F, +) -> Option { + debug_assert!(start_ptr <= ptr); + debug_assert!(ptr <= end_ptr); + + while ptr < end_ptr { + if confirm(*ptr) { + return Some(sub(ptr, start_ptr)); + } + ptr = ptr.offset(1); + } + None +} + +#[inline(always)] +unsafe fn reverse_search bool>( + start_ptr: *const u8, + end_ptr: *const u8, + mut ptr: *const u8, + confirm: F, +) -> Option { + debug_assert!(start_ptr <= ptr); + debug_assert!(ptr <= end_ptr); + + while ptr > start_ptr { + ptr = ptr.offset(-1); + if confirm(*ptr) { + return Some(sub(ptr, start_ptr)); + } + } + None +} + +unsafe fn read_unaligned_usize(ptr: *const u8) -> usize { + (ptr as *const usize).read_unaligned() +} + +/// Subtract `b` from `a` and return the difference. `a` should be greater than +/// or equal to `b`. +fn sub(a: *const u8, b: *const u8) -> usize { + debug_assert!(a >= b); + (a as usize) - (b as usize) +} + +/// Safe wrapper around `forward_search` +#[inline] +pub(crate) fn forward_search_bytes bool>( + s: &[u8], + confirm: F, +) -> Option { + unsafe { + let start = s.as_ptr(); + let end = start.add(s.len()); + forward_search(start, end, start, confirm) + } +} + +/// Safe wrapper around `reverse_search` +#[inline] +pub(crate) fn reverse_search_bytes bool>( + s: &[u8], + confirm: F, +) -> Option { + unsafe { + let start = s.as_ptr(); + let end = start.add(s.len()); + reverse_search(start, end, end, confirm) + } +} + +#[cfg(test)] +mod tests { + use super::{inv_memchr, inv_memrchr}; + // search string, search byte, inv_memchr result, inv_memrchr result. + // these are expanded into a much larger set of tests in build_tests + const TESTS: &[(&[u8], u8, usize, usize)] = &[ + (b"z", b'a', 0, 0), + (b"zz", b'a', 0, 1), + (b"aza", b'a', 1, 1), + (b"zaz", b'a', 0, 2), + (b"zza", b'a', 0, 1), + (b"zaa", b'a', 0, 0), + (b"zzz", b'a', 0, 2), + ]; + + type TestCase = (Vec, u8, Option<(usize, usize)>); + + fn build_tests() -> Vec { + let mut result = vec![]; + for &(search, byte, fwd_pos, rev_pos) in TESTS { + result.push((search.to_vec(), byte, Some((fwd_pos, rev_pos)))); + for i in 1..515 { + // add a bunch of copies of the search byte to the end. + let mut suffixed: Vec = search.into(); + suffixed.extend(std::iter::repeat(byte).take(i)); + result.push((suffixed, byte, Some((fwd_pos, rev_pos)))); + + // add a bunch of copies of the search byte to the start. + let mut prefixed: Vec = + std::iter::repeat(byte).take(i).collect(); + prefixed.extend(search); + result.push(( + prefixed, + byte, + Some((fwd_pos + i, rev_pos + i)), + )); + + // add a bunch of copies of the search byte to both ends. + let mut surrounded: Vec = + std::iter::repeat(byte).take(i).collect(); + surrounded.extend(search); + surrounded.extend(std::iter::repeat(byte).take(i)); + result.push(( + surrounded, + byte, + Some((fwd_pos + i, rev_pos + i)), + )); + } + } + + // build non-matching tests for several sizes + for i in 0..515 { + result.push(( + std::iter::repeat(b'\0').take(i).collect(), + b'\0', + None, + )); + } + + result + } + + #[test] + fn test_inv_memchr() { + use {ByteSlice, B}; + for (search, byte, matching) in build_tests() { + assert_eq!( + inv_memchr(byte, &search), + matching.map(|m| m.0), + "inv_memchr when searching for {:?} in {:?}", + byte as char, + // better printing + B(&search).as_bstr(), + ); + assert_eq!( + inv_memrchr(byte, &search), + matching.map(|m| m.1), + "inv_memrchr when searching for {:?} in {:?}", + byte as char, + // better printing + B(&search).as_bstr(), + ); + // Test a rather large number off offsets for potential alignment issues + for offset in 1..130 { + if offset >= search.len() { + break; + } + // If this would cause us to shift the results off the end, skip + // it so that we don't have to recompute them. + if let Some((f, r)) = matching { + if offset > f || offset > r { + break; + } + } + let realigned = &search[offset..]; + + let forward_pos = matching.map(|m| m.0 - offset); + let reverse_pos = matching.map(|m| m.1 - offset); + + assert_eq!( + inv_memchr(byte, &realigned), + forward_pos, + "inv_memchr when searching (realigned by {}) for {:?} in {:?}", + offset, + byte as char, + realigned.as_bstr(), + ); + assert_eq!( + inv_memrchr(byte, &realigned), + reverse_pos, + "inv_memrchr when searching (realigned by {}) for {:?} in {:?}", + offset, + byte as char, + realigned.as_bstr(), + ); + } + } + } +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/cow.rs b/third_party/cargo/vendor/bstr-0.2.15/src/cow.rs new file mode 100644 index 0000000..1556353 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/cow.rs @@ -0,0 +1,84 @@ +use core::ops; +#[cfg(feature = "std")] +use std::borrow::Cow; + +/// A specialized copy-on-write byte string. +/// +/// The purpose of this type is to permit usage of a "borrowed or owned +/// byte string" in a way that keeps std/no-std compatibility. That is, in +/// no-std mode, this type devolves into a simple &[u8] with no owned variant +/// availble. +#[derive(Clone, Debug)] +pub struct CowBytes<'a>(Imp<'a>); + +#[cfg(feature = "std")] +#[derive(Clone, Debug)] +struct Imp<'a>(Cow<'a, [u8]>); + +#[cfg(not(feature = "std"))] +#[derive(Clone, Debug)] +struct Imp<'a>(&'a [u8]); + +impl<'a> ops::Deref for CowBytes<'a> { + type Target = [u8]; + + fn deref(&self) -> &[u8] { + self.as_slice() + } +} + +impl<'a> CowBytes<'a> { + /// Create a new borrowed CowBytes. + pub fn new>(bytes: &'a B) -> CowBytes<'a> { + CowBytes(Imp::new(bytes.as_ref())) + } + + /// Create a new owned CowBytes. + #[cfg(feature = "std")] + pub fn new_owned(bytes: Vec) -> CowBytes<'static> { + CowBytes(Imp(Cow::Owned(bytes))) + } + + /// Return a borrowed byte string, regardless of whether this is an owned + /// or borrowed byte string internally. + pub fn as_slice(&self) -> &[u8] { + self.0.as_slice() + } + + /// Return an owned version of this copy-on-write byte string. + /// + /// If this is already an owned byte string internally, then this is a + /// no-op. Otherwise, the internal byte string is copied. + #[cfg(feature = "std")] + pub fn into_owned(self) -> CowBytes<'static> { + match (self.0).0 { + Cow::Borrowed(b) => CowBytes::new_owned(b.to_vec()), + Cow::Owned(b) => CowBytes::new_owned(b), + } + } +} + +impl<'a> Imp<'a> { + #[cfg(feature = "std")] + pub fn new(bytes: &'a [u8]) -> Imp<'a> { + Imp(Cow::Borrowed(bytes)) + } + + #[cfg(not(feature = "std"))] + pub fn new(bytes: &'a [u8]) -> Imp<'a> { + Imp(bytes) + } + + #[cfg(feature = "std")] + pub fn as_slice(&self) -> &[u8] { + match self.0 { + Cow::Owned(ref x) => x, + Cow::Borrowed(x) => x, + } + } + + #[cfg(not(feature = "std"))] + pub fn as_slice(&self) -> &[u8] { + self.0 + } +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/ext_slice.rs b/third_party/cargo/vendor/bstr-0.2.15/src/ext_slice.rs new file mode 100644 index 0000000..fa08190 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/ext_slice.rs @@ -0,0 +1,3695 @@ +#[cfg(feature = "std")] +use std::borrow::Cow; +#[cfg(feature = "std")] +use std::ffi::OsStr; +#[cfg(feature = "std")] +use std::path::Path; + +use core::{cmp, iter, ops, ptr, slice, str}; +use memchr::{memchr, memrchr}; + +use ascii; +use bstr::BStr; +use byteset; +#[cfg(feature = "std")] +use ext_vec::ByteVec; +use search::{PrefilterState, TwoWay}; +#[cfg(feature = "unicode")] +use unicode::{ + whitespace_len_fwd, whitespace_len_rev, GraphemeIndices, Graphemes, + SentenceIndices, Sentences, WordIndices, Words, WordsWithBreakIndices, + WordsWithBreaks, +}; +use utf8::{self, CharIndices, Chars, Utf8Chunks, Utf8Error}; + +/// A short-hand constructor for building a `&[u8]`. +/// +/// This idiosyncratic constructor is useful for concisely building byte string +/// slices. Its primary utility is in conveniently writing byte string literals +/// in a uniform way. For example, consider this code that does not compile: +/// +/// ```ignore +/// let strs = vec![b"a", b"xy"]; +/// ``` +/// +/// The above code doesn't compile because the type of the byte string literal +/// `b"a"` is `&'static [u8; 1]`, and the type of `b"xy"` is +/// `&'static [u8; 2]`. Since their types aren't the same, they can't be stored +/// in the same `Vec`. (This is dissimilar from normal Unicode string slices, +/// where both `"a"` and `"xy"` have the same type of `&'static str`.) +/// +/// One way of getting the above code to compile is to convert byte strings to +/// slices. You might try this: +/// +/// ```ignore +/// let strs = vec![&b"a", &b"xy"]; +/// ``` +/// +/// But this just creates values with type `& &'static [u8; 1]` and +/// `& &'static [u8; 2]`. Instead, you need to force the issue like so: +/// +/// ``` +/// let strs = vec![&b"a"[..], &b"xy"[..]]; +/// // or +/// let strs = vec![b"a".as_ref(), b"xy".as_ref()]; +/// ``` +/// +/// But neither of these are particularly convenient to type, especially when +/// it's something as common as a string literal. Thus, this constructor +/// permits writing the following instead: +/// +/// ``` +/// use bstr::B; +/// +/// let strs = vec![B("a"), B(b"xy")]; +/// ``` +/// +/// Notice that this also lets you mix and match both string literals and byte +/// string literals. This can be quite convenient! +#[allow(non_snake_case)] +#[inline] +pub fn B<'a, B: ?Sized + AsRef<[u8]>>(bytes: &'a B) -> &'a [u8] { + bytes.as_ref() +} + +impl ByteSlice for [u8] { + #[inline] + fn as_bytes(&self) -> &[u8] { + self + } + + #[inline] + fn as_bytes_mut(&mut self) -> &mut [u8] { + self + } +} + +/// Ensure that callers cannot implement `ByteSlice` by making an +/// umplementable trait its super trait. +pub trait Sealed {} +impl Sealed for [u8] {} + +/// A trait that extends `&[u8]` with string oriented methods. +pub trait ByteSlice: Sealed { + /// A method for accessing the raw bytes of this type. This is always a + /// no-op and callers shouldn't care about it. This only exists for making + /// the extension trait work. + #[doc(hidden)] + fn as_bytes(&self) -> &[u8]; + + /// A method for accessing the raw bytes of this type, mutably. This is + /// always a no-op and callers shouldn't care about it. This only exists + /// for making the extension trait work. + #[doc(hidden)] + fn as_bytes_mut(&mut self) -> &mut [u8]; + + /// Return this byte slice as a `&BStr`. + /// + /// Use `&BStr` is useful because of its `fmt::Debug` representation + /// and various other trait implementations (such as `PartialEq` and + /// `PartialOrd`). In particular, the `Debug` implementation for `BStr` + /// shows its bytes as a normal string. For invalid UTF-8, hex escape + /// sequences are used. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// println!("{:?}", b"foo\xFFbar".as_bstr()); + /// ``` + #[inline] + fn as_bstr(&self) -> &BStr { + BStr::new(self.as_bytes()) + } + + /// Return this byte slice as a `&mut BStr`. + /// + /// Use `&mut BStr` is useful because of its `fmt::Debug` representation + /// and various other trait implementations (such as `PartialEq` and + /// `PartialOrd`). In particular, the `Debug` implementation for `BStr` + /// shows its bytes as a normal string. For invalid UTF-8, hex escape + /// sequences are used. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let mut bytes = *b"foo\xFFbar"; + /// println!("{:?}", &mut bytes.as_bstr_mut()); + /// ``` + #[inline] + fn as_bstr_mut(&mut self) -> &mut BStr { + BStr::new_mut(self.as_bytes_mut()) + } + + /// Create an immutable byte string from an OS string slice. + /// + /// On Unix, this always succeeds and is zero cost. On non-Unix systems, + /// this returns `None` if the given OS string is not valid UTF-8. (For + /// example, on Windows, file paths are allowed to be a sequence of + /// arbitrary 16-bit integers. Not all such sequences can be transcoded to + /// valid UTF-8.) + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::ffi::OsStr; + /// + /// use bstr::{B, ByteSlice}; + /// + /// let os_str = OsStr::new("foo"); + /// let bs = <[u8]>::from_os_str(os_str).expect("should be valid UTF-8"); + /// assert_eq!(bs, B("foo")); + /// ``` + #[cfg(feature = "std")] + #[inline] + fn from_os_str(os_str: &OsStr) -> Option<&[u8]> { + #[cfg(unix)] + #[inline] + fn imp(os_str: &OsStr) -> Option<&[u8]> { + use std::os::unix::ffi::OsStrExt; + + Some(os_str.as_bytes()) + } + + #[cfg(not(unix))] + #[inline] + fn imp(os_str: &OsStr) -> Option<&[u8]> { + os_str.to_str().map(|s| s.as_bytes()) + } + + imp(os_str) + } + + /// Create an immutable byte string from a file path. + /// + /// On Unix, this always succeeds and is zero cost. On non-Unix systems, + /// this returns `None` if the given path is not valid UTF-8. (For example, + /// on Windows, file paths are allowed to be a sequence of arbitrary 16-bit + /// integers. Not all such sequences can be transcoded to valid UTF-8.) + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::path::Path; + /// + /// use bstr::{B, ByteSlice}; + /// + /// let path = Path::new("foo"); + /// let bs = <[u8]>::from_path(path).expect("should be valid UTF-8"); + /// assert_eq!(bs, B("foo")); + /// ``` + #[cfg(feature = "std")] + #[inline] + fn from_path(path: &Path) -> Option<&[u8]> { + Self::from_os_str(path.as_os_str()) + } + + /// Safely convert this byte string into a `&str` if it's valid UTF-8. + /// + /// If this byte string is not valid UTF-8, then an error is returned. The + /// error returned indicates the first invalid byte found and the length + /// of the error. + /// + /// In cases where a lossy conversion to `&str` is acceptable, then use one + /// of the [`to_str_lossy`](trait.ByteSlice.html#method.to_str_lossy) or + /// [`to_str_lossy_into`](trait.ByteSlice.html#method.to_str_lossy_into) + /// methods. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteSlice, ByteVec}; + /// + /// # fn example() -> Result<(), bstr::Utf8Error> { + /// let s = B("☃βツ").to_str()?; + /// assert_eq!("☃βツ", s); + /// + /// let mut bstring = >::from("☃βツ"); + /// bstring.push(b'\xFF'); + /// let err = bstring.to_str().unwrap_err(); + /// assert_eq!(8, err.valid_up_to()); + /// # Ok(()) }; example().unwrap() + /// ``` + #[inline] + fn to_str(&self) -> Result<&str, Utf8Error> { + utf8::validate(self.as_bytes()).map(|_| { + // SAFETY: This is safe because of the guarantees provided by + // utf8::validate. + unsafe { str::from_utf8_unchecked(self.as_bytes()) } + }) + } + + /// Unsafely convert this byte string into a `&str`, without checking for + /// valid UTF-8. + /// + /// # Safety + /// + /// Callers *must* ensure that this byte string is valid UTF-8 before + /// calling this method. Converting a byte string into a `&str` that is + /// not valid UTF-8 is considered undefined behavior. + /// + /// This routine is useful in performance sensitive contexts where the + /// UTF-8 validity of the byte string is already known and it is + /// undesirable to pay the cost of an additional UTF-8 validation check + /// that [`to_str`](trait.ByteSlice.html#method.to_str) performs. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// // SAFETY: This is safe because string literals are guaranteed to be + /// // valid UTF-8 by the Rust compiler. + /// let s = unsafe { B("☃βツ").to_str_unchecked() }; + /// assert_eq!("☃βツ", s); + /// ``` + #[inline] + unsafe fn to_str_unchecked(&self) -> &str { + str::from_utf8_unchecked(self.as_bytes()) + } + + /// Convert this byte string to a valid UTF-8 string by replacing invalid + /// UTF-8 bytes with the Unicode replacement codepoint (`U+FFFD`). + /// + /// If the byte string is already valid UTF-8, then no copying or + /// allocation is performed and a borrrowed string slice is returned. If + /// the byte string is not valid UTF-8, then an owned string buffer is + /// returned with invalid bytes replaced by the replacement codepoint. + /// + /// This method uses the "substitution of maximal subparts" (Unicode + /// Standard, Chapter 3, Section 9) strategy for inserting the replacement + /// codepoint. Specifically, a replacement codepoint is inserted whenever a + /// byte is found that cannot possibly lead to a valid code unit sequence. + /// If there were previous bytes that represented a prefix of a well-formed + /// code unit sequence, then all of those bytes are substituted with a + /// single replacement codepoint. The "substitution of maximal subparts" + /// strategy is the same strategy used by + /// [W3C's Encoding standard](https://www.w3.org/TR/encoding/). + /// For a more precise description of the maximal subpart strategy, see + /// the Unicode Standard, Chapter 3, Section 9. See also + /// [Public Review Issue #121](http://www.unicode.org/review/pr-121.html). + /// + /// N.B. Rust's standard library also appears to use the same strategy, + /// but it does not appear to be an API guarantee. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::borrow::Cow; + /// + /// use bstr::ByteSlice; + /// + /// let mut bstring = >::from("☃βツ"); + /// assert_eq!(Cow::Borrowed("☃βツ"), bstring.to_str_lossy()); + /// + /// // Add a byte that makes the sequence invalid. + /// bstring.push(b'\xFF'); + /// assert_eq!(Cow::Borrowed("☃βツ\u{FFFD}"), bstring.to_str_lossy()); + /// ``` + /// + /// This demonstrates the "maximal subpart" substitution logic. + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// // \x61 is the ASCII codepoint for 'a'. + /// // \xF1\x80\x80 is a valid 3-byte code unit prefix. + /// // \xE1\x80 is a valid 2-byte code unit prefix. + /// // \xC2 is a valid 1-byte code unit prefix. + /// // \x62 is the ASCII codepoint for 'b'. + /// // + /// // In sum, each of the prefixes is replaced by a single replacement + /// // codepoint since none of the prefixes are properly completed. This + /// // is in contrast to other strategies that might insert a replacement + /// // codepoint for every single byte. + /// let bs = B(b"\x61\xF1\x80\x80\xE1\x80\xC2\x62"); + /// assert_eq!("a\u{FFFD}\u{FFFD}\u{FFFD}b", bs.to_str_lossy()); + /// ``` + #[cfg(feature = "std")] + #[inline] + fn to_str_lossy(&self) -> Cow { + match utf8::validate(self.as_bytes()) { + Ok(()) => { + // SAFETY: This is safe because of the guarantees provided by + // utf8::validate. + unsafe { + Cow::Borrowed(str::from_utf8_unchecked(self.as_bytes())) + } + } + Err(err) => { + let mut lossy = String::with_capacity(self.as_bytes().len()); + let (valid, after) = + self.as_bytes().split_at(err.valid_up_to()); + // SAFETY: This is safe because utf8::validate guarantees + // that all of `valid` is valid UTF-8. + lossy.push_str(unsafe { str::from_utf8_unchecked(valid) }); + lossy.push_str("\u{FFFD}"); + if let Some(len) = err.error_len() { + after[len..].to_str_lossy_into(&mut lossy); + } + Cow::Owned(lossy) + } + } + } + + /// Copy the contents of this byte string into the given owned string + /// buffer, while replacing invalid UTF-8 code unit sequences with the + /// Unicode replacement codepoint (`U+FFFD`). + /// + /// This method uses the same "substitution of maximal subparts" strategy + /// for inserting the replacement codepoint as the + /// [`to_str_lossy`](trait.ByteSlice.html#method.to_str_lossy) method. + /// + /// This routine is useful for amortizing allocation. However, unlike + /// `to_str_lossy`, this routine will _always_ copy the contents of this + /// byte string into the destination buffer, even if this byte string is + /// valid UTF-8. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::borrow::Cow; + /// + /// use bstr::ByteSlice; + /// + /// let mut bstring = >::from("☃βツ"); + /// // Add a byte that makes the sequence invalid. + /// bstring.push(b'\xFF'); + /// + /// let mut dest = String::new(); + /// bstring.to_str_lossy_into(&mut dest); + /// assert_eq!("☃βツ\u{FFFD}", dest); + /// ``` + #[cfg(feature = "std")] + #[inline] + fn to_str_lossy_into(&self, dest: &mut String) { + let mut bytes = self.as_bytes(); + dest.reserve(bytes.len()); + loop { + match utf8::validate(bytes) { + Ok(()) => { + // SAFETY: This is safe because utf8::validate guarantees + // that all of `bytes` is valid UTF-8. + dest.push_str(unsafe { str::from_utf8_unchecked(bytes) }); + break; + } + Err(err) => { + let (valid, after) = bytes.split_at(err.valid_up_to()); + // SAFETY: This is safe because utf8::validate guarantees + // that all of `valid` is valid UTF-8. + dest.push_str(unsafe { str::from_utf8_unchecked(valid) }); + dest.push_str("\u{FFFD}"); + match err.error_len() { + None => break, + Some(len) => bytes = &after[len..], + } + } + } + } + } + + /// Create an OS string slice from this byte string. + /// + /// On Unix, this always succeeds and is zero cost. On non-Unix systems, + /// this returns a UTF-8 decoding error if this byte string is not valid + /// UTF-8. (For example, on Windows, file paths are allowed to be a + /// sequence of arbitrary 16-bit integers. There is no obvious mapping from + /// an arbitrary sequence of 8-bit integers to an arbitrary sequence of + /// 16-bit integers.) + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let os_str = b"foo".to_os_str().expect("should be valid UTF-8"); + /// assert_eq!(os_str, "foo"); + /// ``` + #[cfg(feature = "std")] + #[inline] + fn to_os_str(&self) -> Result<&OsStr, Utf8Error> { + #[cfg(unix)] + #[inline] + fn imp(bytes: &[u8]) -> Result<&OsStr, Utf8Error> { + use std::os::unix::ffi::OsStrExt; + + Ok(OsStr::from_bytes(bytes)) + } + + #[cfg(not(unix))] + #[inline] + fn imp(bytes: &[u8]) -> Result<&OsStr, Utf8Error> { + bytes.to_str().map(OsStr::new) + } + + imp(self.as_bytes()) + } + + /// Lossily create an OS string slice from this byte string. + /// + /// On Unix, this always succeeds and is zero cost. On non-Unix systems, + /// this will perform a UTF-8 check and lossily convert this byte string + /// into valid UTF-8 using the Unicode replacement codepoint. + /// + /// Note that this can prevent the correct roundtripping of file paths on + /// non-Unix systems such as Windows, where file paths are an arbitrary + /// sequence of 16-bit integers. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let os_str = b"foo\xFFbar".to_os_str_lossy(); + /// assert_eq!(os_str.to_string_lossy(), "foo\u{FFFD}bar"); + /// ``` + #[cfg(feature = "std")] + #[inline] + fn to_os_str_lossy(&self) -> Cow { + #[cfg(unix)] + #[inline] + fn imp(bytes: &[u8]) -> Cow { + use std::os::unix::ffi::OsStrExt; + + Cow::Borrowed(OsStr::from_bytes(bytes)) + } + + #[cfg(not(unix))] + #[inline] + fn imp(bytes: &[u8]) -> Cow { + use std::ffi::OsString; + + match bytes.to_str_lossy() { + Cow::Borrowed(x) => Cow::Borrowed(OsStr::new(x)), + Cow::Owned(x) => Cow::Owned(OsString::from(x)), + } + } + + imp(self.as_bytes()) + } + + /// Create a path slice from this byte string. + /// + /// On Unix, this always succeeds and is zero cost. On non-Unix systems, + /// this returns a UTF-8 decoding error if this byte string is not valid + /// UTF-8. (For example, on Windows, file paths are allowed to be a + /// sequence of arbitrary 16-bit integers. There is no obvious mapping from + /// an arbitrary sequence of 8-bit integers to an arbitrary sequence of + /// 16-bit integers.) + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let path = b"foo".to_path().expect("should be valid UTF-8"); + /// assert_eq!(path.as_os_str(), "foo"); + /// ``` + #[cfg(feature = "std")] + #[inline] + fn to_path(&self) -> Result<&Path, Utf8Error> { + self.to_os_str().map(Path::new) + } + + /// Lossily create a path slice from this byte string. + /// + /// On Unix, this always succeeds and is zero cost. On non-Unix systems, + /// this will perform a UTF-8 check and lossily convert this byte string + /// into valid UTF-8 using the Unicode replacement codepoint. + /// + /// Note that this can prevent the correct roundtripping of file paths on + /// non-Unix systems such as Windows, where file paths are an arbitrary + /// sequence of 16-bit integers. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let bs = b"foo\xFFbar"; + /// let path = bs.to_path_lossy(); + /// assert_eq!(path.to_string_lossy(), "foo\u{FFFD}bar"); + /// ``` + #[cfg(feature = "std")] + #[inline] + fn to_path_lossy(&self) -> Cow { + use std::path::PathBuf; + + match self.to_os_str_lossy() { + Cow::Borrowed(x) => Cow::Borrowed(Path::new(x)), + Cow::Owned(x) => Cow::Owned(PathBuf::from(x)), + } + } + + /// Create a new byte string by repeating this byte string `n` times. + /// + /// # Panics + /// + /// This function panics if the capacity of the new byte string would + /// overflow. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// assert_eq!(b"foo".repeatn(4), B("foofoofoofoo")); + /// assert_eq!(b"foo".repeatn(0), B("")); + /// ``` + #[cfg(feature = "std")] + #[inline] + fn repeatn(&self, n: usize) -> Vec { + let bs = self.as_bytes(); + let mut dst = vec![0; bs.len() * n]; + for i in 0..n { + dst[i * bs.len()..(i + 1) * bs.len()].copy_from_slice(bs); + } + dst + } + + /// Returns true if and only if this byte string contains the given needle. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// assert!(b"foo bar".contains_str("foo")); + /// assert!(b"foo bar".contains_str("bar")); + /// assert!(!b"foo".contains_str("foobar")); + /// ``` + #[inline] + fn contains_str>(&self, needle: B) -> bool { + self.find(needle).is_some() + } + + /// Returns true if and only if this byte string has the given prefix. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// assert!(b"foo bar".starts_with_str("foo")); + /// assert!(!b"foo bar".starts_with_str("bar")); + /// assert!(!b"foo".starts_with_str("foobar")); + /// ``` + #[inline] + fn starts_with_str>(&self, prefix: B) -> bool { + self.as_bytes().starts_with(prefix.as_ref()) + } + + /// Returns true if and only if this byte string has the given suffix. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// assert!(b"foo bar".ends_with_str("bar")); + /// assert!(!b"foo bar".ends_with_str("foo")); + /// assert!(!b"bar".ends_with_str("foobar")); + /// ``` + #[inline] + fn ends_with_str>(&self, suffix: B) -> bool { + self.as_bytes().ends_with(suffix.as_ref()) + } + + /// Returns the index of the first occurrence of the given needle. + /// + /// The needle may be any type that can be cheaply converted into a + /// `&[u8]`. This includes, but is not limited to, `&str` and `&[u8]`. + /// + /// Note that if you're are searching for the same needle in many + /// different small haystacks, it may be faster to initialize a + /// [`Finder`](struct.Finder.html) once, and reuse it for each search. + /// + /// # Complexity + /// + /// This routine is guaranteed to have worst case linear time complexity + /// with respect to both the needle and the haystack. That is, this runs + /// in `O(needle.len() + haystack.len())` time. + /// + /// This routine is also guaranteed to have worst case constant space + /// complexity. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let s = b"foo bar baz"; + /// assert_eq!(Some(0), s.find("foo")); + /// assert_eq!(Some(4), s.find("bar")); + /// assert_eq!(None, s.find("quux")); + /// ``` + #[inline] + fn find>(&self, needle: B) -> Option { + Finder::new(needle.as_ref()).find(self.as_bytes()) + } + + /// Returns the index of the last occurrence of the given needle. + /// + /// The needle may be any type that can be cheaply converted into a + /// `&[u8]`. This includes, but is not limited to, `&str` and `&[u8]`. + /// + /// Note that if you're are searching for the same needle in many + /// different small haystacks, it may be faster to initialize a + /// [`FinderReverse`](struct.FinderReverse.html) once, and reuse it for + /// each search. + /// + /// # Complexity + /// + /// This routine is guaranteed to have worst case linear time complexity + /// with respect to both the needle and the haystack. That is, this runs + /// in `O(needle.len() + haystack.len())` time. + /// + /// This routine is also guaranteed to have worst case constant space + /// complexity. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let s = b"foo bar baz"; + /// assert_eq!(Some(0), s.rfind("foo")); + /// assert_eq!(Some(4), s.rfind("bar")); + /// assert_eq!(Some(8), s.rfind("ba")); + /// assert_eq!(None, s.rfind("quux")); + /// ``` + #[inline] + fn rfind>(&self, needle: B) -> Option { + FinderReverse::new(needle.as_ref()).rfind(self.as_bytes()) + } + + /// Returns an iterator of the non-overlapping occurrences of the given + /// needle. The iterator yields byte offset positions indicating the start + /// of each match. + /// + /// # Complexity + /// + /// This routine is guaranteed to have worst case linear time complexity + /// with respect to both the needle and the haystack. That is, this runs + /// in `O(needle.len() + haystack.len())` time. + /// + /// This routine is also guaranteed to have worst case constant space + /// complexity. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let s = b"foo bar foo foo quux foo"; + /// let matches: Vec = s.find_iter("foo").collect(); + /// assert_eq!(matches, vec![0, 8, 12, 21]); + /// ``` + /// + /// An empty string matches at every position, including the position + /// immediately following the last byte: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let matches: Vec = b"foo".find_iter("").collect(); + /// assert_eq!(matches, vec![0, 1, 2, 3]); + /// + /// let matches: Vec = b"".find_iter("").collect(); + /// assert_eq!(matches, vec![0]); + /// ``` + #[inline] + fn find_iter<'a, B: ?Sized + AsRef<[u8]>>( + &'a self, + needle: &'a B, + ) -> Find<'a> { + Find::new(self.as_bytes(), needle.as_ref()) + } + + /// Returns an iterator of the non-overlapping occurrences of the given + /// needle in reverse. The iterator yields byte offset positions indicating + /// the start of each match. + /// + /// # Complexity + /// + /// This routine is guaranteed to have worst case linear time complexity + /// with respect to both the needle and the haystack. That is, this runs + /// in `O(needle.len() + haystack.len())` time. + /// + /// This routine is also guaranteed to have worst case constant space + /// complexity. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let s = b"foo bar foo foo quux foo"; + /// let matches: Vec = s.rfind_iter("foo").collect(); + /// assert_eq!(matches, vec![21, 12, 8, 0]); + /// ``` + /// + /// An empty string matches at every position, including the position + /// immediately following the last byte: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let matches: Vec = b"foo".rfind_iter("").collect(); + /// assert_eq!(matches, vec![3, 2, 1, 0]); + /// + /// let matches: Vec = b"".rfind_iter("").collect(); + /// assert_eq!(matches, vec![0]); + /// ``` + #[inline] + fn rfind_iter<'a, B: ?Sized + AsRef<[u8]>>( + &'a self, + needle: &'a B, + ) -> FindReverse<'a> { + FindReverse::new(self.as_bytes(), needle.as_ref()) + } + + /// Returns the index of the first occurrence of the given byte. If the + /// byte does not occur in this byte string, then `None` is returned. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// assert_eq!(Some(10), b"foo bar baz".find_byte(b'z')); + /// assert_eq!(None, b"foo bar baz".find_byte(b'y')); + /// ``` + #[inline] + fn find_byte(&self, byte: u8) -> Option { + memchr(byte, self.as_bytes()) + } + + /// Returns the index of the last occurrence of the given byte. If the + /// byte does not occur in this byte string, then `None` is returned. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// assert_eq!(Some(10), b"foo bar baz".rfind_byte(b'z')); + /// assert_eq!(None, b"foo bar baz".rfind_byte(b'y')); + /// ``` + #[inline] + fn rfind_byte(&self, byte: u8) -> Option { + memrchr(byte, self.as_bytes()) + } + + /// Returns the index of the first occurrence of the given codepoint. + /// If the codepoint does not occur in this byte string, then `None` is + /// returned. + /// + /// Note that if one searches for the replacement codepoint, `\u{FFFD}`, + /// then only explicit occurrences of that encoding will be found. Invalid + /// UTF-8 sequences will not be matched. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// assert_eq!(Some(10), b"foo bar baz".find_char('z')); + /// assert_eq!(Some(4), B("αβγγδ").find_char('γ')); + /// assert_eq!(None, b"foo bar baz".find_char('y')); + /// ``` + #[inline] + fn find_char(&self, ch: char) -> Option { + self.find(ch.encode_utf8(&mut [0; 4])) + } + + /// Returns the index of the last occurrence of the given codepoint. + /// If the codepoint does not occur in this byte string, then `None` is + /// returned. + /// + /// Note that if one searches for the replacement codepoint, `\u{FFFD}`, + /// then only explicit occurrences of that encoding will be found. Invalid + /// UTF-8 sequences will not be matched. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// assert_eq!(Some(10), b"foo bar baz".rfind_char('z')); + /// assert_eq!(Some(6), B("αβγγδ").rfind_char('γ')); + /// assert_eq!(None, b"foo bar baz".rfind_char('y')); + /// ``` + #[inline] + fn rfind_char(&self, ch: char) -> Option { + self.rfind(ch.encode_utf8(&mut [0; 4])) + } + + /// Returns the index of the first occurrence of any of the bytes in the + /// provided set. + /// + /// The `byteset` may be any type that can be cheaply converted into a + /// `&[u8]`. This includes, but is not limited to, `&str` and `&[u8]`, but + /// note that passing a `&str` which contains multibyte characters may not + /// behave as you expect: each byte in the `&str` is treated as an + /// individual member of the byte set. + /// + /// Note that order is irrelevant for the `byteset` parameter, and + /// duplicate bytes present in its body are ignored. + /// + /// # Complexity + /// + /// This routine is guaranteed to have worst case linear time complexity + /// with respect to both the set of bytes and the haystack. That is, this + /// runs in `O(byteset.len() + haystack.len())` time. + /// + /// This routine is also guaranteed to have worst case constant space + /// complexity. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// assert_eq!(b"foo bar baz".find_byteset(b"zr"), Some(6)); + /// assert_eq!(b"foo baz bar".find_byteset(b"bzr"), Some(4)); + /// assert_eq!(None, b"foo baz bar".find_byteset(b"\t\n")); + /// ``` + #[inline] + fn find_byteset>(&self, byteset: B) -> Option { + byteset::find(self.as_bytes(), byteset.as_ref()) + } + + /// Returns the index of the first occurrence of a byte that is not a member + /// of the provided set. + /// + /// The `byteset` may be any type that can be cheaply converted into a + /// `&[u8]`. This includes, but is not limited to, `&str` and `&[u8]`, but + /// note that passing a `&str` which contains multibyte characters may not + /// behave as you expect: each byte in the `&str` is treated as an + /// individual member of the byte set. + /// + /// Note that order is irrelevant for the `byteset` parameter, and + /// duplicate bytes present in its body are ignored. + /// + /// # Complexity + /// + /// This routine is guaranteed to have worst case linear time complexity + /// with respect to both the set of bytes and the haystack. That is, this + /// runs in `O(byteset.len() + haystack.len())` time. + /// + /// This routine is also guaranteed to have worst case constant space + /// complexity. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// assert_eq!(b"foo bar baz".find_not_byteset(b"fo "), Some(4)); + /// assert_eq!(b"\t\tbaz bar".find_not_byteset(b" \t\r\n"), Some(2)); + /// assert_eq!(b"foo\nbaz\tbar".find_not_byteset(b"\t\n"), Some(0)); + /// ``` + #[inline] + fn find_not_byteset>(&self, byteset: B) -> Option { + byteset::find_not(self.as_bytes(), byteset.as_ref()) + } + + /// Returns the index of the last occurrence of any of the bytes in the + /// provided set. + /// + /// The `byteset` may be any type that can be cheaply converted into a + /// `&[u8]`. This includes, but is not limited to, `&str` and `&[u8]`, but + /// note that passing a `&str` which contains multibyte characters may not + /// behave as you expect: each byte in the `&str` is treated as an + /// individual member of the byte set. + /// + /// Note that order is irrelevant for the `byteset` parameter, and duplicate + /// bytes present in its body are ignored. + /// + /// # Complexity + /// + /// This routine is guaranteed to have worst case linear time complexity + /// with respect to both the set of bytes and the haystack. That is, this + /// runs in `O(byteset.len() + haystack.len())` time. + /// + /// This routine is also guaranteed to have worst case constant space + /// complexity. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// assert_eq!(b"foo bar baz".rfind_byteset(b"agb"), Some(9)); + /// assert_eq!(b"foo baz bar".rfind_byteset(b"rabz "), Some(10)); + /// assert_eq!(b"foo baz bar".rfind_byteset(b"\n123"), None); + /// ``` + #[inline] + fn rfind_byteset>(&self, byteset: B) -> Option { + byteset::rfind(self.as_bytes(), byteset.as_ref()) + } + + /// Returns the index of the last occurrence of a byte that is not a member + /// of the provided set. + /// + /// The `byteset` may be any type that can be cheaply converted into a + /// `&[u8]`. This includes, but is not limited to, `&str` and `&[u8]`, but + /// note that passing a `&str` which contains multibyte characters may not + /// behave as you expect: each byte in the `&str` is treated as an + /// individual member of the byte set. + /// + /// Note that order is irrelevant for the `byteset` parameter, and + /// duplicate bytes present in its body are ignored. + /// + /// # Complexity + /// + /// This routine is guaranteed to have worst case linear time complexity + /// with respect to both the set of bytes and the haystack. That is, this + /// runs in `O(byteset.len() + haystack.len())` time. + /// + /// This routine is also guaranteed to have worst case constant space + /// complexity. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// assert_eq!(b"foo bar baz,\t".rfind_not_byteset(b",\t"), Some(10)); + /// assert_eq!(b"foo baz bar".rfind_not_byteset(b"rabz "), Some(2)); + /// assert_eq!(None, b"foo baz bar".rfind_not_byteset(b"barfoz ")); + /// ``` + #[inline] + fn rfind_not_byteset>(&self, byteset: B) -> Option { + byteset::rfind_not(self.as_bytes(), byteset.as_ref()) + } + + /// Returns an iterator over the fields in a byte string, separated by + /// contiguous whitespace. + /// + /// # Example + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let s = B(" foo\tbar\t\u{2003}\nquux \n"); + /// let fields: Vec<&[u8]> = s.fields().collect(); + /// assert_eq!(fields, vec![B("foo"), B("bar"), B("quux")]); + /// ``` + /// + /// A byte string consisting of just whitespace yields no elements: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// assert_eq!(0, B(" \n\t\u{2003}\n \t").fields().count()); + /// ``` + #[inline] + fn fields(&self) -> Fields { + Fields::new(self.as_bytes()) + } + + /// Returns an iterator over the fields in a byte string, separated by + /// contiguous codepoints satisfying the given predicate. + /// + /// If this byte string is not valid UTF-8, then the given closure will + /// be called with a Unicode replacement codepoint when invalid UTF-8 + /// bytes are seen. + /// + /// # Example + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let s = b"123foo999999bar1quux123456"; + /// let fields: Vec<&[u8]> = s.fields_with(|c| c.is_numeric()).collect(); + /// assert_eq!(fields, vec![B("foo"), B("bar"), B("quux")]); + /// ``` + /// + /// A byte string consisting of all codepoints satisfying the predicate + /// yields no elements: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// assert_eq!(0, b"1911354563".fields_with(|c| c.is_numeric()).count()); + /// ``` + #[inline] + fn fields_with bool>(&self, f: F) -> FieldsWith { + FieldsWith::new(self.as_bytes(), f) + } + + /// Returns an iterator over substrings of this byte string, separated + /// by the given byte string. Each element yielded is guaranteed not to + /// include the splitter substring. + /// + /// The splitter may be any type that can be cheaply converted into a + /// `&[u8]`. This includes, but is not limited to, `&str` and `&[u8]`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let x: Vec<&[u8]> = b"Mary had a little lamb".split_str(" ").collect(); + /// assert_eq!(x, vec![ + /// B("Mary"), B("had"), B("a"), B("little"), B("lamb"), + /// ]); + /// + /// let x: Vec<&[u8]> = b"".split_str("X").collect(); + /// assert_eq!(x, vec![b""]); + /// + /// let x: Vec<&[u8]> = b"lionXXtigerXleopard".split_str("X").collect(); + /// assert_eq!(x, vec![B("lion"), B(""), B("tiger"), B("leopard")]); + /// + /// let x: Vec<&[u8]> = b"lion::tiger::leopard".split_str("::").collect(); + /// assert_eq!(x, vec![B("lion"), B("tiger"), B("leopard")]); + /// ``` + /// + /// If a string contains multiple contiguous separators, you will end up + /// with empty strings yielded by the iterator: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let x: Vec<&[u8]> = b"||||a||b|c".split_str("|").collect(); + /// assert_eq!(x, vec![ + /// B(""), B(""), B(""), B(""), B("a"), B(""), B("b"), B("c"), + /// ]); + /// + /// let x: Vec<&[u8]> = b"(///)".split_str("/").collect(); + /// assert_eq!(x, vec![B("("), B(""), B(""), B(")")]); + /// ``` + /// + /// Separators at the start or end of a string are neighbored by empty + /// strings. + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let x: Vec<&[u8]> = b"010".split_str("0").collect(); + /// assert_eq!(x, vec![B(""), B("1"), B("")]); + /// ``` + /// + /// When the empty string is used as a separator, it splits every **byte** + /// in the byte string, along with the beginning and end of the byte + /// string. + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let x: Vec<&[u8]> = b"rust".split_str("").collect(); + /// assert_eq!(x, vec![ + /// B(""), B("r"), B("u"), B("s"), B("t"), B(""), + /// ]); + /// + /// // Splitting by an empty string is not UTF-8 aware. Elements yielded + /// // may not be valid UTF-8! + /// let x: Vec<&[u8]> = B("☃").split_str("").collect(); + /// assert_eq!(x, vec![ + /// B(""), B(b"\xE2"), B(b"\x98"), B(b"\x83"), B(""), + /// ]); + /// ``` + /// + /// Contiguous separators, especially whitespace, can lead to possibly + /// surprising behavior. For example, this code is correct: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let x: Vec<&[u8]> = b" a b c".split_str(" ").collect(); + /// assert_eq!(x, vec![ + /// B(""), B(""), B(""), B(""), B("a"), B(""), B("b"), B("c"), + /// ]); + /// ``` + /// + /// It does *not* give you `["a", "b", "c"]`. For that behavior, use + /// [`fields`](#method.fields) instead. + #[inline] + fn split_str<'a, B: ?Sized + AsRef<[u8]>>( + &'a self, + splitter: &'a B, + ) -> Split<'a> { + Split::new(self.as_bytes(), splitter.as_ref()) + } + + /// Returns an iterator over substrings of this byte string, separated by + /// the given byte string, in reverse. Each element yielded is guaranteed + /// not to include the splitter substring. + /// + /// The splitter may be any type that can be cheaply converted into a + /// `&[u8]`. This includes, but is not limited to, `&str` and `&[u8]`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let x: Vec<&[u8]> = + /// b"Mary had a little lamb".rsplit_str(" ").collect(); + /// assert_eq!(x, vec![ + /// B("lamb"), B("little"), B("a"), B("had"), B("Mary"), + /// ]); + /// + /// let x: Vec<&[u8]> = b"".rsplit_str("X").collect(); + /// assert_eq!(x, vec![b""]); + /// + /// let x: Vec<&[u8]> = b"lionXXtigerXleopard".rsplit_str("X").collect(); + /// assert_eq!(x, vec![B("leopard"), B("tiger"), B(""), B("lion")]); + /// + /// let x: Vec<&[u8]> = b"lion::tiger::leopard".rsplit_str("::").collect(); + /// assert_eq!(x, vec![B("leopard"), B("tiger"), B("lion")]); + /// ``` + /// + /// If a string contains multiple contiguous separators, you will end up + /// with empty strings yielded by the iterator: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let x: Vec<&[u8]> = b"||||a||b|c".rsplit_str("|").collect(); + /// assert_eq!(x, vec![ + /// B("c"), B("b"), B(""), B("a"), B(""), B(""), B(""), B(""), + /// ]); + /// + /// let x: Vec<&[u8]> = b"(///)".rsplit_str("/").collect(); + /// assert_eq!(x, vec![B(")"), B(""), B(""), B("(")]); + /// ``` + /// + /// Separators at the start or end of a string are neighbored by empty + /// strings. + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let x: Vec<&[u8]> = b"010".rsplit_str("0").collect(); + /// assert_eq!(x, vec![B(""), B("1"), B("")]); + /// ``` + /// + /// When the empty string is used as a separator, it splits every **byte** + /// in the byte string, along with the beginning and end of the byte + /// string. + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let x: Vec<&[u8]> = b"rust".rsplit_str("").collect(); + /// assert_eq!(x, vec![ + /// B(""), B("t"), B("s"), B("u"), B("r"), B(""), + /// ]); + /// + /// // Splitting by an empty string is not UTF-8 aware. Elements yielded + /// // may not be valid UTF-8! + /// let x: Vec<&[u8]> = B("☃").rsplit_str("").collect(); + /// assert_eq!(x, vec![B(""), B(b"\x83"), B(b"\x98"), B(b"\xE2"), B("")]); + /// ``` + /// + /// Contiguous separators, especially whitespace, can lead to possibly + /// surprising behavior. For example, this code is correct: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let x: Vec<&[u8]> = b" a b c".rsplit_str(" ").collect(); + /// assert_eq!(x, vec![ + /// B("c"), B("b"), B(""), B("a"), B(""), B(""), B(""), B(""), + /// ]); + /// ``` + /// + /// It does *not* give you `["a", "b", "c"]`. + #[inline] + fn rsplit_str<'a, B: ?Sized + AsRef<[u8]>>( + &'a self, + splitter: &'a B, + ) -> SplitReverse<'a> { + SplitReverse::new(self.as_bytes(), splitter.as_ref()) + } + + /// Returns an iterator of at most `limit` substrings of this byte string, + /// separated by the given byte string. If `limit` substrings are yielded, + /// then the last substring will contain the remainder of this byte string. + /// + /// The needle may be any type that can be cheaply converted into a + /// `&[u8]`. This includes, but is not limited to, `&str` and `&[u8]`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let x: Vec<_> = b"Mary had a little lamb".splitn_str(3, " ").collect(); + /// assert_eq!(x, vec![B("Mary"), B("had"), B("a little lamb")]); + /// + /// let x: Vec<_> = b"".splitn_str(3, "X").collect(); + /// assert_eq!(x, vec![b""]); + /// + /// let x: Vec<_> = b"lionXXtigerXleopard".splitn_str(3, "X").collect(); + /// assert_eq!(x, vec![B("lion"), B(""), B("tigerXleopard")]); + /// + /// let x: Vec<_> = b"lion::tiger::leopard".splitn_str(2, "::").collect(); + /// assert_eq!(x, vec![B("lion"), B("tiger::leopard")]); + /// + /// let x: Vec<_> = b"abcXdef".splitn_str(1, "X").collect(); + /// assert_eq!(x, vec![B("abcXdef")]); + /// + /// let x: Vec<_> = b"abcdef".splitn_str(2, "X").collect(); + /// assert_eq!(x, vec![B("abcdef")]); + /// + /// let x: Vec<_> = b"abcXdef".splitn_str(0, "X").collect(); + /// assert!(x.is_empty()); + /// ``` + #[inline] + fn splitn_str<'a, B: ?Sized + AsRef<[u8]>>( + &'a self, + limit: usize, + splitter: &'a B, + ) -> SplitN<'a> { + SplitN::new(self.as_bytes(), splitter.as_ref(), limit) + } + + /// Returns an iterator of at most `limit` substrings of this byte string, + /// separated by the given byte string, in reverse. If `limit` substrings + /// are yielded, then the last substring will contain the remainder of this + /// byte string. + /// + /// The needle may be any type that can be cheaply converted into a + /// `&[u8]`. This includes, but is not limited to, `&str` and `&[u8]`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let x: Vec<_> = + /// b"Mary had a little lamb".rsplitn_str(3, " ").collect(); + /// assert_eq!(x, vec![B("lamb"), B("little"), B("Mary had a")]); + /// + /// let x: Vec<_> = b"".rsplitn_str(3, "X").collect(); + /// assert_eq!(x, vec![b""]); + /// + /// let x: Vec<_> = b"lionXXtigerXleopard".rsplitn_str(3, "X").collect(); + /// assert_eq!(x, vec![B("leopard"), B("tiger"), B("lionX")]); + /// + /// let x: Vec<_> = b"lion::tiger::leopard".rsplitn_str(2, "::").collect(); + /// assert_eq!(x, vec![B("leopard"), B("lion::tiger")]); + /// + /// let x: Vec<_> = b"abcXdef".rsplitn_str(1, "X").collect(); + /// assert_eq!(x, vec![B("abcXdef")]); + /// + /// let x: Vec<_> = b"abcdef".rsplitn_str(2, "X").collect(); + /// assert_eq!(x, vec![B("abcdef")]); + /// + /// let x: Vec<_> = b"abcXdef".rsplitn_str(0, "X").collect(); + /// assert!(x.is_empty()); + /// ``` + #[inline] + fn rsplitn_str<'a, B: ?Sized + AsRef<[u8]>>( + &'a self, + limit: usize, + splitter: &'a B, + ) -> SplitNReverse<'a> { + SplitNReverse::new(self.as_bytes(), splitter.as_ref(), limit) + } + + /// Replace all matches of the given needle with the given replacement, and + /// the result as a new `Vec`. + /// + /// This routine is useful as a convenience. If you need to reuse an + /// allocation, use [`replace_into`](#method.replace_into) instead. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let s = b"this is old".replace("old", "new"); + /// assert_eq!(s, "this is new".as_bytes()); + /// ``` + /// + /// When the pattern doesn't match: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let s = b"this is old".replace("nada nada", "limonada"); + /// assert_eq!(s, "this is old".as_bytes()); + /// ``` + /// + /// When the needle is an empty string: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let s = b"foo".replace("", "Z"); + /// assert_eq!(s, "ZfZoZoZ".as_bytes()); + /// ``` + #[cfg(feature = "std")] + #[inline] + fn replace, R: AsRef<[u8]>>( + &self, + needle: N, + replacement: R, + ) -> Vec { + let mut dest = Vec::with_capacity(self.as_bytes().len()); + self.replace_into(needle, replacement, &mut dest); + dest + } + + /// Replace up to `limit` matches of the given needle with the given + /// replacement, and the result as a new `Vec`. + /// + /// This routine is useful as a convenience. If you need to reuse an + /// allocation, use [`replacen_into`](#method.replacen_into) instead. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let s = b"foofoo".replacen("o", "z", 2); + /// assert_eq!(s, "fzzfoo".as_bytes()); + /// ``` + /// + /// When the pattern doesn't match: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let s = b"foofoo".replacen("a", "z", 2); + /// assert_eq!(s, "foofoo".as_bytes()); + /// ``` + /// + /// When the needle is an empty string: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let s = b"foo".replacen("", "Z", 2); + /// assert_eq!(s, "ZfZoo".as_bytes()); + /// ``` + #[cfg(feature = "std")] + #[inline] + fn replacen, R: AsRef<[u8]>>( + &self, + needle: N, + replacement: R, + limit: usize, + ) -> Vec { + let mut dest = Vec::with_capacity(self.as_bytes().len()); + self.replacen_into(needle, replacement, limit, &mut dest); + dest + } + + /// Replace all matches of the given needle with the given replacement, + /// and write the result into the provided `Vec`. + /// + /// This does **not** clear `dest` before writing to it. + /// + /// This routine is useful for reusing allocation. For a more convenient + /// API, use [`replace`](#method.replace) instead. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let s = b"this is old"; + /// + /// let mut dest = vec![]; + /// s.replace_into("old", "new", &mut dest); + /// assert_eq!(dest, "this is new".as_bytes()); + /// ``` + /// + /// When the pattern doesn't match: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let s = b"this is old"; + /// + /// let mut dest = vec![]; + /// s.replace_into("nada nada", "limonada", &mut dest); + /// assert_eq!(dest, "this is old".as_bytes()); + /// ``` + /// + /// When the needle is an empty string: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let s = b"foo"; + /// + /// let mut dest = vec![]; + /// s.replace_into("", "Z", &mut dest); + /// assert_eq!(dest, "ZfZoZoZ".as_bytes()); + /// ``` + #[cfg(feature = "std")] + #[inline] + fn replace_into, R: AsRef<[u8]>>( + &self, + needle: N, + replacement: R, + dest: &mut Vec, + ) { + let (needle, replacement) = (needle.as_ref(), replacement.as_ref()); + + let mut last = 0; + for start in self.find_iter(needle) { + dest.push_str(&self.as_bytes()[last..start]); + dest.push_str(replacement); + last = start + needle.len(); + } + dest.push_str(&self.as_bytes()[last..]); + } + + /// Replace up to `limit` matches of the given needle with the given + /// replacement, and write the result into the provided `Vec`. + /// + /// This does **not** clear `dest` before writing to it. + /// + /// This routine is useful for reusing allocation. For a more convenient + /// API, use [`replacen`](#method.replacen) instead. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let s = b"foofoo"; + /// + /// let mut dest = vec![]; + /// s.replacen_into("o", "z", 2, &mut dest); + /// assert_eq!(dest, "fzzfoo".as_bytes()); + /// ``` + /// + /// When the pattern doesn't match: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let s = b"foofoo"; + /// + /// let mut dest = vec![]; + /// s.replacen_into("a", "z", 2, &mut dest); + /// assert_eq!(dest, "foofoo".as_bytes()); + /// ``` + /// + /// When the needle is an empty string: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let s = b"foo"; + /// + /// let mut dest = vec![]; + /// s.replacen_into("", "Z", 2, &mut dest); + /// assert_eq!(dest, "ZfZoo".as_bytes()); + /// ``` + #[cfg(feature = "std")] + #[inline] + fn replacen_into, R: AsRef<[u8]>>( + &self, + needle: N, + replacement: R, + limit: usize, + dest: &mut Vec, + ) { + let (needle, replacement) = (needle.as_ref(), replacement.as_ref()); + + let mut last = 0; + for start in self.find_iter(needle).take(limit) { + dest.push_str(&self.as_bytes()[last..start]); + dest.push_str(replacement); + last = start + needle.len(); + } + dest.push_str(&self.as_bytes()[last..]); + } + + /// Returns an iterator over the bytes in this byte string. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let bs = b"foobar"; + /// let bytes: Vec = bs.bytes().collect(); + /// assert_eq!(bytes, bs); + /// ``` + #[inline] + fn bytes(&self) -> Bytes { + Bytes { it: self.as_bytes().iter() } + } + + /// Returns an iterator over the Unicode scalar values in this byte string. + /// If invalid UTF-8 is encountered, then the Unicode replacement codepoint + /// is yielded instead. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let bs = b"\xE2\x98\x83\xFF\xF0\x9D\x9E\x83\xE2\x98\x61"; + /// let chars: Vec = bs.chars().collect(); + /// assert_eq!(vec!['☃', '\u{FFFD}', '𝞃', '\u{FFFD}', 'a'], chars); + /// ``` + /// + /// Codepoints can also be iterated over in reverse: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let bs = b"\xE2\x98\x83\xFF\xF0\x9D\x9E\x83\xE2\x98\x61"; + /// let chars: Vec = bs.chars().rev().collect(); + /// assert_eq!(vec!['a', '\u{FFFD}', '𝞃', '\u{FFFD}', '☃'], chars); + /// ``` + #[inline] + fn chars(&self) -> Chars { + Chars::new(self.as_bytes()) + } + + /// Returns an iterator over the Unicode scalar values in this byte string + /// along with their starting and ending byte index positions. If invalid + /// UTF-8 is encountered, then the Unicode replacement codepoint is yielded + /// instead. + /// + /// Note that this is slightly different from the `CharIndices` iterator + /// provided by the standard library. Aside from working on possibly + /// invalid UTF-8, this iterator provides both the corresponding starting + /// and ending byte indices of each codepoint yielded. The ending position + /// is necessary to slice the original byte string when invalid UTF-8 bytes + /// are converted into a Unicode replacement codepoint, since a single + /// replacement codepoint can substitute anywhere from 1 to 3 invalid bytes + /// (inclusive). + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let bs = b"\xE2\x98\x83\xFF\xF0\x9D\x9E\x83\xE2\x98\x61"; + /// let chars: Vec<(usize, usize, char)> = bs.char_indices().collect(); + /// assert_eq!(chars, vec![ + /// (0, 3, '☃'), + /// (3, 4, '\u{FFFD}'), + /// (4, 8, '𝞃'), + /// (8, 10, '\u{FFFD}'), + /// (10, 11, 'a'), + /// ]); + /// ``` + /// + /// Codepoints can also be iterated over in reverse: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let bs = b"\xE2\x98\x83\xFF\xF0\x9D\x9E\x83\xE2\x98\x61"; + /// let chars: Vec<(usize, usize, char)> = bs + /// .char_indices() + /// .rev() + /// .collect(); + /// assert_eq!(chars, vec![ + /// (10, 11, 'a'), + /// (8, 10, '\u{FFFD}'), + /// (4, 8, '𝞃'), + /// (3, 4, '\u{FFFD}'), + /// (0, 3, '☃'), + /// ]); + /// ``` + #[inline] + fn char_indices(&self) -> CharIndices { + CharIndices::new(self.as_bytes()) + } + + /// Iterate over chunks of valid UTF-8. + /// + /// The iterator returned yields chunks of valid UTF-8 separated by invalid + /// UTF-8 bytes, if they exist. Invalid UTF-8 bytes are always 1-3 bytes, + /// which are determined via the "substitution of maximal subparts" + /// strategy described in the docs for the + /// [`ByteSlice::to_str_lossy`](trait.ByteSlice.html#method.to_str_lossy) + /// method. + /// + /// # Examples + /// + /// This example shows how to gather all valid and invalid chunks from a + /// byte slice: + /// + /// ``` + /// use bstr::{ByteSlice, Utf8Chunk}; + /// + /// let bytes = b"foo\xFD\xFEbar\xFF"; + /// + /// let (mut valid_chunks, mut invalid_chunks) = (vec![], vec![]); + /// for chunk in bytes.utf8_chunks() { + /// if !chunk.valid().is_empty() { + /// valid_chunks.push(chunk.valid()); + /// } + /// if !chunk.invalid().is_empty() { + /// invalid_chunks.push(chunk.invalid()); + /// } + /// } + /// + /// assert_eq!(valid_chunks, vec!["foo", "bar"]); + /// assert_eq!(invalid_chunks, vec![b"\xFD", b"\xFE", b"\xFF"]); + /// ``` + #[inline] + fn utf8_chunks(&self) -> Utf8Chunks { + Utf8Chunks { bytes: self.as_bytes() } + } + + /// Returns an iterator over the grapheme clusters in this byte string. + /// If invalid UTF-8 is encountered, then the Unicode replacement codepoint + /// is yielded instead. + /// + /// # Examples + /// + /// This example shows how multiple codepoints can combine to form a + /// single grapheme cluster: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let bs = "a\u{0300}\u{0316}\u{1F1FA}\u{1F1F8}".as_bytes(); + /// let graphemes: Vec<&str> = bs.graphemes().collect(); + /// assert_eq!(vec!["à̖", "🇺🇸"], graphemes); + /// ``` + /// + /// This shows that graphemes can be iterated over in reverse: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let bs = "a\u{0300}\u{0316}\u{1F1FA}\u{1F1F8}".as_bytes(); + /// let graphemes: Vec<&str> = bs.graphemes().rev().collect(); + /// assert_eq!(vec!["🇺🇸", "à̖"], graphemes); + /// ``` + #[cfg(feature = "unicode")] + #[inline] + fn graphemes(&self) -> Graphemes { + Graphemes::new(self.as_bytes()) + } + + /// Returns an iterator over the grapheme clusters in this byte string + /// along with their starting and ending byte index positions. If invalid + /// UTF-8 is encountered, then the Unicode replacement codepoint is yielded + /// instead. + /// + /// # Examples + /// + /// This example shows how to get the byte offsets of each individual + /// grapheme cluster: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let bs = "a\u{0300}\u{0316}\u{1F1FA}\u{1F1F8}".as_bytes(); + /// let graphemes: Vec<(usize, usize, &str)> = + /// bs.grapheme_indices().collect(); + /// assert_eq!(vec![(0, 5, "à̖"), (5, 13, "🇺🇸")], graphemes); + /// ``` + /// + /// This example shows what happens when invalid UTF-8 is enountered. Note + /// that the offsets are valid indices into the original string, and do + /// not necessarily correspond to the length of the `&str` returned! + /// + /// ``` + /// use bstr::{ByteSlice, ByteVec}; + /// + /// let mut bytes = vec![]; + /// bytes.push_str("a\u{0300}\u{0316}"); + /// bytes.push(b'\xFF'); + /// bytes.push_str("\u{1F1FA}\u{1F1F8}"); + /// + /// let graphemes: Vec<(usize, usize, &str)> = + /// bytes.grapheme_indices().collect(); + /// assert_eq!( + /// graphemes, + /// vec![(0, 5, "à̖"), (5, 6, "\u{FFFD}"), (6, 14, "🇺🇸")] + /// ); + /// ``` + #[cfg(feature = "unicode")] + #[inline] + fn grapheme_indices(&self) -> GraphemeIndices { + GraphemeIndices::new(self.as_bytes()) + } + + /// Returns an iterator over the words in this byte string. If invalid + /// UTF-8 is encountered, then the Unicode replacement codepoint is yielded + /// instead. + /// + /// This is similar to + /// [`words_with_breaks`](trait.ByteSlice.html#method.words_with_breaks), + /// except it only returns elements that contain a "word" character. A word + /// character is defined by UTS #18 (Annex C) to be the combination of the + /// `Alphabetic` and `Join_Control` properties, along with the + /// `Decimal_Number`, `Mark` and `Connector_Punctuation` general + /// categories. + /// + /// Since words are made up of one or more codepoints, this iterator + /// yields `&str` elements. When invalid UTF-8 is encountered, replacement + /// codepoints are [substituted](index.html#handling-of-invalid-utf-8). + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let bs = br#"The quick ("brown") fox can't jump 32.3 feet, right?"#; + /// let words: Vec<&str> = bs.words().collect(); + /// assert_eq!(words, vec![ + /// "The", "quick", "brown", "fox", "can't", + /// "jump", "32.3", "feet", "right", + /// ]); + /// ``` + #[cfg(feature = "unicode")] + #[inline] + fn words(&self) -> Words { + Words::new(self.as_bytes()) + } + + /// Returns an iterator over the words in this byte string along with + /// their starting and ending byte index positions. + /// + /// This is similar to + /// [`words_with_break_indices`](trait.ByteSlice.html#method.words_with_break_indices), + /// except it only returns elements that contain a "word" character. A word + /// character is defined by UTS #18 (Annex C) to be the combination of the + /// `Alphabetic` and `Join_Control` properties, along with the + /// `Decimal_Number`, `Mark` and `Connector_Punctuation` general + /// categories. + /// + /// Since words are made up of one or more codepoints, this iterator + /// yields `&str` elements. When invalid UTF-8 is encountered, replacement + /// codepoints are [substituted](index.html#handling-of-invalid-utf-8). + /// + /// # Examples + /// + /// This example shows how to get the byte offsets of each individual + /// word: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let bs = b"can't jump 32.3 feet"; + /// let words: Vec<(usize, usize, &str)> = bs.word_indices().collect(); + /// assert_eq!(words, vec![ + /// (0, 5, "can't"), + /// (6, 10, "jump"), + /// (11, 15, "32.3"), + /// (16, 20, "feet"), + /// ]); + /// ``` + #[cfg(feature = "unicode")] + #[inline] + fn word_indices(&self) -> WordIndices { + WordIndices::new(self.as_bytes()) + } + + /// Returns an iterator over the words in this byte string, along with + /// all breaks between the words. Concatenating all elements yielded by + /// the iterator results in the original string (modulo Unicode replacement + /// codepoint substitutions if invalid UTF-8 is encountered). + /// + /// Since words are made up of one or more codepoints, this iterator + /// yields `&str` elements. When invalid UTF-8 is encountered, replacement + /// codepoints are [substituted](index.html#handling-of-invalid-utf-8). + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let bs = br#"The quick ("brown") fox can't jump 32.3 feet, right?"#; + /// let words: Vec<&str> = bs.words_with_breaks().collect(); + /// assert_eq!(words, vec![ + /// "The", " ", "quick", " ", "(", "\"", "brown", "\"", ")", + /// " ", "fox", " ", "can't", " ", "jump", " ", "32.3", " ", "feet", + /// ",", " ", "right", "?", + /// ]); + /// ``` + #[cfg(feature = "unicode")] + #[inline] + fn words_with_breaks(&self) -> WordsWithBreaks { + WordsWithBreaks::new(self.as_bytes()) + } + + /// Returns an iterator over the words and their byte offsets in this + /// byte string, along with all breaks between the words. Concatenating + /// all elements yielded by the iterator results in the original string + /// (modulo Unicode replacement codepoint substitutions if invalid UTF-8 is + /// encountered). + /// + /// Since words are made up of one or more codepoints, this iterator + /// yields `&str` elements. When invalid UTF-8 is encountered, replacement + /// codepoints are [substituted](index.html#handling-of-invalid-utf-8). + /// + /// # Examples + /// + /// This example shows how to get the byte offsets of each individual + /// word: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let bs = b"can't jump 32.3 feet"; + /// let words: Vec<(usize, usize, &str)> = + /// bs.words_with_break_indices().collect(); + /// assert_eq!(words, vec![ + /// (0, 5, "can't"), + /// (5, 6, " "), + /// (6, 10, "jump"), + /// (10, 11, " "), + /// (11, 15, "32.3"), + /// (15, 16, " "), + /// (16, 20, "feet"), + /// ]); + /// ``` + #[cfg(feature = "unicode")] + #[inline] + fn words_with_break_indices(&self) -> WordsWithBreakIndices { + WordsWithBreakIndices::new(self.as_bytes()) + } + + /// Returns an iterator over the sentences in this byte string. + /// + /// Typically, a sentence will include its trailing punctuation and + /// whitespace. Concatenating all elements yielded by the iterator + /// results in the original string (modulo Unicode replacement codepoint + /// substitutions if invalid UTF-8 is encountered). + /// + /// Since sentences are made up of one or more codepoints, this iterator + /// yields `&str` elements. When invalid UTF-8 is encountered, replacement + /// codepoints are [substituted](index.html#handling-of-invalid-utf-8). + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let bs = b"I want this. Not that. Right now."; + /// let sentences: Vec<&str> = bs.sentences().collect(); + /// assert_eq!(sentences, vec![ + /// "I want this. ", + /// "Not that. ", + /// "Right now.", + /// ]); + /// ``` + #[cfg(feature = "unicode")] + #[inline] + fn sentences(&self) -> Sentences { + Sentences::new(self.as_bytes()) + } + + /// Returns an iterator over the sentences in this byte string along with + /// their starting and ending byte index positions. + /// + /// Typically, a sentence will include its trailing punctuation and + /// whitespace. Concatenating all elements yielded by the iterator + /// results in the original string (modulo Unicode replacement codepoint + /// substitutions if invalid UTF-8 is encountered). + /// + /// Since sentences are made up of one or more codepoints, this iterator + /// yields `&str` elements. When invalid UTF-8 is encountered, replacement + /// codepoints are [substituted](index.html#handling-of-invalid-utf-8). + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let bs = b"I want this. Not that. Right now."; + /// let sentences: Vec<(usize, usize, &str)> = + /// bs.sentence_indices().collect(); + /// assert_eq!(sentences, vec![ + /// (0, 13, "I want this. "), + /// (13, 23, "Not that. "), + /// (23, 33, "Right now."), + /// ]); + /// ``` + #[cfg(feature = "unicode")] + #[inline] + fn sentence_indices(&self) -> SentenceIndices { + SentenceIndices::new(self.as_bytes()) + } + + /// An iterator over all lines in a byte string, without their + /// terminators. + /// + /// For this iterator, the only line terminators recognized are `\r\n` and + /// `\n`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let s = b"\ + /// foo + /// + /// bar\r + /// baz + /// + /// + /// quux"; + /// let lines: Vec<&[u8]> = s.lines().collect(); + /// assert_eq!(lines, vec![ + /// B("foo"), B(""), B("bar"), B("baz"), B(""), B(""), B("quux"), + /// ]); + /// ``` + #[inline] + fn lines(&self) -> Lines { + Lines::new(self.as_bytes()) + } + + /// An iterator over all lines in a byte string, including their + /// terminators. + /// + /// For this iterator, the only line terminator recognized is `\n`. (Since + /// line terminators are included, this also handles `\r\n` line endings.) + /// + /// Line terminators are only included if they are present in the original + /// byte string. For example, the last line in a byte string may not end + /// with a line terminator. + /// + /// Concatenating all elements yielded by this iterator is guaranteed to + /// yield the original byte string. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let s = b"\ + /// foo + /// + /// bar\r + /// baz + /// + /// + /// quux"; + /// let lines: Vec<&[u8]> = s.lines_with_terminator().collect(); + /// assert_eq!(lines, vec![ + /// B("foo\n"), + /// B("\n"), + /// B("bar\r\n"), + /// B("baz\n"), + /// B("\n"), + /// B("\n"), + /// B("quux"), + /// ]); + /// ``` + #[inline] + fn lines_with_terminator(&self) -> LinesWithTerminator { + LinesWithTerminator::new(self.as_bytes()) + } + + /// Return a byte string slice with leading and trailing whitespace + /// removed. + /// + /// Whitespace is defined according to the terms of the `White_Space` + /// Unicode property. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let s = B(" foo\tbar\t\u{2003}\n"); + /// assert_eq!(s.trim(), B("foo\tbar")); + /// ``` + #[cfg(feature = "unicode")] + #[inline] + fn trim(&self) -> &[u8] { + self.trim_start().trim_end() + } + + /// Return a byte string slice with leading whitespace removed. + /// + /// Whitespace is defined according to the terms of the `White_Space` + /// Unicode property. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let s = B(" foo\tbar\t\u{2003}\n"); + /// assert_eq!(s.trim_start(), B("foo\tbar\t\u{2003}\n")); + /// ``` + #[cfg(feature = "unicode")] + #[inline] + fn trim_start(&self) -> &[u8] { + let start = whitespace_len_fwd(self.as_bytes()); + &self.as_bytes()[start..] + } + + /// Return a byte string slice with trailing whitespace removed. + /// + /// Whitespace is defined according to the terms of the `White_Space` + /// Unicode property. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let s = B(" foo\tbar\t\u{2003}\n"); + /// assert_eq!(s.trim_end(), B(" foo\tbar")); + /// ``` + #[cfg(feature = "unicode")] + #[inline] + fn trim_end(&self) -> &[u8] { + let end = whitespace_len_rev(self.as_bytes()); + &self.as_bytes()[..end] + } + + /// Return a byte string slice with leading and trailing characters + /// satisfying the given predicate removed. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let s = b"123foo5bar789"; + /// assert_eq!(s.trim_with(|c| c.is_numeric()), B("foo5bar")); + /// ``` + #[inline] + fn trim_with bool>(&self, mut trim: F) -> &[u8] { + self.trim_start_with(&mut trim).trim_end_with(&mut trim) + } + + /// Return a byte string slice with leading characters satisfying the given + /// predicate removed. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let s = b"123foo5bar789"; + /// assert_eq!(s.trim_start_with(|c| c.is_numeric()), B("foo5bar789")); + /// ``` + #[inline] + fn trim_start_with bool>(&self, mut trim: F) -> &[u8] { + for (s, _, ch) in self.char_indices() { + if !trim(ch) { + return &self.as_bytes()[s..]; + } + } + b"" + } + + /// Return a byte string slice with trailing characters satisfying the + /// given predicate removed. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let s = b"123foo5bar789"; + /// assert_eq!(s.trim_end_with(|c| c.is_numeric()), B("123foo5bar")); + /// ``` + #[inline] + fn trim_end_with bool>(&self, mut trim: F) -> &[u8] { + for (_, e, ch) in self.char_indices().rev() { + if !trim(ch) { + return &self.as_bytes()[..e]; + } + } + b"" + } + + /// Returns a new `Vec` containing the lowercase equivalent of this + /// byte string. + /// + /// In this case, lowercase is defined according to the `Lowercase` Unicode + /// property. + /// + /// If invalid UTF-8 is seen, or if a character has no lowercase variant, + /// then it is written to the given buffer unchanged. + /// + /// Note that some characters in this byte string may expand into multiple + /// characters when changing the case, so the number of bytes written to + /// the given byte string may not be equivalent to the number of bytes in + /// this byte string. + /// + /// If you'd like to reuse an allocation for performance reasons, then use + /// [`to_lowercase_into`](#method.to_lowercase_into) instead. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let s = B("HELLO Β"); + /// assert_eq!("hello β".as_bytes(), s.to_lowercase().as_bytes()); + /// ``` + /// + /// Scripts without case are not changed: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let s = B("农历新年"); + /// assert_eq!("农历新年".as_bytes(), s.to_lowercase().as_bytes()); + /// ``` + /// + /// Invalid UTF-8 remains as is: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let s = B(b"FOO\xFFBAR\xE2\x98BAZ"); + /// assert_eq!(B(b"foo\xFFbar\xE2\x98baz"), s.to_lowercase().as_bytes()); + /// ``` + #[cfg(all(feature = "std", feature = "unicode"))] + #[inline] + fn to_lowercase(&self) -> Vec { + let mut buf = vec![]; + self.to_lowercase_into(&mut buf); + buf + } + + /// Writes the lowercase equivalent of this byte string into the given + /// buffer. The buffer is not cleared before written to. + /// + /// In this case, lowercase is defined according to the `Lowercase` + /// Unicode property. + /// + /// If invalid UTF-8 is seen, or if a character has no lowercase variant, + /// then it is written to the given buffer unchanged. + /// + /// Note that some characters in this byte string may expand into multiple + /// characters when changing the case, so the number of bytes written to + /// the given byte string may not be equivalent to the number of bytes in + /// this byte string. + /// + /// If you don't need to amortize allocation and instead prefer + /// convenience, then use [`to_lowercase`](#method.to_lowercase) instead. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let s = B("HELLO Β"); + /// + /// let mut buf = vec![]; + /// s.to_lowercase_into(&mut buf); + /// assert_eq!("hello β".as_bytes(), buf.as_bytes()); + /// ``` + /// + /// Scripts without case are not changed: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let s = B("农历新年"); + /// + /// let mut buf = vec![]; + /// s.to_lowercase_into(&mut buf); + /// assert_eq!("农历新年".as_bytes(), buf.as_bytes()); + /// ``` + /// + /// Invalid UTF-8 remains as is: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let s = B(b"FOO\xFFBAR\xE2\x98BAZ"); + /// + /// let mut buf = vec![]; + /// s.to_lowercase_into(&mut buf); + /// assert_eq!(B(b"foo\xFFbar\xE2\x98baz"), buf.as_bytes()); + /// ``` + #[cfg(all(feature = "std", feature = "unicode"))] + #[inline] + fn to_lowercase_into(&self, buf: &mut Vec) { + // TODO: This is the best we can do given what std exposes I think. + // If we roll our own case handling, then we might be able to do this + // a bit faster. We shouldn't roll our own case handling unless we + // need to, e.g., for doing caseless matching or case folding. + + // TODO(BUG): This doesn't handle any special casing rules. + + buf.reserve(self.as_bytes().len()); + for (s, e, ch) in self.char_indices() { + if ch == '\u{FFFD}' { + buf.push_str(&self.as_bytes()[s..e]); + } else if ch.is_ascii() { + buf.push_char(ch.to_ascii_lowercase()); + } else { + for upper in ch.to_lowercase() { + buf.push_char(upper); + } + } + } + } + + /// Returns a new `Vec` containing the ASCII lowercase equivalent of + /// this byte string. + /// + /// In this case, lowercase is only defined in ASCII letters. Namely, the + /// letters `A-Z` are converted to `a-z`. All other bytes remain unchanged. + /// In particular, the length of the byte string returned is always + /// equivalent to the length of this byte string. + /// + /// If you'd like to reuse an allocation for performance reasons, then use + /// [`make_ascii_lowercase`](#method.make_ascii_lowercase) to perform + /// the conversion in place. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let s = B("HELLO Β"); + /// assert_eq!("hello Β".as_bytes(), s.to_ascii_lowercase().as_bytes()); + /// ``` + /// + /// Invalid UTF-8 remains as is: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let s = B(b"FOO\xFFBAR\xE2\x98BAZ"); + /// assert_eq!(s.to_ascii_lowercase(), B(b"foo\xFFbar\xE2\x98baz")); + /// ``` + #[cfg(feature = "std")] + #[inline] + fn to_ascii_lowercase(&self) -> Vec { + self.as_bytes().to_ascii_lowercase() + } + + /// Convert this byte string to its lowercase ASCII equivalent in place. + /// + /// In this case, lowercase is only defined in ASCII letters. Namely, the + /// letters `A-Z` are converted to `a-z`. All other bytes remain unchanged. + /// + /// If you don't need to do the conversion in + /// place and instead prefer convenience, then use + /// [`to_ascii_lowercase`](#method.to_ascii_lowercase) instead. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let mut s = >::from("HELLO Β"); + /// s.make_ascii_lowercase(); + /// assert_eq!(s, "hello Β".as_bytes()); + /// ``` + /// + /// Invalid UTF-8 remains as is: + /// + /// ``` + /// use bstr::{B, ByteSlice, ByteVec}; + /// + /// let mut s = >::from_slice(b"FOO\xFFBAR\xE2\x98BAZ"); + /// s.make_ascii_lowercase(); + /// assert_eq!(s, B(b"foo\xFFbar\xE2\x98baz")); + /// ``` + #[inline] + fn make_ascii_lowercase(&mut self) { + self.as_bytes_mut().make_ascii_lowercase(); + } + + /// Returns a new `Vec` containing the uppercase equivalent of this + /// byte string. + /// + /// In this case, uppercase is defined according to the `Uppercase` + /// Unicode property. + /// + /// If invalid UTF-8 is seen, or if a character has no uppercase variant, + /// then it is written to the given buffer unchanged. + /// + /// Note that some characters in this byte string may expand into multiple + /// characters when changing the case, so the number of bytes written to + /// the given byte string may not be equivalent to the number of bytes in + /// this byte string. + /// + /// If you'd like to reuse an allocation for performance reasons, then use + /// [`to_uppercase_into`](#method.to_uppercase_into) instead. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let s = B("hello β"); + /// assert_eq!(s.to_uppercase(), B("HELLO Β")); + /// ``` + /// + /// Scripts without case are not changed: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let s = B("农历新年"); + /// assert_eq!(s.to_uppercase(), B("农历新年")); + /// ``` + /// + /// Invalid UTF-8 remains as is: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let s = B(b"foo\xFFbar\xE2\x98baz"); + /// assert_eq!(s.to_uppercase(), B(b"FOO\xFFBAR\xE2\x98BAZ")); + /// ``` + #[cfg(all(feature = "std", feature = "unicode"))] + #[inline] + fn to_uppercase(&self) -> Vec { + let mut buf = vec![]; + self.to_uppercase_into(&mut buf); + buf + } + + /// Writes the uppercase equivalent of this byte string into the given + /// buffer. The buffer is not cleared before written to. + /// + /// In this case, uppercase is defined according to the `Uppercase` + /// Unicode property. + /// + /// If invalid UTF-8 is seen, or if a character has no uppercase variant, + /// then it is written to the given buffer unchanged. + /// + /// Note that some characters in this byte string may expand into multiple + /// characters when changing the case, so the number of bytes written to + /// the given byte string may not be equivalent to the number of bytes in + /// this byte string. + /// + /// If you don't need to amortize allocation and instead prefer + /// convenience, then use [`to_uppercase`](#method.to_uppercase) instead. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let s = B("hello β"); + /// + /// let mut buf = vec![]; + /// s.to_uppercase_into(&mut buf); + /// assert_eq!(buf, B("HELLO Β")); + /// ``` + /// + /// Scripts without case are not changed: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let s = B("农历新年"); + /// + /// let mut buf = vec![]; + /// s.to_uppercase_into(&mut buf); + /// assert_eq!(buf, B("农历新年")); + /// ``` + /// + /// Invalid UTF-8 remains as is: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let s = B(b"foo\xFFbar\xE2\x98baz"); + /// + /// let mut buf = vec![]; + /// s.to_uppercase_into(&mut buf); + /// assert_eq!(buf, B(b"FOO\xFFBAR\xE2\x98BAZ")); + /// ``` + #[cfg(all(feature = "std", feature = "unicode"))] + #[inline] + fn to_uppercase_into(&self, buf: &mut Vec) { + // TODO: This is the best we can do given what std exposes I think. + // If we roll our own case handling, then we might be able to do this + // a bit faster. We shouldn't roll our own case handling unless we + // need to, e.g., for doing caseless matching or case folding. + buf.reserve(self.as_bytes().len()); + for (s, e, ch) in self.char_indices() { + if ch == '\u{FFFD}' { + buf.push_str(&self.as_bytes()[s..e]); + } else if ch.is_ascii() { + buf.push_char(ch.to_ascii_uppercase()); + } else { + for upper in ch.to_uppercase() { + buf.push_char(upper); + } + } + } + } + + /// Returns a new `Vec` containing the ASCII uppercase equivalent of + /// this byte string. + /// + /// In this case, uppercase is only defined in ASCII letters. Namely, the + /// letters `a-z` are converted to `A-Z`. All other bytes remain unchanged. + /// In particular, the length of the byte string returned is always + /// equivalent to the length of this byte string. + /// + /// If you'd like to reuse an allocation for performance reasons, then use + /// [`make_ascii_uppercase`](#method.make_ascii_uppercase) to perform + /// the conversion in place. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let s = B("hello β"); + /// assert_eq!(s.to_ascii_uppercase(), B("HELLO β")); + /// ``` + /// + /// Invalid UTF-8 remains as is: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let s = B(b"foo\xFFbar\xE2\x98baz"); + /// assert_eq!(s.to_ascii_uppercase(), B(b"FOO\xFFBAR\xE2\x98BAZ")); + /// ``` + #[cfg(feature = "std")] + #[inline] + fn to_ascii_uppercase(&self) -> Vec { + self.as_bytes().to_ascii_uppercase() + } + + /// Convert this byte string to its uppercase ASCII equivalent in place. + /// + /// In this case, uppercase is only defined in ASCII letters. Namely, the + /// letters `a-z` are converted to `A-Z`. All other bytes remain unchanged. + /// + /// If you don't need to do the conversion in + /// place and instead prefer convenience, then use + /// [`to_ascii_uppercase`](#method.to_ascii_uppercase) instead. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let mut s = >::from("hello β"); + /// s.make_ascii_uppercase(); + /// assert_eq!(s, B("HELLO β")); + /// ``` + /// + /// Invalid UTF-8 remains as is: + /// + /// ``` + /// use bstr::{B, ByteSlice, ByteVec}; + /// + /// let mut s = >::from_slice(b"foo\xFFbar\xE2\x98baz"); + /// s.make_ascii_uppercase(); + /// assert_eq!(s, B(b"FOO\xFFBAR\xE2\x98BAZ")); + /// ``` + #[inline] + fn make_ascii_uppercase(&mut self) { + self.as_bytes_mut().make_ascii_uppercase(); + } + + /// Reverse the bytes in this string, in place. + /// + /// This is not necessarily a well formed operation! For example, if this + /// byte string contains valid UTF-8 that isn't ASCII, then reversing the + /// string will likely result in invalid UTF-8 and otherwise non-sensical + /// content. + /// + /// Note that this is equivalent to the generic `[u8]::reverse` method. + /// This method is provided to permit callers to explicitly differentiate + /// between reversing bytes, codepoints and graphemes. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let mut s = >::from("hello"); + /// s.reverse_bytes(); + /// assert_eq!(s, "olleh".as_bytes()); + /// ``` + #[inline] + fn reverse_bytes(&mut self) { + self.as_bytes_mut().reverse(); + } + + /// Reverse the codepoints in this string, in place. + /// + /// If this byte string is valid UTF-8, then its reversal by codepoint + /// is also guaranteed to be valid UTF-8. + /// + /// This operation is equivalent to the following, but without allocating: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let mut s = >::from("foo☃bar"); + /// + /// let mut chars: Vec = s.chars().collect(); + /// chars.reverse(); + /// + /// let reversed: String = chars.into_iter().collect(); + /// assert_eq!(reversed, "rab☃oof"); + /// ``` + /// + /// Note that this is not necessarily a well formed operation. For example, + /// if this byte string contains grapheme clusters with more than one + /// codepoint, then those grapheme clusters will not necessarily be + /// preserved. If you'd like to preserve grapheme clusters, then use + /// [`reverse_graphemes`](#method.reverse_graphemes) instead. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let mut s = >::from("foo☃bar"); + /// s.reverse_chars(); + /// assert_eq!(s, "rab☃oof".as_bytes()); + /// ``` + /// + /// This example shows that not all reversals lead to a well formed string. + /// For example, in this case, combining marks are used to put accents over + /// some letters, and those accent marks must appear after the codepoints + /// they modify. + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let mut s = >::from("résumé"); + /// s.reverse_chars(); + /// assert_eq!(s, B(b"\xCC\x81emus\xCC\x81er")); + /// ``` + /// + /// A word of warning: the above example relies on the fact that + /// `résumé` is in decomposed normal form, which means there are separate + /// codepoints for the accents above `e`. If it is instead in composed + /// normal form, then the example works: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let mut s = >::from("résumé"); + /// s.reverse_chars(); + /// assert_eq!(s, B("émusér")); + /// ``` + /// + /// The point here is to be cautious and not assume that just because + /// `reverse_chars` works in one case, that it therefore works in all + /// cases. + #[inline] + fn reverse_chars(&mut self) { + let mut i = 0; + loop { + let (_, size) = utf8::decode(&self.as_bytes()[i..]); + if size == 0 { + break; + } + if size > 1 { + self.as_bytes_mut()[i..i + size].reverse_bytes(); + } + i += size; + } + self.reverse_bytes(); + } + + /// Reverse the graphemes in this string, in place. + /// + /// If this byte string is valid UTF-8, then its reversal by grapheme + /// is also guaranteed to be valid UTF-8. + /// + /// This operation is equivalent to the following, but without allocating: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let mut s = >::from("foo☃bar"); + /// + /// let mut graphemes: Vec<&str> = s.graphemes().collect(); + /// graphemes.reverse(); + /// + /// let reversed = graphemes.concat(); + /// assert_eq!(reversed, "rab☃oof"); + /// ``` + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let mut s = >::from("foo☃bar"); + /// s.reverse_graphemes(); + /// assert_eq!(s, "rab☃oof".as_bytes()); + /// ``` + /// + /// This example shows how this correctly handles grapheme clusters, + /// unlike `reverse_chars`. + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let mut s = >::from("résumé"); + /// s.reverse_graphemes(); + /// assert_eq!(s, "émusér".as_bytes()); + /// ``` + #[cfg(feature = "unicode")] + #[inline] + fn reverse_graphemes(&mut self) { + use unicode::decode_grapheme; + + let mut i = 0; + loop { + let (_, size) = decode_grapheme(&self.as_bytes()[i..]); + if size == 0 { + break; + } + if size > 1 { + self.as_bytes_mut()[i..i + size].reverse_bytes(); + } + i += size; + } + self.reverse_bytes(); + } + + /// Returns true if and only if every byte in this byte string is ASCII. + /// + /// ASCII is an encoding that defines 128 codepoints. A byte corresponds to + /// an ASCII codepoint if and only if it is in the inclusive range + /// `[0, 127]`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// assert!(B("abc").is_ascii()); + /// assert!(!B("☃βツ").is_ascii()); + /// assert!(!B(b"\xFF").is_ascii()); + /// ``` + #[inline] + fn is_ascii(&self) -> bool { + ascii::first_non_ascii_byte(self.as_bytes()) == self.as_bytes().len() + } + + /// Returns true if and only if the entire byte string is valid UTF-8. + /// + /// If you need location information about where a byte string's first + /// invalid UTF-8 byte is, then use the [`to_str`](#method.to_str) method. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// assert!(B("abc").is_utf8()); + /// assert!(B("☃βツ").is_utf8()); + /// // invalid bytes + /// assert!(!B(b"abc\xFF").is_utf8()); + /// // surrogate encoding + /// assert!(!B(b"\xED\xA0\x80").is_utf8()); + /// // incomplete sequence + /// assert!(!B(b"\xF0\x9D\x9Ca").is_utf8()); + /// // overlong sequence + /// assert!(!B(b"\xF0\x82\x82\xAC").is_utf8()); + /// ``` + #[inline] + fn is_utf8(&self) -> bool { + utf8::validate(self.as_bytes()).is_ok() + } + + /// Returns the last byte in this byte string, if it's non-empty. If this + /// byte string is empty, this returns `None`. + /// + /// Note that this is like the generic `[u8]::last`, except this returns + /// the byte by value instead of a reference to the byte. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// assert_eq!(Some(b'z'), b"baz".last_byte()); + /// assert_eq!(None, b"".last_byte()); + /// ``` + #[inline] + fn last_byte(&self) -> Option { + let bytes = self.as_bytes(); + bytes.get(bytes.len().saturating_sub(1)).map(|&b| b) + } + + /// Returns the index of the first non-ASCII byte in this byte string (if + /// any such indices exist). Specifically, it returns the index of the + /// first byte with a value greater than or equal to `0x80`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{ByteSlice, B}; + /// + /// assert_eq!(Some(3), b"abc\xff".find_non_ascii_byte()); + /// assert_eq!(None, b"abcde".find_non_ascii_byte()); + /// assert_eq!(Some(0), B("😀").find_non_ascii_byte()); + /// ``` + #[inline] + fn find_non_ascii_byte(&self) -> Option { + let index = ascii::first_non_ascii_byte(self.as_bytes()); + if index == self.as_bytes().len() { + None + } else { + Some(index) + } + } + + /// Copies elements from one part of the slice to another part of itself, + /// where the parts may be overlapping. + /// + /// `src` is the range within this byte string to copy from, while `dest` + /// is the starting index of the range within this byte string to copy to. + /// The length indicated by `src` must be less than or equal to the number + /// of bytes from `dest` to the end of the byte string. + /// + /// # Panics + /// + /// Panics if either range is out of bounds, or if `src` is too big to fit + /// into `dest`, or if the end of `src` is before the start. + /// + /// # Examples + /// + /// Copying four bytes within a byte string: + /// + /// ``` + /// use bstr::{B, ByteSlice}; + /// + /// let mut buf = *b"Hello, World!"; + /// let s = &mut buf; + /// s.copy_within_str(1..5, 8); + /// assert_eq!(s, B("Hello, Wello!")); + /// ``` + #[inline] + fn copy_within_str(&mut self, src: R, dest: usize) + where + R: ops::RangeBounds, + { + // TODO: Deprecate this once slice::copy_within stabilizes. + let src_start = match src.start_bound() { + ops::Bound::Included(&n) => n, + ops::Bound::Excluded(&n) => { + n.checked_add(1).expect("attempted to index slice beyond max") + } + ops::Bound::Unbounded => 0, + }; + let src_end = match src.end_bound() { + ops::Bound::Included(&n) => { + n.checked_add(1).expect("attempted to index slice beyond max") + } + ops::Bound::Excluded(&n) => n, + ops::Bound::Unbounded => self.as_bytes().len(), + }; + assert!(src_start <= src_end, "src end is before src start"); + assert!(src_end <= self.as_bytes().len(), "src is out of bounds"); + let count = src_end - src_start; + assert!( + dest <= self.as_bytes().len() - count, + "dest is out of bounds", + ); + + // SAFETY: This is safe because we use ptr::copy to handle overlapping + // copies, and is also safe because we've checked all the bounds above. + // Finally, we are only dealing with u8 data, which is Copy, which + // means we can copy without worrying about ownership/destructors. + unsafe { + ptr::copy( + self.as_bytes().get_unchecked(src_start), + self.as_bytes_mut().get_unchecked_mut(dest), + count, + ); + } + } +} + +/// A single substring searcher fixed to a particular needle. +/// +/// The purpose of this type is to permit callers to construct a substring +/// searcher that can be used to search haystacks without the overhead of +/// constructing the searcher in the first place. This is a somewhat niche +/// concern when it's necessary to re-use the same needle to search multiple +/// different haystacks with as little overhead as possible. In general, using +/// [`ByteSlice::find`](trait.ByteSlice.html#method.find) +/// or +/// [`ByteSlice::find_iter`](trait.ByteSlice.html#method.find_iter) +/// is good enough, but `Finder` is useful when you can meaningfully observe +/// searcher construction time in a profile. +/// +/// When the `std` feature is enabled, then this type has an `into_owned` +/// version which permits building a `Finder` that is not connected to the +/// lifetime of its needle. +#[derive(Clone, Debug)] +pub struct Finder<'a> { + searcher: TwoWay<'a>, +} + +impl<'a> Finder<'a> { + /// Create a new finder for the given needle. + #[inline] + pub fn new>(needle: &'a B) -> Finder<'a> { + Finder { searcher: TwoWay::forward(needle.as_ref()) } + } + + /// Convert this finder into its owned variant, such that it no longer + /// borrows the needle. + /// + /// If this is already an owned finder, then this is a no-op. Otherwise, + /// this copies the needle. + /// + /// This is only available when the `std` feature is enabled. + #[cfg(feature = "std")] + #[inline] + pub fn into_owned(self) -> Finder<'static> { + Finder { searcher: self.searcher.into_owned() } + } + + /// Returns the needle that this finder searches for. + /// + /// Note that the lifetime of the needle returned is tied to the lifetime + /// of the finder, and may be shorter than the `'a` lifetime. Namely, a + /// finder's needle can be either borrowed or owned, so the lifetime of the + /// needle returned must necessarily be the shorter of the two. + #[inline] + pub fn needle(&self) -> &[u8] { + self.searcher.needle() + } + + /// Returns the index of the first occurrence of this needle in the given + /// haystack. + /// + /// The haystack may be any type that can be cheaply converted into a + /// `&[u8]`. This includes, but is not limited to, `&str` and `&[u8]`. + /// + /// # Complexity + /// + /// This routine is guaranteed to have worst case linear time complexity + /// with respect to both the needle and the haystack. That is, this runs + /// in `O(needle.len() + haystack.len())` time. + /// + /// This routine is also guaranteed to have worst case constant space + /// complexity. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::Finder; + /// + /// let haystack = "foo bar baz"; + /// assert_eq!(Some(0), Finder::new("foo").find(haystack)); + /// assert_eq!(Some(4), Finder::new("bar").find(haystack)); + /// assert_eq!(None, Finder::new("quux").find(haystack)); + /// ``` + #[inline] + pub fn find>(&self, haystack: B) -> Option { + self.searcher.find(haystack.as_ref()) + } +} + +/// A single substring reverse searcher fixed to a particular needle. +/// +/// The purpose of this type is to permit callers to construct a substring +/// searcher that can be used to search haystacks without the overhead of +/// constructing the searcher in the first place. This is a somewhat niche +/// concern when it's necessary to re-use the same needle to search multiple +/// different haystacks with as little overhead as possible. In general, using +/// [`ByteSlice::rfind`](trait.ByteSlice.html#method.rfind) +/// or +/// [`ByteSlice::rfind_iter`](trait.ByteSlice.html#method.rfind_iter) +/// is good enough, but `FinderReverse` is useful when you can meaningfully +/// observe searcher construction time in a profile. +/// +/// When the `std` feature is enabled, then this type has an `into_owned` +/// version which permits building a `FinderReverse` that is not connected to +/// the lifetime of its needle. +#[derive(Clone, Debug)] +pub struct FinderReverse<'a> { + searcher: TwoWay<'a>, +} + +impl<'a> FinderReverse<'a> { + /// Create a new reverse finder for the given needle. + #[inline] + pub fn new>(needle: &'a B) -> FinderReverse<'a> { + FinderReverse { searcher: TwoWay::reverse(needle.as_ref()) } + } + + /// Convert this finder into its owned variant, such that it no longer + /// borrows the needle. + /// + /// If this is already an owned finder, then this is a no-op. Otherwise, + /// this copies the needle. + /// + /// This is only available when the `std` feature is enabled. + #[cfg(feature = "std")] + #[inline] + pub fn into_owned(self) -> FinderReverse<'static> { + FinderReverse { searcher: self.searcher.into_owned() } + } + + /// Returns the needle that this finder searches for. + /// + /// Note that the lifetime of the needle returned is tied to the lifetime + /// of this finder, and may be shorter than the `'a` lifetime. Namely, + /// a finder's needle can be either borrowed or owned, so the lifetime of + /// the needle returned must necessarily be the shorter of the two. + #[inline] + pub fn needle(&self) -> &[u8] { + self.searcher.needle() + } + + /// Returns the index of the last occurrence of this needle in the given + /// haystack. + /// + /// The haystack may be any type that can be cheaply converted into a + /// `&[u8]`. This includes, but is not limited to, `&str` and `&[u8]`. + /// + /// # Complexity + /// + /// This routine is guaranteed to have worst case linear time complexity + /// with respect to both the needle and the haystack. That is, this runs + /// in `O(needle.len() + haystack.len())` time. + /// + /// This routine is also guaranteed to have worst case constant space + /// complexity. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::FinderReverse; + /// + /// let haystack = "foo bar baz"; + /// assert_eq!(Some(0), FinderReverse::new("foo").rfind(haystack)); + /// assert_eq!(Some(4), FinderReverse::new("bar").rfind(haystack)); + /// assert_eq!(None, FinderReverse::new("quux").rfind(haystack)); + /// ``` + #[inline] + pub fn rfind>(&self, haystack: B) -> Option { + self.searcher.rfind(haystack.as_ref()) + } +} + +/// An iterator over non-overlapping substring matches. +/// +/// Matches are reported by the byte offset at which they begin. +/// +/// `'a` is the shorter of two lifetimes: the byte string being searched or the +/// byte string being looked for. +#[derive(Debug)] +pub struct Find<'a> { + haystack: &'a [u8], + prestate: PrefilterState, + searcher: TwoWay<'a>, + pos: usize, +} + +impl<'a> Find<'a> { + fn new(haystack: &'a [u8], needle: &'a [u8]) -> Find<'a> { + let searcher = TwoWay::forward(needle); + let prestate = searcher.prefilter_state(); + Find { haystack, prestate, searcher, pos: 0 } + } +} + +impl<'a> Iterator for Find<'a> { + type Item = usize; + + #[inline] + fn next(&mut self) -> Option { + if self.pos > self.haystack.len() { + return None; + } + let result = self + .searcher + .find_with(&mut self.prestate, &self.haystack[self.pos..]); + match result { + None => None, + Some(i) => { + let pos = self.pos + i; + self.pos = pos + cmp::max(1, self.searcher.needle().len()); + Some(pos) + } + } + } +} + +/// An iterator over non-overlapping substring matches in reverse. +/// +/// Matches are reported by the byte offset at which they begin. +/// +/// `'a` is the shorter of two lifetimes: the byte string being searched or the +/// byte string being looked for. +#[derive(Debug)] +pub struct FindReverse<'a> { + haystack: &'a [u8], + prestate: PrefilterState, + searcher: TwoWay<'a>, + /// When searching with an empty needle, this gets set to `None` after + /// we've yielded the last element at `0`. + pos: Option, +} + +impl<'a> FindReverse<'a> { + fn new(haystack: &'a [u8], needle: &'a [u8]) -> FindReverse<'a> { + let searcher = TwoWay::reverse(needle); + let prestate = searcher.prefilter_state(); + let pos = Some(haystack.len()); + FindReverse { haystack, prestate, searcher, pos } + } + + fn haystack(&self) -> &'a [u8] { + self.haystack + } + + fn needle(&self) -> &[u8] { + self.searcher.needle() + } +} + +impl<'a> Iterator for FindReverse<'a> { + type Item = usize; + + #[inline] + fn next(&mut self) -> Option { + let pos = match self.pos { + None => return None, + Some(pos) => pos, + }; + let result = self + .searcher + .rfind_with(&mut self.prestate, &self.haystack[..pos]); + match result { + None => None, + Some(i) => { + if pos == i { + self.pos = pos.checked_sub(1); + } else { + self.pos = Some(i); + } + Some(i) + } + } + } +} + +/// An iterator over the bytes in a byte string. +/// +/// `'a` is the lifetime of the byte string being traversed. +#[derive(Clone, Debug)] +pub struct Bytes<'a> { + it: slice::Iter<'a, u8>, +} + +impl<'a> Bytes<'a> { + /// Views the remaining underlying data as a subslice of the original data. + /// This has the same lifetime as the original slice, + /// and so the iterator can continue to be used while this exists. + #[inline] + pub fn as_slice(&self) -> &'a [u8] { + self.it.as_slice() + } +} + +impl<'a> Iterator for Bytes<'a> { + type Item = u8; + + #[inline] + fn next(&mut self) -> Option { + self.it.next().map(|&b| b) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.it.size_hint() + } +} + +impl<'a> DoubleEndedIterator for Bytes<'a> { + #[inline] + fn next_back(&mut self) -> Option { + self.it.next_back().map(|&b| b) + } +} + +impl<'a> ExactSizeIterator for Bytes<'a> { + #[inline] + fn len(&self) -> usize { + self.it.len() + } +} + +impl<'a> iter::FusedIterator for Bytes<'a> {} + +/// An iterator over the fields in a byte string, separated by whitespace. +/// +/// This iterator splits on contiguous runs of whitespace, such that the fields +/// in `foo\t\t\n \nbar` are `foo` and `bar`. +/// +/// `'a` is the lifetime of the byte string being split. +#[derive(Debug)] +pub struct Fields<'a> { + it: FieldsWith<'a, fn(char) -> bool>, +} + +impl<'a> Fields<'a> { + fn new(bytes: &'a [u8]) -> Fields<'a> { + Fields { it: bytes.fields_with(|ch| ch.is_whitespace()) } + } +} + +impl<'a> Iterator for Fields<'a> { + type Item = &'a [u8]; + + #[inline] + fn next(&mut self) -> Option<&'a [u8]> { + self.it.next() + } +} + +/// An iterator over fields in the byte string, separated by a predicate over +/// codepoints. +/// +/// This iterator splits a byte string based on its predicate function such +/// that the elements returned are separated by contiguous runs of codepoints +/// for which the predicate returns true. +/// +/// `'a` is the lifetime of the byte string being split, while `F` is the type +/// of the predicate, i.e., `FnMut(char) -> bool`. +#[derive(Debug)] +pub struct FieldsWith<'a, F> { + f: F, + bytes: &'a [u8], + chars: CharIndices<'a>, +} + +impl<'a, F: FnMut(char) -> bool> FieldsWith<'a, F> { + fn new(bytes: &'a [u8], f: F) -> FieldsWith<'a, F> { + FieldsWith { f, bytes, chars: bytes.char_indices() } + } +} + +impl<'a, F: FnMut(char) -> bool> Iterator for FieldsWith<'a, F> { + type Item = &'a [u8]; + + #[inline] + fn next(&mut self) -> Option<&'a [u8]> { + let (start, mut end); + loop { + match self.chars.next() { + None => return None, + Some((s, e, ch)) => { + if !(self.f)(ch) { + start = s; + end = e; + break; + } + } + } + } + while let Some((_, e, ch)) = self.chars.next() { + if (self.f)(ch) { + break; + } + end = e; + } + Some(&self.bytes[start..end]) + } +} + +/// An iterator over substrings in a byte string, split by a separator. +/// +/// `'a` is the lifetime of the byte string being split. +#[derive(Debug)] +pub struct Split<'a> { + finder: Find<'a>, + /// The end position of the previous match of our splitter. The element + /// we yield corresponds to the substring starting at `last` up to the + /// beginning of the next match of the splitter. + last: usize, + /// Only set when iteration is complete. A corner case here is when a + /// splitter is matched at the end of the haystack. At that point, we still + /// need to yield an empty string following it. + done: bool, +} + +impl<'a> Split<'a> { + fn new(haystack: &'a [u8], splitter: &'a [u8]) -> Split<'a> { + let finder = haystack.find_iter(splitter); + Split { finder, last: 0, done: false } + } +} + +impl<'a> Iterator for Split<'a> { + type Item = &'a [u8]; + + #[inline] + fn next(&mut self) -> Option<&'a [u8]> { + let haystack = self.finder.haystack; + match self.finder.next() { + Some(start) => { + let next = &haystack[self.last..start]; + self.last = start + self.finder.searcher.needle().len(); + Some(next) + } + None => { + if self.last >= haystack.len() { + if !self.done { + self.done = true; + Some(b"") + } else { + None + } + } else { + let s = &haystack[self.last..]; + self.last = haystack.len(); + self.done = true; + Some(s) + } + } + } + } +} + +/// An iterator over substrings in a byte string, split by a separator, in +/// reverse. +/// +/// `'a` is the lifetime of the byte string being split, while `F` is the type +/// of the predicate, i.e., `FnMut(char) -> bool`. +#[derive(Debug)] +pub struct SplitReverse<'a> { + finder: FindReverse<'a>, + /// The end position of the previous match of our splitter. The element + /// we yield corresponds to the substring starting at `last` up to the + /// beginning of the next match of the splitter. + last: usize, + /// Only set when iteration is complete. A corner case here is when a + /// splitter is matched at the end of the haystack. At that point, we still + /// need to yield an empty string following it. + done: bool, +} + +impl<'a> SplitReverse<'a> { + fn new(haystack: &'a [u8], splitter: &'a [u8]) -> SplitReverse<'a> { + let finder = haystack.rfind_iter(splitter); + SplitReverse { finder, last: haystack.len(), done: false } + } +} + +impl<'a> Iterator for SplitReverse<'a> { + type Item = &'a [u8]; + + #[inline] + fn next(&mut self) -> Option<&'a [u8]> { + let haystack = self.finder.haystack(); + match self.finder.next() { + Some(start) => { + let nlen = self.finder.needle().len(); + let next = &haystack[start + nlen..self.last]; + self.last = start; + Some(next) + } + None => { + if self.last == 0 { + if !self.done { + self.done = true; + Some(b"") + } else { + None + } + } else { + let s = &haystack[..self.last]; + self.last = 0; + self.done = true; + Some(s) + } + } + } + } +} + +/// An iterator over at most `n` substrings in a byte string, split by a +/// separator. +/// +/// `'a` is the lifetime of the byte string being split, while `F` is the type +/// of the predicate, i.e., `FnMut(char) -> bool`. +#[derive(Debug)] +pub struct SplitN<'a> { + split: Split<'a>, + limit: usize, + count: usize, +} + +impl<'a> SplitN<'a> { + fn new( + haystack: &'a [u8], + splitter: &'a [u8], + limit: usize, + ) -> SplitN<'a> { + let split = haystack.split_str(splitter); + SplitN { split, limit, count: 0 } + } +} + +impl<'a> Iterator for SplitN<'a> { + type Item = &'a [u8]; + + #[inline] + fn next(&mut self) -> Option<&'a [u8]> { + self.count += 1; + if self.count > self.limit || self.split.done { + None + } else if self.count == self.limit { + Some(&self.split.finder.haystack[self.split.last..]) + } else { + self.split.next() + } + } +} + +/// An iterator over at most `n` substrings in a byte string, split by a +/// separator, in reverse. +/// +/// `'a` is the lifetime of the byte string being split, while `F` is the type +/// of the predicate, i.e., `FnMut(char) -> bool`. +#[derive(Debug)] +pub struct SplitNReverse<'a> { + split: SplitReverse<'a>, + limit: usize, + count: usize, +} + +impl<'a> SplitNReverse<'a> { + fn new( + haystack: &'a [u8], + splitter: &'a [u8], + limit: usize, + ) -> SplitNReverse<'a> { + let split = haystack.rsplit_str(splitter); + SplitNReverse { split, limit, count: 0 } + } +} + +impl<'a> Iterator for SplitNReverse<'a> { + type Item = &'a [u8]; + + #[inline] + fn next(&mut self) -> Option<&'a [u8]> { + self.count += 1; + if self.count > self.limit || self.split.done { + None + } else if self.count == self.limit { + Some(&self.split.finder.haystack()[..self.split.last]) + } else { + self.split.next() + } + } +} + +/// An iterator over all lines in a byte string, without their terminators. +/// +/// For this iterator, the only line terminators recognized are `\r\n` and +/// `\n`. +/// +/// `'a` is the lifetime of the byte string being iterated over. +pub struct Lines<'a> { + it: LinesWithTerminator<'a>, +} + +impl<'a> Lines<'a> { + fn new(bytes: &'a [u8]) -> Lines<'a> { + Lines { it: LinesWithTerminator::new(bytes) } + } +} + +impl<'a> Iterator for Lines<'a> { + type Item = &'a [u8]; + + #[inline] + fn next(&mut self) -> Option<&'a [u8]> { + let mut line = self.it.next()?; + if line.last_byte() == Some(b'\n') { + line = &line[..line.len() - 1]; + if line.last_byte() == Some(b'\r') { + line = &line[..line.len() - 1]; + } + } + Some(line) + } +} + +/// An iterator over all lines in a byte string, including their terminators. +/// +/// For this iterator, the only line terminator recognized is `\n`. (Since +/// line terminators are included, this also handles `\r\n` line endings.) +/// +/// Line terminators are only included if they are present in the original +/// byte string. For example, the last line in a byte string may not end with +/// a line terminator. +/// +/// Concatenating all elements yielded by this iterator is guaranteed to yield +/// the original byte string. +/// +/// `'a` is the lifetime of the byte string being iterated over. +pub struct LinesWithTerminator<'a> { + bytes: &'a [u8], +} + +impl<'a> LinesWithTerminator<'a> { + fn new(bytes: &'a [u8]) -> LinesWithTerminator<'a> { + LinesWithTerminator { bytes } + } +} + +impl<'a> Iterator for LinesWithTerminator<'a> { + type Item = &'a [u8]; + + #[inline] + fn next(&mut self) -> Option<&'a [u8]> { + match self.bytes.find_byte(b'\n') { + None if self.bytes.is_empty() => None, + None => { + let line = self.bytes; + self.bytes = b""; + Some(line) + } + Some(end) => { + let line = &self.bytes[..end + 1]; + self.bytes = &self.bytes[end + 1..]; + Some(line) + } + } + } +} + +#[cfg(test)] +mod tests { + use ext_slice::{ByteSlice, B}; + use tests::LOSSY_TESTS; + + #[test] + fn to_str_lossy() { + for (i, &(expected, input)) in LOSSY_TESTS.iter().enumerate() { + let got = B(input).to_str_lossy(); + assert_eq!( + expected.as_bytes(), + got.as_bytes(), + "to_str_lossy(ith: {:?}, given: {:?})", + i, + input, + ); + + let mut got = String::new(); + B(input).to_str_lossy_into(&mut got); + assert_eq!( + expected.as_bytes(), + got.as_bytes(), + "to_str_lossy_into", + ); + + let got = String::from_utf8_lossy(input); + assert_eq!(expected.as_bytes(), got.as_bytes(), "std"); + } + } + + #[test] + #[should_panic] + fn copy_within_fail1() { + let mut buf = *b"foobar"; + let s = &mut buf; + s.copy_within_str(0..2, 5); + } + + #[test] + #[should_panic] + fn copy_within_fail2() { + let mut buf = *b"foobar"; + let s = &mut buf; + s.copy_within_str(3..2, 0); + } + + #[test] + #[should_panic] + fn copy_within_fail3() { + let mut buf = *b"foobar"; + let s = &mut buf; + s.copy_within_str(5..7, 0); + } + + #[test] + #[should_panic] + fn copy_within_fail4() { + let mut buf = *b"foobar"; + let s = &mut buf; + s.copy_within_str(0..1, 6); + } +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/ext_vec.rs b/third_party/cargo/vendor/bstr-0.2.15/src/ext_vec.rs new file mode 100644 index 0000000..6f6db56 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/ext_vec.rs @@ -0,0 +1,1108 @@ +#![allow(unused_imports)] + +use std::borrow::Cow; +use std::error; +use std::ffi::{OsStr, OsString}; +use std::fmt; +use std::iter; +use std::ops; +use std::path::{Path, PathBuf}; +use std::ptr; +use std::str; +use std::vec; + +use ext_slice::ByteSlice; +use utf8::{self, Utf8Error}; + +/// Concatenate the elements given by the iterator together into a single +/// `Vec`. +/// +/// The elements may be any type that can be cheaply converted into an `&[u8]`. +/// This includes, but is not limited to, `&str`, `&BStr` and `&[u8]` itself. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use bstr; +/// +/// let s = bstr::concat(&["foo", "bar", "baz"]); +/// assert_eq!(s, "foobarbaz".as_bytes()); +/// ``` +#[inline] +pub fn concat(elements: I) -> Vec +where + T: AsRef<[u8]>, + I: IntoIterator, +{ + let mut dest = vec![]; + for element in elements { + dest.push_str(element); + } + dest +} + +/// Join the elements given by the iterator with the given separator into a +/// single `Vec`. +/// +/// Both the separator and the elements may be any type that can be cheaply +/// converted into an `&[u8]`. This includes, but is not limited to, +/// `&str`, `&BStr` and `&[u8]` itself. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use bstr; +/// +/// let s = bstr::join(",", &["foo", "bar", "baz"]); +/// assert_eq!(s, "foo,bar,baz".as_bytes()); +/// ``` +#[inline] +pub fn join(separator: B, elements: I) -> Vec +where + B: AsRef<[u8]>, + T: AsRef<[u8]>, + I: IntoIterator, +{ + let mut it = elements.into_iter(); + let mut dest = vec![]; + match it.next() { + None => return dest, + Some(first) => { + dest.push_str(first); + } + } + for element in it { + dest.push_str(&separator); + dest.push_str(element); + } + dest +} + +impl ByteVec for Vec { + #[inline] + fn as_vec(&self) -> &Vec { + self + } + + #[inline] + fn as_vec_mut(&mut self) -> &mut Vec { + self + } + + #[inline] + fn into_vec(self) -> Vec { + self + } +} + +/// Ensure that callers cannot implement `ByteSlice` by making an +/// umplementable trait its super trait. +pub trait Sealed {} +impl Sealed for Vec {} + +/// A trait that extends `Vec` with string oriented methods. +/// +/// Note that when using the constructor methods, such as +/// `ByteVec::from_slice`, one should actually call them using the concrete +/// type. For example: +/// +/// ``` +/// use bstr::{B, ByteVec}; +/// +/// let s = Vec::from_slice(b"abc"); // NOT ByteVec::from_slice("...") +/// assert_eq!(s, B("abc")); +/// ``` +pub trait ByteVec: Sealed { + /// A method for accessing the raw vector bytes of this type. This is + /// always a no-op and callers shouldn't care about it. This only exists + /// for making the extension trait work. + #[doc(hidden)] + fn as_vec(&self) -> &Vec; + + /// A method for accessing the raw vector bytes of this type, mutably. This + /// is always a no-op and callers shouldn't care about it. This only exists + /// for making the extension trait work. + #[doc(hidden)] + fn as_vec_mut(&mut self) -> &mut Vec; + + /// A method for consuming ownership of this vector. This is always a no-op + /// and callers shouldn't care about it. This only exists for making the + /// extension trait work. + #[doc(hidden)] + fn into_vec(self) -> Vec + where + Self: Sized; + + /// Create a new owned byte string from the given byte slice. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteVec}; + /// + /// let s = Vec::from_slice(b"abc"); + /// assert_eq!(s, B("abc")); + /// ``` + #[inline] + fn from_slice>(bytes: B) -> Vec { + bytes.as_ref().to_vec() + } + + /// Create a new byte string from an owned OS string. + /// + /// On Unix, this always succeeds and is zero cost. On non-Unix systems, + /// this returns the original OS string if it is not valid UTF-8. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::ffi::OsString; + /// + /// use bstr::{B, ByteVec}; + /// + /// let os_str = OsString::from("foo"); + /// let bs = Vec::from_os_string(os_str).expect("valid UTF-8"); + /// assert_eq!(bs, B("foo")); + /// ``` + #[inline] + fn from_os_string(os_str: OsString) -> Result, OsString> { + #[cfg(unix)] + #[inline] + fn imp(os_str: OsString) -> Result, OsString> { + use std::os::unix::ffi::OsStringExt; + + Ok(Vec::from(os_str.into_vec())) + } + + #[cfg(not(unix))] + #[inline] + fn imp(os_str: OsString) -> Result, OsString> { + os_str.into_string().map(Vec::from) + } + + imp(os_str) + } + + /// Lossily create a new byte string from an OS string slice. + /// + /// On Unix, this always succeeds, is zero cost and always returns a slice. + /// On non-Unix systems, this does a UTF-8 check. If the given OS string + /// slice is not valid UTF-8, then it is lossily decoded into valid UTF-8 + /// (with invalid bytes replaced by the Unicode replacement codepoint). + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::ffi::OsStr; + /// + /// use bstr::{B, ByteVec}; + /// + /// let os_str = OsStr::new("foo"); + /// let bs = Vec::from_os_str_lossy(os_str); + /// assert_eq!(bs, B("foo")); + /// ``` + #[inline] + fn from_os_str_lossy<'a>(os_str: &'a OsStr) -> Cow<'a, [u8]> { + #[cfg(unix)] + #[inline] + fn imp<'a>(os_str: &'a OsStr) -> Cow<'a, [u8]> { + use std::os::unix::ffi::OsStrExt; + + Cow::Borrowed(os_str.as_bytes()) + } + + #[cfg(not(unix))] + #[inline] + fn imp<'a>(os_str: &'a OsStr) -> Cow<'a, [u8]> { + match os_str.to_string_lossy() { + Cow::Borrowed(x) => Cow::Borrowed(x.as_bytes()), + Cow::Owned(x) => Cow::Owned(Vec::from(x)), + } + } + + imp(os_str) + } + + /// Create a new byte string from an owned file path. + /// + /// On Unix, this always succeeds and is zero cost. On non-Unix systems, + /// this returns the original path if it is not valid UTF-8. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::path::PathBuf; + /// + /// use bstr::{B, ByteVec}; + /// + /// let path = PathBuf::from("foo"); + /// let bs = Vec::from_path_buf(path).expect("must be valid UTF-8"); + /// assert_eq!(bs, B("foo")); + /// ``` + #[inline] + fn from_path_buf(path: PathBuf) -> Result, PathBuf> { + Vec::from_os_string(path.into_os_string()).map_err(PathBuf::from) + } + + /// Lossily create a new byte string from a file path. + /// + /// On Unix, this always succeeds, is zero cost and always returns a slice. + /// On non-Unix systems, this does a UTF-8 check. If the given path is not + /// valid UTF-8, then it is lossily decoded into valid UTF-8 (with invalid + /// bytes replaced by the Unicode replacement codepoint). + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::path::Path; + /// + /// use bstr::{B, ByteVec}; + /// + /// let path = Path::new("foo"); + /// let bs = Vec::from_path_lossy(path); + /// assert_eq!(bs, B("foo")); + /// ``` + #[inline] + fn from_path_lossy<'a>(path: &'a Path) -> Cow<'a, [u8]> { + Vec::from_os_str_lossy(path.as_os_str()) + } + + /// Appends the given byte to the end of this byte string. + /// + /// Note that this is equivalent to the generic `Vec::push` method. This + /// method is provided to permit callers to explicitly differentiate + /// between pushing bytes, codepoints and strings. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteVec; + /// + /// let mut s = >::from("abc"); + /// s.push_byte(b'\xE2'); + /// s.push_byte(b'\x98'); + /// s.push_byte(b'\x83'); + /// assert_eq!(s, "abc☃".as_bytes()); + /// ``` + #[inline] + fn push_byte(&mut self, byte: u8) { + self.as_vec_mut().push(byte); + } + + /// Appends the given `char` to the end of this byte string. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteVec; + /// + /// let mut s = >::from("abc"); + /// s.push_char('1'); + /// s.push_char('2'); + /// s.push_char('3'); + /// assert_eq!(s, "abc123".as_bytes()); + /// ``` + #[inline] + fn push_char(&mut self, ch: char) { + if ch.len_utf8() == 1 { + self.push_byte(ch as u8); + return; + } + self.as_vec_mut() + .extend_from_slice(ch.encode_utf8(&mut [0; 4]).as_bytes()); + } + + /// Appends the given slice to the end of this byte string. This accepts + /// any type that be converted to a `&[u8]`. This includes, but is not + /// limited to, `&str`, `&BStr`, and of course, `&[u8]` itself. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteVec; + /// + /// let mut s = >::from("abc"); + /// s.push_str(b"123"); + /// assert_eq!(s, "abc123".as_bytes()); + /// ``` + #[inline] + fn push_str>(&mut self, bytes: B) { + self.as_vec_mut().extend_from_slice(bytes.as_ref()); + } + + /// Converts a `Vec` into a `String` if and only if this byte string is + /// valid UTF-8. + /// + /// If it is not valid UTF-8, then a + /// [`FromUtf8Error`](struct.FromUtf8Error.html) + /// is returned. (This error can be used to examine why UTF-8 validation + /// failed, or to regain the original byte string.) + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteVec; + /// + /// # fn example() -> Result<(), Box> { + /// let bytes = Vec::from("hello"); + /// let string = bytes.into_string()?; + /// + /// assert_eq!("hello", string); + /// # Ok(()) }; example().unwrap() + /// ``` + /// + /// If this byte string is not valid UTF-8, then an error will be returned. + /// That error can then be used to inspect the location at which invalid + /// UTF-8 was found, or to regain the original byte string: + /// + /// ``` + /// use bstr::{B, ByteVec}; + /// + /// let bytes = Vec::from_slice(b"foo\xFFbar"); + /// let err = bytes.into_string().unwrap_err(); + /// + /// assert_eq!(err.utf8_error().valid_up_to(), 3); + /// assert_eq!(err.utf8_error().error_len(), Some(1)); + /// + /// // At no point in this example is an allocation performed. + /// let bytes = Vec::from(err.into_vec()); + /// assert_eq!(bytes, B(b"foo\xFFbar")); + /// ``` + #[inline] + fn into_string(self) -> Result + where + Self: Sized, + { + match utf8::validate(self.as_vec()) { + Err(err) => Err(FromUtf8Error { original: self.into_vec(), err }), + Ok(()) => { + // SAFETY: This is safe because of the guarantees provided by + // utf8::validate. + unsafe { Ok(self.into_string_unchecked()) } + } + } + } + + /// Lossily converts a `Vec` into a `String`. If this byte string + /// contains invalid UTF-8, then the invalid bytes are replaced with the + /// Unicode replacement codepoint. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteVec; + /// + /// let bytes = Vec::from_slice(b"foo\xFFbar"); + /// let string = bytes.into_string_lossy(); + /// assert_eq!(string, "foo\u{FFFD}bar"); + /// ``` + #[inline] + fn into_string_lossy(self) -> String + where + Self: Sized, + { + match self.as_vec().to_str_lossy() { + Cow::Borrowed(_) => { + // SAFETY: to_str_lossy() returning a Cow::Borrowed guarantees + // the entire string is valid utf8. + unsafe { self.into_string_unchecked() } + } + Cow::Owned(s) => s, + } + } + + /// Unsafely convert this byte string into a `String`, without checking for + /// valid UTF-8. + /// + /// # Safety + /// + /// Callers *must* ensure that this byte string is valid UTF-8 before + /// calling this method. Converting a byte string into a `String` that is + /// not valid UTF-8 is considered undefined behavior. + /// + /// This routine is useful in performance sensitive contexts where the + /// UTF-8 validity of the byte string is already known and it is + /// undesirable to pay the cost of an additional UTF-8 validation check + /// that [`into_string`](#method.into_string) performs. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteVec; + /// + /// // SAFETY: This is safe because string literals are guaranteed to be + /// // valid UTF-8 by the Rust compiler. + /// let s = unsafe { Vec::from("☃βツ").into_string_unchecked() }; + /// assert_eq!("☃βツ", s); + /// ``` + #[inline] + unsafe fn into_string_unchecked(self) -> String + where + Self: Sized, + { + String::from_utf8_unchecked(self.into_vec()) + } + + /// Converts this byte string into an OS string, in place. + /// + /// On Unix, this always succeeds and is zero cost. On non-Unix systems, + /// this returns the original byte string if it is not valid UTF-8. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::ffi::OsStr; + /// + /// use bstr::ByteVec; + /// + /// let bs = Vec::from("foo"); + /// let os_str = bs.into_os_string().expect("should be valid UTF-8"); + /// assert_eq!(os_str, OsStr::new("foo")); + /// ``` + #[inline] + fn into_os_string(self) -> Result> + where + Self: Sized, + { + #[cfg(unix)] + #[inline] + fn imp(v: Vec) -> Result> { + use std::os::unix::ffi::OsStringExt; + + Ok(OsString::from_vec(v)) + } + + #[cfg(not(unix))] + #[inline] + fn imp(v: Vec) -> Result> { + match v.into_string() { + Ok(s) => Ok(OsString::from(s)), + Err(err) => Err(err.into_vec()), + } + } + + imp(self.into_vec()) + } + + /// Lossily converts this byte string into an OS string, in place. + /// + /// On Unix, this always succeeds and is zero cost. On non-Unix systems, + /// this will perform a UTF-8 check and lossily convert this byte string + /// into valid UTF-8 using the Unicode replacement codepoint. + /// + /// Note that this can prevent the correct roundtripping of file paths on + /// non-Unix systems such as Windows, where file paths are an arbitrary + /// sequence of 16-bit integers. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteVec; + /// + /// let bs = Vec::from_slice(b"foo\xFFbar"); + /// let os_str = bs.into_os_string_lossy(); + /// assert_eq!(os_str.to_string_lossy(), "foo\u{FFFD}bar"); + /// ``` + #[inline] + fn into_os_string_lossy(self) -> OsString + where + Self: Sized, + { + #[cfg(unix)] + #[inline] + fn imp(v: Vec) -> OsString { + use std::os::unix::ffi::OsStringExt; + + OsString::from_vec(v) + } + + #[cfg(not(unix))] + #[inline] + fn imp(v: Vec) -> OsString { + OsString::from(v.into_string_lossy()) + } + + imp(self.into_vec()) + } + + /// Converts this byte string into an owned file path, in place. + /// + /// On Unix, this always succeeds and is zero cost. On non-Unix systems, + /// this returns the original byte string if it is not valid UTF-8. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteVec; + /// + /// let bs = Vec::from("foo"); + /// let path = bs.into_path_buf().expect("should be valid UTF-8"); + /// assert_eq!(path.as_os_str(), "foo"); + /// ``` + #[inline] + fn into_path_buf(self) -> Result> + where + Self: Sized, + { + self.into_os_string().map(PathBuf::from) + } + + /// Lossily converts this byte string into an owned file path, in place. + /// + /// On Unix, this always succeeds and is zero cost. On non-Unix systems, + /// this will perform a UTF-8 check and lossily convert this byte string + /// into valid UTF-8 using the Unicode replacement codepoint. + /// + /// Note that this can prevent the correct roundtripping of file paths on + /// non-Unix systems such as Windows, where file paths are an arbitrary + /// sequence of 16-bit integers. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteVec; + /// + /// let bs = Vec::from_slice(b"foo\xFFbar"); + /// let path = bs.into_path_buf_lossy(); + /// assert_eq!(path.to_string_lossy(), "foo\u{FFFD}bar"); + /// ``` + #[inline] + fn into_path_buf_lossy(self) -> PathBuf + where + Self: Sized, + { + PathBuf::from(self.into_os_string_lossy()) + } + + /// Removes the last byte from this `Vec` and returns it. + /// + /// If this byte string is empty, then `None` is returned. + /// + /// If the last codepoint in this byte string is not ASCII, then removing + /// the last byte could make this byte string contain invalid UTF-8. + /// + /// Note that this is equivalent to the generic `Vec::pop` method. This + /// method is provided to permit callers to explicitly differentiate + /// between popping bytes and codepoints. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteVec; + /// + /// let mut s = Vec::from("foo"); + /// assert_eq!(s.pop_byte(), Some(b'o')); + /// assert_eq!(s.pop_byte(), Some(b'o')); + /// assert_eq!(s.pop_byte(), Some(b'f')); + /// assert_eq!(s.pop_byte(), None); + /// ``` + #[inline] + fn pop_byte(&mut self) -> Option { + self.as_vec_mut().pop() + } + + /// Removes the last codepoint from this `Vec` and returns it. + /// + /// If this byte string is empty, then `None` is returned. If the last + /// bytes of this byte string do not correspond to a valid UTF-8 code unit + /// sequence, then the Unicode replacement codepoint is yielded instead in + /// accordance with the + /// [replacement codepoint substitution policy](index.html#handling-of-invalid-utf8-8). + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteVec; + /// + /// let mut s = Vec::from("foo"); + /// assert_eq!(s.pop_char(), Some('o')); + /// assert_eq!(s.pop_char(), Some('o')); + /// assert_eq!(s.pop_char(), Some('f')); + /// assert_eq!(s.pop_char(), None); + /// ``` + /// + /// This shows the replacement codepoint substitution policy. Note that + /// the first pop yields a replacement codepoint but actually removes two + /// bytes. This is in contrast with subsequent pops when encountering + /// `\xFF` since `\xFF` is never a valid prefix for any valid UTF-8 + /// code unit sequence. + /// + /// ``` + /// use bstr::ByteVec; + /// + /// let mut s = Vec::from_slice(b"f\xFF\xFF\xFFoo\xE2\x98"); + /// assert_eq!(s.pop_char(), Some('\u{FFFD}')); + /// assert_eq!(s.pop_char(), Some('o')); + /// assert_eq!(s.pop_char(), Some('o')); + /// assert_eq!(s.pop_char(), Some('\u{FFFD}')); + /// assert_eq!(s.pop_char(), Some('\u{FFFD}')); + /// assert_eq!(s.pop_char(), Some('\u{FFFD}')); + /// assert_eq!(s.pop_char(), Some('f')); + /// assert_eq!(s.pop_char(), None); + /// ``` + #[inline] + fn pop_char(&mut self) -> Option { + let (ch, size) = utf8::decode_last_lossy(self.as_vec()); + if size == 0 { + return None; + } + let new_len = self.as_vec().len() - size; + self.as_vec_mut().truncate(new_len); + Some(ch) + } + + /// Removes a `char` from this `Vec` at the given byte position and + /// returns it. + /// + /// If the bytes at the given position do not lead to a valid UTF-8 code + /// unit sequence, then a + /// [replacement codepoint is returned instead](index.html#handling-of-invalid-utf8-8). + /// + /// # Panics + /// + /// Panics if `at` is larger than or equal to this byte string's length. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteVec; + /// + /// let mut s = Vec::from("foo☃bar"); + /// assert_eq!(s.remove_char(3), '☃'); + /// assert_eq!(s, b"foobar"); + /// ``` + /// + /// This example shows how the Unicode replacement codepoint policy is + /// used: + /// + /// ``` + /// use bstr::ByteVec; + /// + /// let mut s = Vec::from_slice(b"foo\xFFbar"); + /// assert_eq!(s.remove_char(3), '\u{FFFD}'); + /// assert_eq!(s, b"foobar"); + /// ``` + #[inline] + fn remove_char(&mut self, at: usize) -> char { + let (ch, size) = utf8::decode_lossy(&self.as_vec()[at..]); + assert!( + size > 0, + "expected {} to be less than {}", + at, + self.as_vec().len(), + ); + self.as_vec_mut().drain(at..at + size); + ch + } + + /// Inserts the given codepoint into this `Vec` at a particular byte + /// position. + /// + /// This is an `O(n)` operation as it may copy a number of elements in this + /// byte string proportional to its length. + /// + /// # Panics + /// + /// Panics if `at` is larger than the byte string's length. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteVec; + /// + /// let mut s = Vec::from("foobar"); + /// s.insert_char(3, '☃'); + /// assert_eq!(s, "foo☃bar".as_bytes()); + /// ``` + #[inline] + fn insert_char(&mut self, at: usize, ch: char) { + self.insert_str(at, ch.encode_utf8(&mut [0; 4]).as_bytes()); + } + + /// Inserts the given byte string into this byte string at a particular + /// byte position. + /// + /// This is an `O(n)` operation as it may copy a number of elements in this + /// byte string proportional to its length. + /// + /// The given byte string may be any type that can be cheaply converted + /// into a `&[u8]`. This includes, but is not limited to, `&str` and + /// `&[u8]`. + /// + /// # Panics + /// + /// Panics if `at` is larger than the byte string's length. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteVec; + /// + /// let mut s = Vec::from("foobar"); + /// s.insert_str(3, "☃☃☃"); + /// assert_eq!(s, "foo☃☃☃bar".as_bytes()); + /// ``` + #[inline] + fn insert_str>(&mut self, at: usize, bytes: B) { + let bytes = bytes.as_ref(); + let len = self.as_vec().len(); + assert!(at <= len, "expected {} to be <= {}", at, len); + + // SAFETY: We'd like to efficiently splice in the given bytes into + // this byte string. Since we are only working with `u8` elements here, + // we only need to consider whether our bounds are correct and whether + // our byte string has enough space. + self.as_vec_mut().reserve(bytes.len()); + unsafe { + // Shift bytes after `at` over by the length of `bytes` to make + // room for it. This requires referencing two regions of memory + // that may overlap, so we use ptr::copy. + ptr::copy( + self.as_vec().as_ptr().add(at), + self.as_vec_mut().as_mut_ptr().add(at + bytes.len()), + len - at, + ); + // Now copy the bytes given into the room we made above. In this + // case, we know that the given bytes cannot possibly overlap + // with this byte string since we have a mutable borrow of the + // latter. Thus, we can use a nonoverlapping copy. + ptr::copy_nonoverlapping( + bytes.as_ptr(), + self.as_vec_mut().as_mut_ptr().add(at), + bytes.len(), + ); + self.as_vec_mut().set_len(len + bytes.len()); + } + } + + /// Removes the specified range in this byte string and replaces it with + /// the given bytes. The given bytes do not need to have the same length + /// as the range provided. + /// + /// # Panics + /// + /// Panics if the given range is invalid. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteVec; + /// + /// let mut s = Vec::from("foobar"); + /// s.replace_range(2..4, "xxxxx"); + /// assert_eq!(s, "foxxxxxar".as_bytes()); + /// ``` + #[inline] + fn replace_range(&mut self, range: R, replace_with: B) + where + R: ops::RangeBounds, + B: AsRef<[u8]>, + { + self.as_vec_mut().splice(range, replace_with.as_ref().iter().cloned()); + } + + /// Creates a draining iterator that removes the specified range in this + /// `Vec` and yields each of the removed bytes. + /// + /// Note that the elements specified by the given range are removed + /// regardless of whether the returned iterator is fully exhausted. + /// + /// Also note that is is unspecified how many bytes are removed from the + /// `Vec` if the `DrainBytes` iterator is leaked. + /// + /// # Panics + /// + /// Panics if the given range is not valid. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::ByteVec; + /// + /// let mut s = Vec::from("foobar"); + /// { + /// let mut drainer = s.drain_bytes(2..4); + /// assert_eq!(drainer.next(), Some(b'o')); + /// assert_eq!(drainer.next(), Some(b'b')); + /// assert_eq!(drainer.next(), None); + /// } + /// assert_eq!(s, "foar".as_bytes()); + /// ``` + #[inline] + fn drain_bytes(&mut self, range: R) -> DrainBytes + where + R: ops::RangeBounds, + { + DrainBytes { it: self.as_vec_mut().drain(range) } + } +} + +/// A draining byte oriented iterator for `Vec`. +/// +/// This iterator is created by +/// [`ByteVec::drain_bytes`](trait.ByteVec.html#method.drain_bytes). +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use bstr::ByteVec; +/// +/// let mut s = Vec::from("foobar"); +/// { +/// let mut drainer = s.drain_bytes(2..4); +/// assert_eq!(drainer.next(), Some(b'o')); +/// assert_eq!(drainer.next(), Some(b'b')); +/// assert_eq!(drainer.next(), None); +/// } +/// assert_eq!(s, "foar".as_bytes()); +/// ``` +#[derive(Debug)] +pub struct DrainBytes<'a> { + it: vec::Drain<'a, u8>, +} + +impl<'a> iter::FusedIterator for DrainBytes<'a> {} + +impl<'a> Iterator for DrainBytes<'a> { + type Item = u8; + + #[inline] + fn next(&mut self) -> Option { + self.it.next() + } +} + +impl<'a> DoubleEndedIterator for DrainBytes<'a> { + #[inline] + fn next_back(&mut self) -> Option { + self.it.next_back() + } +} + +impl<'a> ExactSizeIterator for DrainBytes<'a> { + #[inline] + fn len(&self) -> usize { + self.it.len() + } +} + +/// An error that may occur when converting a `Vec` to a `String`. +/// +/// This error includes the original `Vec` that failed to convert to a +/// `String`. This permits callers to recover the allocation used even if it +/// it not valid UTF-8. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use bstr::{B, ByteVec}; +/// +/// let bytes = Vec::from_slice(b"foo\xFFbar"); +/// let err = bytes.into_string().unwrap_err(); +/// +/// assert_eq!(err.utf8_error().valid_up_to(), 3); +/// assert_eq!(err.utf8_error().error_len(), Some(1)); +/// +/// // At no point in this example is an allocation performed. +/// let bytes = Vec::from(err.into_vec()); +/// assert_eq!(bytes, B(b"foo\xFFbar")); +/// ``` +#[derive(Debug, Eq, PartialEq)] +pub struct FromUtf8Error { + original: Vec, + err: Utf8Error, +} + +impl FromUtf8Error { + /// Return the original bytes as a slice that failed to convert to a + /// `String`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteVec}; + /// + /// let bytes = Vec::from_slice(b"foo\xFFbar"); + /// let err = bytes.into_string().unwrap_err(); + /// + /// // At no point in this example is an allocation performed. + /// assert_eq!(err.as_bytes(), B(b"foo\xFFbar")); + /// ``` + #[inline] + pub fn as_bytes(&self) -> &[u8] { + &self.original + } + + /// Consume this error and return the original byte string that failed to + /// convert to a `String`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteVec}; + /// + /// let bytes = Vec::from_slice(b"foo\xFFbar"); + /// let err = bytes.into_string().unwrap_err(); + /// let original = err.into_vec(); + /// + /// // At no point in this example is an allocation performed. + /// assert_eq!(original, B(b"foo\xFFbar")); + /// ``` + #[inline] + pub fn into_vec(self) -> Vec { + self.original + } + + /// Return the underlying UTF-8 error that occurred. This error provides + /// information on the nature and location of the invalid UTF-8 detected. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bstr::{B, ByteVec}; + /// + /// let bytes = Vec::from_slice(b"foo\xFFbar"); + /// let err = bytes.into_string().unwrap_err(); + /// + /// assert_eq!(err.utf8_error().valid_up_to(), 3); + /// assert_eq!(err.utf8_error().error_len(), Some(1)); + /// ``` + #[inline] + pub fn utf8_error(&self) -> &Utf8Error { + &self.err + } +} + +impl error::Error for FromUtf8Error { + #[inline] + fn description(&self) -> &str { + "invalid UTF-8 vector" + } +} + +impl fmt::Display for FromUtf8Error { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.err) + } +} + +#[cfg(test)] +mod tests { + use ext_slice::B; + use ext_vec::ByteVec; + + #[test] + fn insert() { + let mut s = vec![]; + s.insert_str(0, "foo"); + assert_eq!(s, "foo".as_bytes()); + + let mut s = Vec::from("a"); + s.insert_str(0, "foo"); + assert_eq!(s, "fooa".as_bytes()); + + let mut s = Vec::from("a"); + s.insert_str(1, "foo"); + assert_eq!(s, "afoo".as_bytes()); + + let mut s = Vec::from("foobar"); + s.insert_str(3, "quux"); + assert_eq!(s, "fooquuxbar".as_bytes()); + + let mut s = Vec::from("foobar"); + s.insert_str(3, "x"); + assert_eq!(s, "fooxbar".as_bytes()); + + let mut s = Vec::from("foobar"); + s.insert_str(0, "x"); + assert_eq!(s, "xfoobar".as_bytes()); + + let mut s = Vec::from("foobar"); + s.insert_str(6, "x"); + assert_eq!(s, "foobarx".as_bytes()); + + let mut s = Vec::from("foobar"); + s.insert_str(3, "quuxbazquux"); + assert_eq!(s, "fooquuxbazquuxbar".as_bytes()); + } + + #[test] + #[should_panic] + fn insert_fail1() { + let mut s = vec![]; + s.insert_str(1, "foo"); + } + + #[test] + #[should_panic] + fn insert_fail2() { + let mut s = Vec::from("a"); + s.insert_str(2, "foo"); + } + + #[test] + #[should_panic] + fn insert_fail3() { + let mut s = Vec::from("foobar"); + s.insert_str(7, "foo"); + } +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/impls.rs b/third_party/cargo/vendor/bstr-0.2.15/src/impls.rs new file mode 100644 index 0000000..4cba48e --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/impls.rs @@ -0,0 +1,984 @@ +macro_rules! impl_partial_eq { + ($lhs:ty, $rhs:ty) => { + impl<'a, 'b> PartialEq<$rhs> for $lhs { + #[inline] + fn eq(&self, other: &$rhs) -> bool { + let other: &[u8] = other.as_ref(); + PartialEq::eq(self.as_bytes(), other) + } + } + + impl<'a, 'b> PartialEq<$lhs> for $rhs { + #[inline] + fn eq(&self, other: &$lhs) -> bool { + let this: &[u8] = self.as_ref(); + PartialEq::eq(this, other.as_bytes()) + } + } + }; +} + +#[cfg(feature = "std")] +macro_rules! impl_partial_eq_cow { + ($lhs:ty, $rhs:ty) => { + impl<'a, 'b> PartialEq<$rhs> for $lhs { + #[inline] + fn eq(&self, other: &$rhs) -> bool { + let other: &[u8] = (&**other).as_ref(); + PartialEq::eq(self.as_bytes(), other) + } + } + + impl<'a, 'b> PartialEq<$lhs> for $rhs { + #[inline] + fn eq(&self, other: &$lhs) -> bool { + let this: &[u8] = (&**other).as_ref(); + PartialEq::eq(this, self.as_bytes()) + } + } + }; +} + +macro_rules! impl_partial_ord { + ($lhs:ty, $rhs:ty) => { + impl<'a, 'b> PartialOrd<$rhs> for $lhs { + #[inline] + fn partial_cmp(&self, other: &$rhs) -> Option { + let other: &[u8] = other.as_ref(); + PartialOrd::partial_cmp(self.as_bytes(), other) + } + } + + impl<'a, 'b> PartialOrd<$lhs> for $rhs { + #[inline] + fn partial_cmp(&self, other: &$lhs) -> Option { + let this: &[u8] = self.as_ref(); + PartialOrd::partial_cmp(this, other.as_bytes()) + } + } + }; +} + +#[cfg(feature = "std")] +mod bstring { + use std::borrow::{Borrow, Cow, ToOwned}; + use std::cmp::Ordering; + use std::fmt; + use std::iter::FromIterator; + use std::ops; + + use bstr::BStr; + use bstring::BString; + use ext_vec::ByteVec; + + impl fmt::Display for BString { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self.as_bstr(), f) + } + } + + impl fmt::Debug for BString { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(self.as_bstr(), f) + } + } + + impl ops::Deref for BString { + type Target = Vec; + + #[inline] + fn deref(&self) -> &Vec { + &self.bytes + } + } + + impl ops::DerefMut for BString { + #[inline] + fn deref_mut(&mut self) -> &mut Vec { + &mut self.bytes + } + } + + impl AsRef<[u8]> for BString { + #[inline] + fn as_ref(&self) -> &[u8] { + &self.bytes + } + } + + impl AsRef for BString { + #[inline] + fn as_ref(&self) -> &BStr { + self.as_bstr() + } + } + + impl AsMut<[u8]> for BString { + #[inline] + fn as_mut(&mut self) -> &mut [u8] { + &mut self.bytes + } + } + + impl AsMut for BString { + #[inline] + fn as_mut(&mut self) -> &mut BStr { + self.as_mut_bstr() + } + } + + impl Borrow for BString { + #[inline] + fn borrow(&self) -> &BStr { + self.as_bstr() + } + } + + impl ToOwned for BStr { + type Owned = BString; + + #[inline] + fn to_owned(&self) -> BString { + BString::from(self) + } + } + + impl Default for BString { + fn default() -> BString { + BString::from(vec![]) + } + } + + impl<'a> From<&'a [u8]> for BString { + #[inline] + fn from(s: &'a [u8]) -> BString { + BString::from(s.to_vec()) + } + } + + impl From> for BString { + #[inline] + fn from(s: Vec) -> BString { + BString { bytes: s } + } + } + + impl From for Vec { + #[inline] + fn from(s: BString) -> Vec { + s.bytes + } + } + + impl<'a> From<&'a str> for BString { + #[inline] + fn from(s: &'a str) -> BString { + BString::from(s.as_bytes().to_vec()) + } + } + + impl From for BString { + #[inline] + fn from(s: String) -> BString { + BString::from(s.into_bytes()) + } + } + + impl<'a> From<&'a BStr> for BString { + #[inline] + fn from(s: &'a BStr) -> BString { + BString::from(s.bytes.to_vec()) + } + } + + impl<'a> From for Cow<'a, BStr> { + #[inline] + fn from(s: BString) -> Cow<'a, BStr> { + Cow::Owned(s) + } + } + + impl FromIterator for BString { + #[inline] + fn from_iter>(iter: T) -> BString { + BString::from(iter.into_iter().collect::()) + } + } + + impl FromIterator for BString { + #[inline] + fn from_iter>(iter: T) -> BString { + BString::from(iter.into_iter().collect::>()) + } + } + + impl<'a> FromIterator<&'a str> for BString { + #[inline] + fn from_iter>(iter: T) -> BString { + let mut buf = vec![]; + for b in iter { + buf.push_str(b); + } + BString::from(buf) + } + } + + impl<'a> FromIterator<&'a [u8]> for BString { + #[inline] + fn from_iter>(iter: T) -> BString { + let mut buf = vec![]; + for b in iter { + buf.push_str(b); + } + BString::from(buf) + } + } + + impl<'a> FromIterator<&'a BStr> for BString { + #[inline] + fn from_iter>(iter: T) -> BString { + let mut buf = vec![]; + for b in iter { + buf.push_str(b); + } + BString::from(buf) + } + } + + impl FromIterator for BString { + #[inline] + fn from_iter>(iter: T) -> BString { + let mut buf = vec![]; + for b in iter { + buf.push_str(b); + } + BString::from(buf) + } + } + + impl Eq for BString {} + + impl PartialEq for BString { + #[inline] + fn eq(&self, other: &BString) -> bool { + &self[..] == &other[..] + } + } + + impl_partial_eq!(BString, Vec); + impl_partial_eq!(BString, [u8]); + impl_partial_eq!(BString, &'a [u8]); + impl_partial_eq!(BString, String); + impl_partial_eq!(BString, str); + impl_partial_eq!(BString, &'a str); + impl_partial_eq!(BString, BStr); + impl_partial_eq!(BString, &'a BStr); + + impl PartialOrd for BString { + #[inline] + fn partial_cmp(&self, other: &BString) -> Option { + PartialOrd::partial_cmp(&self.bytes, &other.bytes) + } + } + + impl Ord for BString { + #[inline] + fn cmp(&self, other: &BString) -> Ordering { + self.partial_cmp(other).unwrap() + } + } + + impl_partial_ord!(BString, Vec); + impl_partial_ord!(BString, [u8]); + impl_partial_ord!(BString, &'a [u8]); + impl_partial_ord!(BString, String); + impl_partial_ord!(BString, str); + impl_partial_ord!(BString, &'a str); + impl_partial_ord!(BString, BStr); + impl_partial_ord!(BString, &'a BStr); +} + +mod bstr { + #[cfg(feature = "std")] + use std::borrow::Cow; + + use core::cmp::Ordering; + use core::fmt; + use core::ops; + + use bstr::BStr; + use ext_slice::ByteSlice; + + impl fmt::Display for BStr { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + /// Write the given bstr (lossily) to the given formatter. + fn write_bstr( + f: &mut fmt::Formatter, + bstr: &BStr, + ) -> Result<(), fmt::Error> { + for chunk in bstr.utf8_chunks() { + f.write_str(chunk.valid())?; + if !chunk.invalid().is_empty() { + f.write_str("\u{FFFD}")?; + } + } + Ok(()) + } + + /// Write 'num' fill characters to the given formatter. + fn write_pads(f: &mut fmt::Formatter, num: usize) -> fmt::Result { + let fill = f.fill(); + for _ in 0..num { + f.write_fmt(format_args!("{}", fill))?; + } + Ok(()) + } + + if let Some(align) = f.align() { + let width = f.width().unwrap_or(0); + let nchars = self.chars().count(); + let remaining_pads = width.saturating_sub(nchars); + match align { + fmt::Alignment::Left => { + write_bstr(f, self)?; + write_pads(f, remaining_pads)?; + } + fmt::Alignment::Right => { + write_pads(f, remaining_pads)?; + write_bstr(f, self)?; + } + fmt::Alignment::Center => { + let half = remaining_pads / 2; + let second_half = if remaining_pads % 2 == 0 { + half + } else { + half + 1 + }; + write_pads(f, half)?; + write_bstr(f, self)?; + write_pads(f, second_half)?; + } + } + Ok(()) + } else { + write_bstr(f, self)?; + Ok(()) + } + } + } + + impl fmt::Debug for BStr { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "\"")?; + for (s, e, ch) in self.char_indices() { + match ch { + '\0' => write!(f, "\\0")?, + '\u{FFFD}' => { + let bytes = self[s..e].as_bytes(); + if bytes == b"\xEF\xBF\xBD" { + write!(f, "{}", ch.escape_debug())?; + } else { + for &b in self[s..e].as_bytes() { + write!(f, r"\x{:02X}", b)?; + } + } + } + // ASCII control characters except \0, \n, \r, \t + '\x01'..='\x08' + | '\x0b' + | '\x0c' + | '\x0e'..='\x19' + | '\x7f' => { + write!(f, "\\x{:02x}", ch as u32)?; + } + '\n' | '\r' | '\t' | _ => { + write!(f, "{}", ch.escape_debug())?; + } + } + } + write!(f, "\"")?; + Ok(()) + } + } + + impl ops::Deref for BStr { + type Target = [u8]; + + #[inline] + fn deref(&self) -> &[u8] { + &self.bytes + } + } + + impl ops::DerefMut for BStr { + #[inline] + fn deref_mut(&mut self) -> &mut [u8] { + &mut self.bytes + } + } + + impl ops::Index for BStr { + type Output = u8; + + #[inline] + fn index(&self, idx: usize) -> &u8 { + &self.as_bytes()[idx] + } + } + + impl ops::Index for BStr { + type Output = BStr; + + #[inline] + fn index(&self, _: ops::RangeFull) -> &BStr { + self + } + } + + impl ops::Index> for BStr { + type Output = BStr; + + #[inline] + fn index(&self, r: ops::Range) -> &BStr { + BStr::new(&self.as_bytes()[r.start..r.end]) + } + } + + impl ops::Index> for BStr { + type Output = BStr; + + #[inline] + fn index(&self, r: ops::RangeInclusive) -> &BStr { + BStr::new(&self.as_bytes()[*r.start()..=*r.end()]) + } + } + + impl ops::Index> for BStr { + type Output = BStr; + + #[inline] + fn index(&self, r: ops::RangeFrom) -> &BStr { + BStr::new(&self.as_bytes()[r.start..]) + } + } + + impl ops::Index> for BStr { + type Output = BStr; + + #[inline] + fn index(&self, r: ops::RangeTo) -> &BStr { + BStr::new(&self.as_bytes()[..r.end]) + } + } + + impl ops::Index> for BStr { + type Output = BStr; + + #[inline] + fn index(&self, r: ops::RangeToInclusive) -> &BStr { + BStr::new(&self.as_bytes()[..=r.end]) + } + } + + impl ops::IndexMut for BStr { + #[inline] + fn index_mut(&mut self, idx: usize) -> &mut u8 { + &mut self.bytes[idx] + } + } + + impl ops::IndexMut for BStr { + #[inline] + fn index_mut(&mut self, _: ops::RangeFull) -> &mut BStr { + self + } + } + + impl ops::IndexMut> for BStr { + #[inline] + fn index_mut(&mut self, r: ops::Range) -> &mut BStr { + BStr::from_bytes_mut(&mut self.bytes[r.start..r.end]) + } + } + + impl ops::IndexMut> for BStr { + #[inline] + fn index_mut(&mut self, r: ops::RangeInclusive) -> &mut BStr { + BStr::from_bytes_mut(&mut self.bytes[*r.start()..=*r.end()]) + } + } + + impl ops::IndexMut> for BStr { + #[inline] + fn index_mut(&mut self, r: ops::RangeFrom) -> &mut BStr { + BStr::from_bytes_mut(&mut self.bytes[r.start..]) + } + } + + impl ops::IndexMut> for BStr { + #[inline] + fn index_mut(&mut self, r: ops::RangeTo) -> &mut BStr { + BStr::from_bytes_mut(&mut self.bytes[..r.end]) + } + } + + impl ops::IndexMut> for BStr { + #[inline] + fn index_mut(&mut self, r: ops::RangeToInclusive) -> &mut BStr { + BStr::from_bytes_mut(&mut self.bytes[..=r.end]) + } + } + + impl AsRef<[u8]> for BStr { + #[inline] + fn as_ref(&self) -> &[u8] { + self.as_bytes() + } + } + + impl AsRef for [u8] { + #[inline] + fn as_ref(&self) -> &BStr { + BStr::new(self) + } + } + + impl AsRef for str { + #[inline] + fn as_ref(&self) -> &BStr { + BStr::new(self) + } + } + + impl AsMut<[u8]> for BStr { + #[inline] + fn as_mut(&mut self) -> &mut [u8] { + &mut self.bytes + } + } + + impl AsMut for [u8] { + #[inline] + fn as_mut(&mut self) -> &mut BStr { + BStr::new_mut(self) + } + } + + impl<'a> Default for &'a BStr { + fn default() -> &'a BStr { + BStr::from_bytes(b"") + } + } + + impl<'a> Default for &'a mut BStr { + fn default() -> &'a mut BStr { + BStr::from_bytes_mut(&mut []) + } + } + + impl<'a> From<&'a [u8]> for &'a BStr { + #[inline] + fn from(s: &'a [u8]) -> &'a BStr { + BStr::from_bytes(s) + } + } + + impl<'a> From<&'a str> for &'a BStr { + #[inline] + fn from(s: &'a str) -> &'a BStr { + BStr::from_bytes(s.as_bytes()) + } + } + + #[cfg(feature = "std")] + impl<'a> From<&'a BStr> for Cow<'a, BStr> { + #[inline] + fn from(s: &'a BStr) -> Cow<'a, BStr> { + Cow::Borrowed(s) + } + } + + #[cfg(feature = "std")] + impl From> for Box { + #[inline] + fn from(s: Box<[u8]>) -> Box { + BStr::from_boxed_bytes(s) + } + } + + #[cfg(feature = "std")] + impl From> for Box<[u8]> { + #[inline] + fn from(s: Box) -> Box<[u8]> { + BStr::into_boxed_bytes(s) + } + } + + impl Eq for BStr {} + + impl PartialEq for BStr { + #[inline] + fn eq(&self, other: &BStr) -> bool { + self.as_bytes() == other.as_bytes() + } + } + + impl_partial_eq!(BStr, [u8]); + impl_partial_eq!(BStr, &'a [u8]); + impl_partial_eq!(BStr, str); + impl_partial_eq!(BStr, &'a str); + + #[cfg(feature = "std")] + impl_partial_eq!(BStr, Vec); + #[cfg(feature = "std")] + impl_partial_eq!(&'a BStr, Vec); + #[cfg(feature = "std")] + impl_partial_eq!(BStr, String); + #[cfg(feature = "std")] + impl_partial_eq!(&'a BStr, String); + #[cfg(feature = "std")] + impl_partial_eq_cow!(&'a BStr, Cow<'a, BStr>); + #[cfg(feature = "std")] + impl_partial_eq_cow!(&'a BStr, Cow<'a, str>); + #[cfg(feature = "std")] + impl_partial_eq_cow!(&'a BStr, Cow<'a, [u8]>); + + impl PartialOrd for BStr { + #[inline] + fn partial_cmp(&self, other: &BStr) -> Option { + PartialOrd::partial_cmp(self.as_bytes(), other.as_bytes()) + } + } + + impl Ord for BStr { + #[inline] + fn cmp(&self, other: &BStr) -> Ordering { + self.partial_cmp(other).unwrap() + } + } + + impl_partial_ord!(BStr, [u8]); + impl_partial_ord!(BStr, &'a [u8]); + impl_partial_ord!(BStr, str); + impl_partial_ord!(BStr, &'a str); + + #[cfg(feature = "std")] + impl_partial_ord!(BStr, Vec); + #[cfg(feature = "std")] + impl_partial_ord!(&'a BStr, Vec); + #[cfg(feature = "std")] + impl_partial_ord!(BStr, String); + #[cfg(feature = "std")] + impl_partial_ord!(&'a BStr, String); +} + +#[cfg(feature = "serde1-nostd")] +mod bstr_serde { + use core::fmt; + + use serde::{ + de::Error, de::Visitor, Deserialize, Deserializer, Serialize, + Serializer, + }; + + use bstr::BStr; + + impl Serialize for BStr { + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_bytes(self.as_bytes()) + } + } + + impl<'a, 'de: 'a> Deserialize<'de> for &'a BStr { + #[inline] + fn deserialize(deserializer: D) -> Result<&'a BStr, D::Error> + where + D: Deserializer<'de>, + { + struct BStrVisitor; + + impl<'de> Visitor<'de> for BStrVisitor { + type Value = &'de BStr; + + fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("a borrowed byte string") + } + + #[inline] + fn visit_borrowed_bytes( + self, + value: &'de [u8], + ) -> Result<&'de BStr, E> { + Ok(BStr::new(value)) + } + + #[inline] + fn visit_borrowed_str( + self, + value: &'de str, + ) -> Result<&'de BStr, E> { + Ok(BStr::new(value)) + } + } + + deserializer.deserialize_bytes(BStrVisitor) + } + } +} + +#[cfg(feature = "serde1")] +mod bstring_serde { + use std::cmp; + use std::fmt; + + use serde::{ + de::Error, de::SeqAccess, de::Visitor, Deserialize, Deserializer, + Serialize, Serializer, + }; + + use bstring::BString; + + impl Serialize for BString { + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_bytes(self.as_bytes()) + } + } + + impl<'de> Deserialize<'de> for BString { + #[inline] + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct BStringVisitor; + + impl<'de> Visitor<'de> for BStringVisitor { + type Value = BString; + + fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("a byte string") + } + + #[inline] + fn visit_seq>( + self, + mut visitor: V, + ) -> Result { + let len = cmp::min(visitor.size_hint().unwrap_or(0), 256); + let mut bytes = Vec::with_capacity(len); + while let Some(v) = visitor.next_element()? { + bytes.push(v); + } + Ok(BString::from(bytes)) + } + + #[inline] + fn visit_bytes( + self, + value: &[u8], + ) -> Result { + Ok(BString::from(value)) + } + + #[inline] + fn visit_byte_buf( + self, + value: Vec, + ) -> Result { + Ok(BString::from(value)) + } + + #[inline] + fn visit_str( + self, + value: &str, + ) -> Result { + Ok(BString::from(value)) + } + + #[inline] + fn visit_string( + self, + value: String, + ) -> Result { + Ok(BString::from(value)) + } + } + + deserializer.deserialize_byte_buf(BStringVisitor) + } + } +} + +#[cfg(test)] +mod display { + use crate::ByteSlice; + use bstring::BString; + + #[test] + fn clean() { + assert_eq!(&format!("{}", &b"abc".as_bstr()), "abc"); + assert_eq!(&format!("{}", &b"\xf0\x28\x8c\xbc".as_bstr()), "�(��"); + } + + #[test] + fn width_bigger_than_bstr() { + assert_eq!(&format!("{:<7}!", &b"abc".as_bstr()), "abc !"); + assert_eq!(&format!("{:>7}!", &b"abc".as_bstr()), " abc!"); + assert_eq!(&format!("{:^7}!", &b"abc".as_bstr()), " abc !"); + assert_eq!(&format!("{:^6}!", &b"abc".as_bstr()), " abc !"); + assert_eq!(&format!("{:-<7}!", &b"abc".as_bstr()), "abc----!"); + assert_eq!(&format!("{:->7}!", &b"abc".as_bstr()), "----abc!"); + assert_eq!(&format!("{:-^7}!", &b"abc".as_bstr()), "--abc--!"); + assert_eq!(&format!("{:-^6}!", &b"abc".as_bstr()), "-abc--!"); + + assert_eq!( + &format!("{:<7}!", &b"\xf0\x28\x8c\xbc".as_bstr()), + "�(�� !" + ); + assert_eq!( + &format!("{:>7}!", &b"\xf0\x28\x8c\xbc".as_bstr()), + " �(��!" + ); + assert_eq!( + &format!("{:^7}!", &b"\xf0\x28\x8c\xbc".as_bstr()), + " �(�� !" + ); + assert_eq!( + &format!("{:^6}!", &b"\xf0\x28\x8c\xbc".as_bstr()), + " �(�� !" + ); + + assert_eq!( + &format!("{:-<7}!", &b"\xf0\x28\x8c\xbc".as_bstr()), + "�(��---!" + ); + assert_eq!( + &format!("{:->7}!", &b"\xf0\x28\x8c\xbc".as_bstr()), + "---�(��!" + ); + assert_eq!( + &format!("{:-^7}!", &b"\xf0\x28\x8c\xbc".as_bstr()), + "-�(��--!" + ); + assert_eq!( + &format!("{:-^6}!", &b"\xf0\x28\x8c\xbc".as_bstr()), + "-�(��-!" + ); + } + + #[test] + fn width_lesser_than_bstr() { + assert_eq!(&format!("{:<2}!", &b"abc".as_bstr()), "abc!"); + assert_eq!(&format!("{:>2}!", &b"abc".as_bstr()), "abc!"); + assert_eq!(&format!("{:^2}!", &b"abc".as_bstr()), "abc!"); + assert_eq!(&format!("{:-<2}!", &b"abc".as_bstr()), "abc!"); + assert_eq!(&format!("{:->2}!", &b"abc".as_bstr()), "abc!"); + assert_eq!(&format!("{:-^2}!", &b"abc".as_bstr()), "abc!"); + + assert_eq!( + &format!("{:<3}!", &b"\xf0\x28\x8c\xbc".as_bstr()), + "�(��!" + ); + assert_eq!( + &format!("{:>3}!", &b"\xf0\x28\x8c\xbc".as_bstr()), + "�(��!" + ); + assert_eq!( + &format!("{:^3}!", &b"\xf0\x28\x8c\xbc".as_bstr()), + "�(��!" + ); + assert_eq!( + &format!("{:^2}!", &b"\xf0\x28\x8c\xbc".as_bstr()), + "�(��!" + ); + + assert_eq!( + &format!("{:-<3}!", &b"\xf0\x28\x8c\xbc".as_bstr()), + "�(��!" + ); + assert_eq!( + &format!("{:->3}!", &b"\xf0\x28\x8c\xbc".as_bstr()), + "�(��!" + ); + assert_eq!( + &format!("{:-^3}!", &b"\xf0\x28\x8c\xbc".as_bstr()), + "�(��!" + ); + assert_eq!( + &format!("{:-^2}!", &b"\xf0\x28\x8c\xbc".as_bstr()), + "�(��!" + ); + } + + quickcheck! { + fn total_length(bstr: BString) -> bool { + let size = bstr.chars().count(); + format!("{:<1$}", bstr.as_bstr(), size).chars().count() >= size + } + } +} + +#[cfg(test)] +mod bstring_arbitrary { + use bstring::BString; + + use quickcheck::{Arbitrary, Gen}; + + impl Arbitrary for BString { + fn arbitrary(g: &mut Gen) -> BString { + BString::from(Vec::::arbitrary(g)) + } + + fn shrink(&self) -> Box> { + Box::new(self.bytes.shrink().map(BString::from)) + } + } +} + +#[test] +fn test_debug() { + use crate::{ByteSlice, B}; + + assert_eq!( + r#""\0\0\0 ftypisom\0\0\x02\0isomiso2avc1mp""#, + format!("{:?}", b"\0\0\0 ftypisom\0\0\x02\0isomiso2avc1mp".as_bstr()), + ); + + // Tests that if the underlying bytes contain the UTF-8 encoding of the + // replacement codepoint, then we emit the codepoint just like other + // non-printable Unicode characters. + assert_eq!( + b"\"\\xFF\xEF\xBF\xBD\\xFF\"".as_bstr(), + // Before fixing #72, the output here would be: + // \\xFF\\xEF\\xBF\\xBD\\xFF + B(&format!("{:?}", b"\xFF\xEF\xBF\xBD\xFF".as_bstr())).as_bstr(), + ); +} + +// See: https://github.com/BurntSushi/bstr/issues/82 +#[test] +fn test_cows_regression() { + use crate::ByteSlice; + use std::borrow::Cow; + + let c1 = Cow::from(b"hello bstr".as_bstr()); + let c2 = b"goodbye bstr".as_bstr(); + assert_ne!(c1, c2); + + let c3 = Cow::from("hello str"); + let c4 = "goodbye str"; + assert_ne!(c3, c4); +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/io.rs b/third_party/cargo/vendor/bstr-0.2.15/src/io.rs new file mode 100644 index 0000000..f2b4452 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/io.rs @@ -0,0 +1,514 @@ +/*! +Utilities for working with I/O using byte strings. + +This module currently only exports a single trait, `BufReadExt`, which provides +facilities for conveniently and efficiently working with lines as byte strings. + +More APIs may be added in the future. +*/ + +use std::io; + +use ext_slice::ByteSlice; +use ext_vec::ByteVec; + +/// An extention trait for +/// [`std::io::BufRead`](https://doc.rust-lang.org/std/io/trait.BufRead.html) +/// which provides convenience APIs for dealing with byte strings. +pub trait BufReadExt: io::BufRead { + /// Returns an iterator over the lines of this reader, where each line + /// is represented as a byte string. + /// + /// Each item yielded by this iterator is a `io::Result>`, where + /// an error is yielded if there was a problem reading from the underlying + /// reader. + /// + /// On success, the next line in the iterator is returned. The line does + /// *not* contain a trailing `\n` or `\r\n`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::io; + /// + /// use bstr::io::BufReadExt; + /// + /// # fn example() -> Result<(), io::Error> { + /// let cursor = io::Cursor::new(b"lorem\nipsum\r\ndolor"); + /// + /// let mut lines = vec![]; + /// for result in cursor.byte_lines() { + /// let line = result?; + /// lines.push(line); + /// } + /// assert_eq!(lines.len(), 3); + /// assert_eq!(lines[0], "lorem".as_bytes()); + /// assert_eq!(lines[1], "ipsum".as_bytes()); + /// assert_eq!(lines[2], "dolor".as_bytes()); + /// # Ok(()) }; example().unwrap() + /// ``` + fn byte_lines(self) -> ByteLines + where + Self: Sized, + { + ByteLines { buf: self } + } + + /// Returns an iterator over byte-terminated records of this reader, where + /// each record is represented as a byte string. + /// + /// Each item yielded by this iterator is a `io::Result>`, where + /// an error is yielded if there was a problem reading from the underlying + /// reader. + /// + /// On success, the next record in the iterator is returned. The record + /// does *not* contain its trailing terminator. + /// + /// Note that calling `byte_records(b'\n')` differs from `byte_lines()` in + /// that it has no special handling for `\r`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::io; + /// + /// use bstr::io::BufReadExt; + /// + /// # fn example() -> Result<(), io::Error> { + /// let cursor = io::Cursor::new(b"lorem\x00ipsum\x00dolor"); + /// + /// let mut records = vec![]; + /// for result in cursor.byte_records(b'\x00') { + /// let record = result?; + /// records.push(record); + /// } + /// assert_eq!(records.len(), 3); + /// assert_eq!(records[0], "lorem".as_bytes()); + /// assert_eq!(records[1], "ipsum".as_bytes()); + /// assert_eq!(records[2], "dolor".as_bytes()); + /// # Ok(()) }; example().unwrap() + /// ``` + fn byte_records(self, terminator: u8) -> ByteRecords + where + Self: Sized, + { + ByteRecords { terminator, buf: self } + } + + /// Executes the given closure on each line in the underlying reader. + /// + /// If the closure returns an error (or if the underlying reader returns an + /// error), then iteration is stopped and the error is returned. If false + /// is returned, then iteration is stopped and no error is returned. + /// + /// The closure given is called on exactly the same values as yielded by + /// the [`byte_lines`](trait.BufReadExt.html#method.byte_lines) + /// iterator. Namely, lines do _not_ contain trailing `\n` or `\r\n` bytes. + /// + /// This routine is useful for iterating over lines as quickly as + /// possible. Namely, a single allocation is reused for each line. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::io; + /// + /// use bstr::io::BufReadExt; + /// + /// # fn example() -> Result<(), io::Error> { + /// let cursor = io::Cursor::new(b"lorem\nipsum\r\ndolor"); + /// + /// let mut lines = vec![]; + /// cursor.for_byte_line(|line| { + /// lines.push(line.to_vec()); + /// Ok(true) + /// })?; + /// assert_eq!(lines.len(), 3); + /// assert_eq!(lines[0], "lorem".as_bytes()); + /// assert_eq!(lines[1], "ipsum".as_bytes()); + /// assert_eq!(lines[2], "dolor".as_bytes()); + /// # Ok(()) }; example().unwrap() + /// ``` + fn for_byte_line(self, mut for_each_line: F) -> io::Result<()> + where + Self: Sized, + F: FnMut(&[u8]) -> io::Result, + { + self.for_byte_line_with_terminator(|line| { + for_each_line(&trim_line_slice(&line)) + }) + } + + /// Executes the given closure on each byte-terminated record in the + /// underlying reader. + /// + /// If the closure returns an error (or if the underlying reader returns an + /// error), then iteration is stopped and the error is returned. If false + /// is returned, then iteration is stopped and no error is returned. + /// + /// The closure given is called on exactly the same values as yielded by + /// the [`byte_records`](trait.BufReadExt.html#method.byte_records) + /// iterator. Namely, records do _not_ contain a trailing terminator byte. + /// + /// This routine is useful for iterating over records as quickly as + /// possible. Namely, a single allocation is reused for each record. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::io; + /// + /// use bstr::io::BufReadExt; + /// + /// # fn example() -> Result<(), io::Error> { + /// let cursor = io::Cursor::new(b"lorem\x00ipsum\x00dolor"); + /// + /// let mut records = vec![]; + /// cursor.for_byte_record(b'\x00', |record| { + /// records.push(record.to_vec()); + /// Ok(true) + /// })?; + /// assert_eq!(records.len(), 3); + /// assert_eq!(records[0], "lorem".as_bytes()); + /// assert_eq!(records[1], "ipsum".as_bytes()); + /// assert_eq!(records[2], "dolor".as_bytes()); + /// # Ok(()) }; example().unwrap() + /// ``` + fn for_byte_record( + self, + terminator: u8, + mut for_each_record: F, + ) -> io::Result<()> + where + Self: Sized, + F: FnMut(&[u8]) -> io::Result, + { + self.for_byte_record_with_terminator(terminator, |chunk| { + for_each_record(&trim_record_slice(&chunk, terminator)) + }) + } + + /// Executes the given closure on each line in the underlying reader. + /// + /// If the closure returns an error (or if the underlying reader returns an + /// error), then iteration is stopped and the error is returned. If false + /// is returned, then iteration is stopped and no error is returned. + /// + /// Unlike + /// [`for_byte_line`](trait.BufReadExt.html#method.for_byte_line), + /// the lines given to the closure *do* include the line terminator, if one + /// exists. + /// + /// This routine is useful for iterating over lines as quickly as + /// possible. Namely, a single allocation is reused for each line. + /// + /// This is identical to `for_byte_record_with_terminator` with a + /// terminator of `\n`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::io; + /// + /// use bstr::io::BufReadExt; + /// + /// # fn example() -> Result<(), io::Error> { + /// let cursor = io::Cursor::new(b"lorem\nipsum\r\ndolor"); + /// + /// let mut lines = vec![]; + /// cursor.for_byte_line_with_terminator(|line| { + /// lines.push(line.to_vec()); + /// Ok(true) + /// })?; + /// assert_eq!(lines.len(), 3); + /// assert_eq!(lines[0], "lorem\n".as_bytes()); + /// assert_eq!(lines[1], "ipsum\r\n".as_bytes()); + /// assert_eq!(lines[2], "dolor".as_bytes()); + /// # Ok(()) }; example().unwrap() + /// ``` + fn for_byte_line_with_terminator( + self, + for_each_line: F, + ) -> io::Result<()> + where + Self: Sized, + F: FnMut(&[u8]) -> io::Result, + { + self.for_byte_record_with_terminator(b'\n', for_each_line) + } + + /// Executes the given closure on each byte-terminated record in the + /// underlying reader. + /// + /// If the closure returns an error (or if the underlying reader returns an + /// error), then iteration is stopped and the error is returned. If false + /// is returned, then iteration is stopped and no error is returned. + /// + /// Unlike + /// [`for_byte_record`](trait.BufReadExt.html#method.for_byte_record), + /// the lines given to the closure *do* include the record terminator, if + /// one exists. + /// + /// This routine is useful for iterating over records as quickly as + /// possible. Namely, a single allocation is reused for each record. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::io; + /// + /// use bstr::B; + /// use bstr::io::BufReadExt; + /// + /// # fn example() -> Result<(), io::Error> { + /// let cursor = io::Cursor::new(b"lorem\x00ipsum\x00dolor"); + /// + /// let mut records = vec![]; + /// cursor.for_byte_record_with_terminator(b'\x00', |record| { + /// records.push(record.to_vec()); + /// Ok(true) + /// })?; + /// assert_eq!(records.len(), 3); + /// assert_eq!(records[0], B(b"lorem\x00")); + /// assert_eq!(records[1], B("ipsum\x00")); + /// assert_eq!(records[2], B("dolor")); + /// # Ok(()) }; example().unwrap() + /// ``` + fn for_byte_record_with_terminator( + mut self, + terminator: u8, + mut for_each_record: F, + ) -> io::Result<()> + where + Self: Sized, + F: FnMut(&[u8]) -> io::Result, + { + let mut bytes = vec![]; + let mut res = Ok(()); + let mut consumed = 0; + 'outer: loop { + // Lend out complete record slices from our buffer + { + let mut buf = self.fill_buf()?; + while let Some(index) = buf.find_byte(terminator) { + let (record, rest) = buf.split_at(index + 1); + buf = rest; + consumed += record.len(); + match for_each_record(&record) { + Ok(false) => break 'outer, + Err(err) => { + res = Err(err); + break 'outer; + } + _ => (), + } + } + + // Copy the final record fragment to our local buffer. This + // saves read_until() from re-scanning a buffer we know + // contains no remaining terminators. + bytes.extend_from_slice(&buf); + consumed += buf.len(); + } + + self.consume(consumed); + consumed = 0; + + // N.B. read_until uses a different version of memchr that may + // be slower than the memchr crate that bstr uses. However, this + // should only run for a fairly small number of records, assuming a + // decent buffer size. + self.read_until(terminator, &mut bytes)?; + if bytes.is_empty() || !for_each_record(&bytes)? { + break; + } + bytes.clear(); + } + self.consume(consumed); + res + } +} + +impl BufReadExt for B {} + +/// An iterator over lines from an instance of +/// [`std::io::BufRead`](https://doc.rust-lang.org/std/io/trait.BufRead.html). +/// +/// This iterator is generally created by calling the +/// [`byte_lines`](trait.BufReadExt.html#method.byte_lines) +/// method on the +/// [`BufReadExt`](trait.BufReadExt.html) +/// trait. +#[derive(Debug)] +pub struct ByteLines { + buf: B, +} + +/// An iterator over records from an instance of +/// [`std::io::BufRead`](https://doc.rust-lang.org/std/io/trait.BufRead.html). +/// +/// A byte record is any sequence of bytes terminated by a particular byte +/// chosen by the caller. For example, NUL separated byte strings are said to +/// be NUL-terminated byte records. +/// +/// This iterator is generally created by calling the +/// [`byte_records`](trait.BufReadExt.html#method.byte_records) +/// method on the +/// [`BufReadExt`](trait.BufReadExt.html) +/// trait. +#[derive(Debug)] +pub struct ByteRecords { + buf: B, + terminator: u8, +} + +impl Iterator for ByteLines { + type Item = io::Result>; + + fn next(&mut self) -> Option>> { + let mut bytes = vec![]; + match self.buf.read_until(b'\n', &mut bytes) { + Err(e) => Some(Err(e)), + Ok(0) => None, + Ok(_) => { + trim_line(&mut bytes); + Some(Ok(bytes)) + } + } + } +} + +impl Iterator for ByteRecords { + type Item = io::Result>; + + fn next(&mut self) -> Option>> { + let mut bytes = vec![]; + match self.buf.read_until(self.terminator, &mut bytes) { + Err(e) => Some(Err(e)), + Ok(0) => None, + Ok(_) => { + trim_record(&mut bytes, self.terminator); + Some(Ok(bytes)) + } + } + } +} + +fn trim_line(line: &mut Vec) { + if line.last_byte() == Some(b'\n') { + line.pop_byte(); + if line.last_byte() == Some(b'\r') { + line.pop_byte(); + } + } +} + +fn trim_line_slice(mut line: &[u8]) -> &[u8] { + if line.last_byte() == Some(b'\n') { + line = &line[..line.len() - 1]; + if line.last_byte() == Some(b'\r') { + line = &line[..line.len() - 1]; + } + } + line +} + +fn trim_record(record: &mut Vec, terminator: u8) { + if record.last_byte() == Some(terminator) { + record.pop_byte(); + } +} + +fn trim_record_slice(mut record: &[u8], terminator: u8) -> &[u8] { + if record.last_byte() == Some(terminator) { + record = &record[..record.len() - 1]; + } + record +} + +#[cfg(test)] +mod tests { + use super::BufReadExt; + use bstring::BString; + + fn collect_lines>(slice: B) -> Vec { + let mut lines = vec![]; + slice + .as_ref() + .for_byte_line(|line| { + lines.push(BString::from(line.to_vec())); + Ok(true) + }) + .unwrap(); + lines + } + + fn collect_lines_term>(slice: B) -> Vec { + let mut lines = vec![]; + slice + .as_ref() + .for_byte_line_with_terminator(|line| { + lines.push(BString::from(line.to_vec())); + Ok(true) + }) + .unwrap(); + lines + } + + #[test] + fn lines_without_terminator() { + assert_eq!(collect_lines(""), Vec::::new()); + + assert_eq!(collect_lines("\n"), vec![""]); + assert_eq!(collect_lines("\n\n"), vec!["", ""]); + assert_eq!(collect_lines("a\nb\n"), vec!["a", "b"]); + assert_eq!(collect_lines("a\nb"), vec!["a", "b"]); + assert_eq!(collect_lines("abc\nxyz\n"), vec!["abc", "xyz"]); + assert_eq!(collect_lines("abc\nxyz"), vec!["abc", "xyz"]); + + assert_eq!(collect_lines("\r\n"), vec![""]); + assert_eq!(collect_lines("\r\n\r\n"), vec!["", ""]); + assert_eq!(collect_lines("a\r\nb\r\n"), vec!["a", "b"]); + assert_eq!(collect_lines("a\r\nb"), vec!["a", "b"]); + assert_eq!(collect_lines("abc\r\nxyz\r\n"), vec!["abc", "xyz"]); + assert_eq!(collect_lines("abc\r\nxyz"), vec!["abc", "xyz"]); + + assert_eq!(collect_lines("abc\rxyz"), vec!["abc\rxyz"]); + } + + #[test] + fn lines_with_terminator() { + assert_eq!(collect_lines_term(""), Vec::::new()); + + assert_eq!(collect_lines_term("\n"), vec!["\n"]); + assert_eq!(collect_lines_term("\n\n"), vec!["\n", "\n"]); + assert_eq!(collect_lines_term("a\nb\n"), vec!["a\n", "b\n"]); + assert_eq!(collect_lines_term("a\nb"), vec!["a\n", "b"]); + assert_eq!(collect_lines_term("abc\nxyz\n"), vec!["abc\n", "xyz\n"]); + assert_eq!(collect_lines_term("abc\nxyz"), vec!["abc\n", "xyz"]); + + assert_eq!(collect_lines_term("\r\n"), vec!["\r\n"]); + assert_eq!(collect_lines_term("\r\n\r\n"), vec!["\r\n", "\r\n"]); + assert_eq!(collect_lines_term("a\r\nb\r\n"), vec!["a\r\n", "b\r\n"]); + assert_eq!(collect_lines_term("a\r\nb"), vec!["a\r\n", "b"]); + assert_eq!( + collect_lines_term("abc\r\nxyz\r\n"), + vec!["abc\r\n", "xyz\r\n"] + ); + assert_eq!(collect_lines_term("abc\r\nxyz"), vec!["abc\r\n", "xyz"]); + + assert_eq!(collect_lines_term("abc\rxyz"), vec!["abc\rxyz"]); + } +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/lib.rs b/third_party/cargo/vendor/bstr-0.2.15/src/lib.rs new file mode 100644 index 0000000..c240cd1 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/lib.rs @@ -0,0 +1,456 @@ +/*! +An experimental byte string library. + +Byte strings are just like standard Unicode strings with one very important +difference: byte strings are only *conventionally* UTF-8 while Rust's standard +Unicode strings are *guaranteed* to be valid UTF-8. The primary motivation for +byte strings is for handling arbitrary bytes that are mostly UTF-8. + +# Overview + +This crate provides two important traits that provide string oriented methods +on `&[u8]` and `Vec` types: + +* [`ByteSlice`](trait.ByteSlice.html) extends the `[u8]` type with additional + string oriented methods. +* [`ByteVec`](trait.ByteVec.html) extends the `Vec` type with additional + string oriented methods. + +Additionally, this crate provides two concrete byte string types that deref to +`[u8]` and `Vec`. These are useful for storing byte string types, and come +with convenient `std::fmt::Debug` implementations: + +* [`BStr`](struct.BStr.html) is a byte string slice, analogous to `str`. +* [`BString`](struct.BString.html) is an owned growable byte string buffer, + analogous to `String`. + +Additionally, the free function [`B`](fn.B.html) serves as a convenient short +hand for writing byte string literals. + +# Quick examples + +Byte strings build on the existing APIs for `Vec` and `&[u8]`, with +additional string oriented methods. Operations such as iterating over +graphemes, searching for substrings, replacing substrings, trimming and case +conversion are examples of things not provided on the standard library `&[u8]` +APIs but are provided by this crate. For example, this code iterates over all +of occurrences of a subtring: + +``` +use bstr::ByteSlice; + +let s = b"foo bar foo foo quux foo"; + +let mut matches = vec![]; +for start in s.find_iter("foo") { + matches.push(start); +} +assert_eq!(matches, [0, 8, 12, 21]); +``` + +Here's another example showing how to do a search and replace (and also showing +use of the `B` function): + +``` +use bstr::{B, ByteSlice}; + +let old = B("foo ☃☃☃ foo foo quux foo"); +let new = old.replace("foo", "hello"); +assert_eq!(new, B("hello ☃☃☃ hello hello quux hello")); +``` + +And here's an example that shows case conversion, even in the presence of +invalid UTF-8: + +``` +use bstr::{ByteSlice, ByteVec}; + +let mut lower = Vec::from("hello β"); +lower[0] = b'\xFF'; +// lowercase β is uppercased to Β +assert_eq!(lower.to_uppercase(), b"\xFFELLO \xCE\x92"); +``` + +# Convenient debug representation + +When working with byte strings, it is often useful to be able to print them +as if they were byte strings and not sequences of integers. While this crate +cannot affect the `std::fmt::Debug` implementations for `[u8]` and `Vec`, +this crate does provide the `BStr` and `BString` types which have convenient +`std::fmt::Debug` implementations. + +For example, this + +``` +use bstr::ByteSlice; + +let mut bytes = Vec::from("hello β"); +bytes[0] = b'\xFF'; + +println!("{:?}", bytes.as_bstr()); +``` + +will output `"\xFFello β"`. + +This example works because the +[`ByteSlice::as_bstr`](trait.ByteSlice.html#method.as_bstr) +method converts any `&[u8]` to a `&BStr`. + +# When should I use byte strings? + +This library is somewhat of an experiment that reflects my hypothesis that +UTF-8 by convention is a better trade off in some circumstances than guaranteed +UTF-8. It's possible, perhaps even likely, that this is a niche concern for +folks working closely with core text primitives. + +The first time this idea hit me was in the implementation of Rust's regex +engine. In particular, very little of the internal implementation cares at all +about searching valid UTF-8 encoded strings. Indeed, internally, the +implementation converts `&str` from the API to `&[u8]` fairly quickly and +just deals with raw bytes. UTF-8 match boundaries are then guaranteed by the +finite state machine itself rather than any specific string type. This makes it +possible to not only run regexes on `&str` values, but also on `&[u8]` values. + +Why would you ever want to run a regex on a `&[u8]` though? Well, `&[u8]` is +the fundamental way at which one reads data from all sorts of streams, via the +standard library's [`Read`](https://doc.rust-lang.org/std/io/trait.Read.html) +trait. In particular, there is no platform independent way to determine whether +what you're reading from is some binary file or a human readable text file. +Therefore, if you're writing a program to search files, you probably need to +deal with `&[u8]` directly unless you're okay with first converting it to a +`&str` and dropping any bytes that aren't valid UTF-8. (Or otherwise determine +the encoding---which is often impractical---and perform a transcoding step.) +Often, the simplest and most robust way to approach this is to simply treat the +contents of a file as if it were mostly valid UTF-8 and pass through invalid +UTF-8 untouched. This may not be the most correct approach though! + +One case in particular exacerbates these issues, and that's memory mapping +a file. When you memory map a file, that file may be gigabytes big, but all +you get is a `&[u8]`. Converting that to a `&str` all in one go is generally +not a good idea because of the costs associated with doing so, and also +because it generally causes one to do two passes over the data instead of +one, which is quite undesirable. It is of course usually possible to do it an +incremental way by only parsing chunks at a time, but this is often complex to +do or impractical. For example, many regex engines only accept one contiguous +sequence of bytes at a time with no way to perform incremental matching. + +In summary, the conventional UTF-8 byte strings provided by this library is an +experiment. They are definitely useful in some limited circumstances, but how +useful they are more broadly isn't clear yet. + +# `bstr` in public APIs + +Since this library is still experimental, you should not use it in the public +API of your crates until it hits `1.0` (unless you're OK with with tracking +breaking releases of `bstr`). + +In general, it should be possible to avoid putting anything in this crate into +your public APIs. Namely, you should never need to use the `ByteSlice` or +`ByteVec` traits as bounds on public APIs, since their only purpose is to +extend the methods on the concrete types `[u8]` and `Vec`, respectively. +Similarly, it should not be necessary to put either the `BStr` or `BString` +types into public APIs. If you want to use them internally, then they can +be converted to/from `[u8]`/`Vec` as needed. + +# Differences with standard strings + +The primary difference between `[u8]` and `str` is that the former is +conventionally UTF-8 while the latter is guaranteed to be UTF-8. The phrase +"conventionally UTF-8" means that a `[u8]` may contain bytes that do not form +a valid UTF-8 sequence, but operations defined on the type in this crate are +generally most useful on valid UTF-8 sequences. For example, iterating over +Unicode codepoints or grapheme clusters is an operation that is only defined +on valid UTF-8. Therefore, when invalid UTF-8 is encountered, the Unicode +replacement codepoint is substituted. Thus, a byte string that is not UTF-8 at +all is of limited utility when using these crate. + +However, not all operations on byte strings are specifically Unicode aware. For +example, substring search has no specific Unicode semantics ascribed to it. It +works just as well for byte strings that are completely valid UTF-8 as for byte +strings that contain no valid UTF-8 at all. Similarly for replacements and +various other operations that do not need any Unicode specific tailoring. + +Aside from the difference in how UTF-8 is handled, the APIs between `[u8]` and +`str` (and `Vec` and `String`) are intentionally very similar, including +maintaining the same behavior for corner cases in things like substring +splitting. There are, however, some differences: + +* Substring search is not done with `matches`, but instead, `find_iter`. + In general, this crate does not define any generic + [`Pattern`](https://doc.rust-lang.org/std/str/pattern/trait.Pattern.html) + infrastructure, and instead prefers adding new methods for different + argument types. For example, `matches` can search by a `char` or a `&str`, + where as `find_iter` can only search by a byte string. `find_char` can be + used for searching by a `char`. +* Since `SliceConcatExt` in the standard library is unstable, it is not + possible to reuse that to implement `join` and `concat` methods. Instead, + [`join`](fn.join.html) and [`concat`](fn.concat.html) are provided as free + functions that perform a similar task. +* This library bundles in a few more Unicode operations, such as grapheme, + word and sentence iterators. More operations, such as normalization and + case folding, may be provided in the future. +* Some `String`/`str` APIs will panic if a particular index was not on a valid + UTF-8 code unit sequence boundary. Conversely, no such checking is performed + in this crate, as is consistent with treating byte strings as a sequence of + bytes. This means callers are responsible for maintaining a UTF-8 invariant + if that's important. +* Some routines provided by this crate, such as `starts_with_str`, have a + `_str` suffix to differentiate them from similar routines already defined + on the `[u8]` type. The difference is that `starts_with` requires its + parameter to be a `&[u8]`, where as `starts_with_str` permits its parameter + to by anything that implements `AsRef<[u8]>`, which is more flexible. This + means you can write `bytes.starts_with_str("☃")` instead of + `bytes.starts_with("☃".as_bytes())`. + +Otherwise, you should find most of the APIs between this crate and the standard +library string APIs to be very similar, if not identical. + +# Handling of invalid UTF-8 + +Since byte strings are only *conventionally* UTF-8, there is no guarantee +that byte strings contain valid UTF-8. Indeed, it is perfectly legal for a +byte string to contain arbitrary bytes. However, since this library defines +a *string* type, it provides many operations specified by Unicode. These +operations are typically only defined over codepoints, and thus have no real +meaning on bytes that are invalid UTF-8 because they do not map to a particular +codepoint. + +For this reason, whenever operations defined only on codepoints are used, this +library will automatically convert invalid UTF-8 to the Unicode replacement +codepoint, `U+FFFD`, which looks like this: `�`. For example, an +[iterator over codepoints](struct.Chars.html) will yield a Unicode +replacement codepoint whenever it comes across bytes that are not valid UTF-8: + +``` +use bstr::ByteSlice; + +let bs = b"a\xFF\xFFz"; +let chars: Vec = bs.chars().collect(); +assert_eq!(vec!['a', '\u{FFFD}', '\u{FFFD}', 'z'], chars); +``` + +There are a few ways in which invalid bytes can be substituted with a Unicode +replacement codepoint. One way, not used by this crate, is to replace every +individual invalid byte with a single replacement codepoint. In contrast, the +approach this crate uses is called the "substitution of maximal subparts," as +specified by the Unicode Standard (Chapter 3, Section 9). (This approach is +also used by [W3C's Encoding Standard](https://www.w3.org/TR/encoding/).) In +this strategy, a replacement codepoint is inserted whenever a byte is found +that cannot possibly lead to a valid UTF-8 code unit sequence. If there were +previous bytes that represented a *prefix* of a well-formed UTF-8 code unit +sequence, then all of those bytes (up to 3) are substituted with a single +replacement codepoint. For example: + +``` +use bstr::ByteSlice; + +let bs = b"a\xF0\x9F\x87z"; +let chars: Vec = bs.chars().collect(); +// The bytes \xF0\x9F\x87 could lead to a valid UTF-8 sequence, but 3 of them +// on their own are invalid. Only one replacement codepoint is substituted, +// which demonstrates the "substitution of maximal subparts" strategy. +assert_eq!(vec!['a', '\u{FFFD}', 'z'], chars); +``` + +If you do need to access the raw bytes for some reason in an iterator like +`Chars`, then you should use the iterator's "indices" variant, which gives +the byte offsets containing the invalid UTF-8 bytes that were substituted with +the replacement codepoint. For example: + +``` +use bstr::{B, ByteSlice}; + +let bs = b"a\xE2\x98z"; +let chars: Vec<(usize, usize, char)> = bs.char_indices().collect(); +// Even though the replacement codepoint is encoded as 3 bytes itself, the +// byte range given here is only two bytes, corresponding to the original +// raw bytes. +assert_eq!(vec![(0, 1, 'a'), (1, 3, '\u{FFFD}'), (3, 4, 'z')], chars); + +// Thus, getting the original raw bytes is as simple as slicing the original +// byte string: +let chars: Vec<&[u8]> = bs.char_indices().map(|(s, e, _)| &bs[s..e]).collect(); +assert_eq!(vec![B("a"), B(b"\xE2\x98"), B("z")], chars); +``` + +# File paths and OS strings + +One of the premiere features of Rust's standard library is how it handles file +paths. In particular, it makes it very hard to write incorrect code while +simultaneously providing a correct cross platform abstraction for manipulating +file paths. The key challenge that one faces with file paths across platforms +is derived from the following observations: + +* On most Unix-like systems, file paths are an arbitrary sequence of bytes. +* On Windows, file paths are an arbitrary sequence of 16-bit integers. + +(In both cases, certain sequences aren't allowed. For example a `NUL` byte is +not allowed in either case. But we can ignore this for the purposes of this +section.) + +Byte strings, like the ones provided in this crate, line up really well with +file paths on Unix like systems, which are themselves just arbitrary sequences +of bytes. It turns out that if you treat them as "mostly UTF-8," then things +work out pretty well. On the contrary, byte strings _don't_ really work +that well on Windows because it's not possible to correctly roundtrip file +paths between 16-bit integers and something that looks like UTF-8 _without_ +explicitly defining an encoding to do this for you, which is anathema to byte +strings, which are just bytes. + +Rust's standard library elegantly solves this problem by specifying an +internal encoding for file paths that's only used on Windows called +[WTF-8](https://simonsapin.github.io/wtf-8/). Its key properties are that they +permit losslessly roundtripping file paths on Windows by extending UTF-8 to +support an encoding of surrogate codepoints, while simultaneously supporting +zero-cost conversion from Rust's Unicode strings to file paths. (Since UTF-8 is +a proper subset of WTF-8.) + +The fundamental point at which the above strategy fails is when you want to +treat file paths as things that look like strings in a zero cost way. In most +cases, this is actually the wrong thing to do, but some cases call for it, +for example, glob or regex matching on file paths. This is because WTF-8 is +treated as an internal implementation detail, and there is no way to access +those bytes via a public API. Therefore, such consumers are limited in what +they can do: + +1. One could re-implement WTF-8 and re-encode file paths on Windows to WTF-8 + by accessing their underlying 16-bit integer representation. Unfortunately, + this isn't zero cost (it introduces a second WTF-8 decoding step) and it's + not clear this is a good thing to do, since WTF-8 should ideally remain an + internal implementation detail. +2. One could instead declare that they will not handle paths on Windows that + are not valid UTF-16, and return an error when one is encountered. +3. Like (2), but instead of returning an error, lossily decode the file path + on Windows that isn't valid UTF-16 into UTF-16 by replacing invalid bytes + with the Unicode replacement codepoint. + +While this library may provide facilities for (1) in the future, currently, +this library only provides facilities for (2) and (3). In particular, a suite +of conversion functions are provided that permit converting between byte +strings, OS strings and file paths. For owned byte strings, they are: + +* [`ByteVec::from_os_string`](trait.ByteVec.html#method.from_os_string) +* [`ByteVec::from_os_str_lossy`](trait.ByteVec.html#method.from_os_str_lossy) +* [`ByteVec::from_path_buf`](trait.ByteVec.html#method.from_path_buf) +* [`ByteVec::from_path_lossy`](trait.ByteVec.html#method.from_path_lossy) +* [`ByteVec::into_os_string`](trait.ByteVec.html#method.into_os_string) +* [`ByteVec::into_os_string_lossy`](trait.ByteVec.html#method.into_os_string_lossy) +* [`ByteVec::into_path_buf`](trait.ByteVec.html#method.into_path_buf) +* [`ByteVec::into_path_buf_lossy`](trait.ByteVec.html#method.into_path_buf_lossy) + +For byte string slices, they are: + +* [`ByteSlice::from_os_str`](trait.ByteSlice.html#method.from_os_str) +* [`ByteSlice::from_path`](trait.ByteSlice.html#method.from_path) +* [`ByteSlice::to_os_str`](trait.ByteSlice.html#method.to_os_str) +* [`ByteSlice::to_os_str_lossy`](trait.ByteSlice.html#method.to_os_str_lossy) +* [`ByteSlice::to_path`](trait.ByteSlice.html#method.to_path) +* [`ByteSlice::to_path_lossy`](trait.ByteSlice.html#method.to_path_lossy) + +On Unix, all of these conversions are rigorously zero cost, which gives one +a way to ergonomically deal with raw file paths exactly as they are using +normal string-related functions. On Windows, these conversion routines perform +a UTF-8 check and either return an error or lossily decode the file path +into valid UTF-8, depending on which function you use. This means that you +cannot roundtrip all file paths on Windows correctly using these conversion +routines. However, this may be an acceptable downside since such file paths +are exceptionally rare. Moreover, roundtripping isn't always necessary, for +example, if all you're doing is filtering based on file paths. + +The reason why using byte strings for this is potentially superior than the +standard library's approach is that a lot of Rust code is already lossily +converting file paths to Rust's Unicode strings, which are required to be valid +UTF-8, and thus contain latent bugs on Unix where paths with invalid UTF-8 are +not terribly uncommon. If you instead use byte strings, then you're guaranteed +to write correct code for Unix, at the cost of getting a corner case wrong on +Windows. +*/ + +#![cfg_attr(not(feature = "std"), no_std)] +#![allow(dead_code)] + +#[cfg(feature = "std")] +extern crate core; + +#[cfg(feature = "unicode")] +#[macro_use] +extern crate lazy_static; +extern crate memchr; +#[cfg(test)] +#[macro_use] +extern crate quickcheck; +#[cfg(feature = "unicode")] +extern crate regex_automata; +#[cfg(feature = "serde1-nostd")] +extern crate serde; +#[cfg(test)] +extern crate ucd_parse; + +pub use bstr::BStr; +#[cfg(feature = "std")] +pub use bstring::BString; +pub use ext_slice::{ + ByteSlice, Bytes, Fields, FieldsWith, Find, FindReverse, Finder, + FinderReverse, Lines, LinesWithTerminator, Split, SplitN, SplitNReverse, + SplitReverse, B, +}; +#[cfg(feature = "std")] +pub use ext_vec::{concat, join, ByteVec, DrainBytes, FromUtf8Error}; +#[cfg(feature = "unicode")] +pub use unicode::{ + GraphemeIndices, Graphemes, SentenceIndices, Sentences, WordIndices, + Words, WordsWithBreakIndices, WordsWithBreaks, +}; +pub use utf8::{ + decode as decode_utf8, decode_last as decode_last_utf8, CharIndices, + Chars, Utf8Chunk, Utf8Chunks, Utf8Error, +}; + +mod ascii; +mod bstr; +#[cfg(feature = "std")] +mod bstring; +mod byteset; +mod cow; +mod ext_slice; +#[cfg(feature = "std")] +mod ext_vec; +mod impls; +#[cfg(feature = "std")] +pub mod io; +mod search; +#[cfg(test)] +mod tests; +#[cfg(feature = "unicode")] +mod unicode; +mod utf8; + +#[cfg(test)] +mod apitests { + use bstr::BStr; + use bstring::BString; + use ext_slice::{Finder, FinderReverse}; + + #[test] + fn oibits() { + use std::panic::{RefUnwindSafe, UnwindSafe}; + + fn assert_send() {} + fn assert_sync() {} + fn assert_unwind_safe() {} + + assert_send::<&BStr>(); + assert_sync::<&BStr>(); + assert_unwind_safe::<&BStr>(); + assert_send::(); + assert_sync::(); + assert_unwind_safe::(); + + assert_send::(); + assert_sync::(); + assert_unwind_safe::(); + assert_send::(); + assert_sync::(); + assert_unwind_safe::(); + } +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/search/byte_frequencies.rs b/third_party/cargo/vendor/bstr-0.2.15/src/search/byte_frequencies.rs new file mode 100644 index 0000000..c313b62 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/search/byte_frequencies.rs @@ -0,0 +1,258 @@ +pub const BYTE_FREQUENCIES: [u8; 256] = [ + 55, // '\x00' + 52, // '\x01' + 51, // '\x02' + 50, // '\x03' + 49, // '\x04' + 48, // '\x05' + 47, // '\x06' + 46, // '\x07' + 45, // '\x08' + 103, // '\t' + 242, // '\n' + 66, // '\x0b' + 67, // '\x0c' + 229, // '\r' + 44, // '\x0e' + 43, // '\x0f' + 42, // '\x10' + 41, // '\x11' + 40, // '\x12' + 39, // '\x13' + 38, // '\x14' + 37, // '\x15' + 36, // '\x16' + 35, // '\x17' + 34, // '\x18' + 33, // '\x19' + 56, // '\x1a' + 32, // '\x1b' + 31, // '\x1c' + 30, // '\x1d' + 29, // '\x1e' + 28, // '\x1f' + 255, // ' ' + 148, // '!' + 164, // '"' + 149, // '#' + 136, // '$' + 160, // '%' + 155, // '&' + 173, // "'" + 221, // '(' + 222, // ')' + 134, // '*' + 122, // '+' + 232, // ',' + 202, // '-' + 215, // '.' + 224, // '/' + 208, // '0' + 220, // '1' + 204, // '2' + 187, // '3' + 183, // '4' + 179, // '5' + 177, // '6' + 168, // '7' + 178, // '8' + 200, // '9' + 226, // ':' + 195, // ';' + 154, // '<' + 184, // '=' + 174, // '>' + 126, // '?' + 120, // '@' + 191, // 'A' + 157, // 'B' + 194, // 'C' + 170, // 'D' + 189, // 'E' + 162, // 'F' + 161, // 'G' + 150, // 'H' + 193, // 'I' + 142, // 'J' + 137, // 'K' + 171, // 'L' + 176, // 'M' + 185, // 'N' + 167, // 'O' + 186, // 'P' + 112, // 'Q' + 175, // 'R' + 192, // 'S' + 188, // 'T' + 156, // 'U' + 140, // 'V' + 143, // 'W' + 123, // 'X' + 133, // 'Y' + 128, // 'Z' + 147, // '[' + 138, // '\\' + 146, // ']' + 114, // '^' + 223, // '_' + 151, // '`' + 249, // 'a' + 216, // 'b' + 238, // 'c' + 236, // 'd' + 253, // 'e' + 227, // 'f' + 218, // 'g' + 230, // 'h' + 247, // 'i' + 135, // 'j' + 180, // 'k' + 241, // 'l' + 233, // 'm' + 246, // 'n' + 244, // 'o' + 231, // 'p' + 139, // 'q' + 245, // 'r' + 243, // 's' + 251, // 't' + 235, // 'u' + 201, // 'v' + 196, // 'w' + 240, // 'x' + 214, // 'y' + 152, // 'z' + 182, // '{' + 205, // '|' + 181, // '}' + 127, // '~' + 27, // '\x7f' + 212, // '\x80' + 211, // '\x81' + 210, // '\x82' + 213, // '\x83' + 228, // '\x84' + 197, // '\x85' + 169, // '\x86' + 159, // '\x87' + 131, // '\x88' + 172, // '\x89' + 105, // '\x8a' + 80, // '\x8b' + 98, // '\x8c' + 96, // '\x8d' + 97, // '\x8e' + 81, // '\x8f' + 207, // '\x90' + 145, // '\x91' + 116, // '\x92' + 115, // '\x93' + 144, // '\x94' + 130, // '\x95' + 153, // '\x96' + 121, // '\x97' + 107, // '\x98' + 132, // '\x99' + 109, // '\x9a' + 110, // '\x9b' + 124, // '\x9c' + 111, // '\x9d' + 82, // '\x9e' + 108, // '\x9f' + 118, // '\xa0' + 141, // '¡' + 113, // '¢' + 129, // '£' + 119, // '¤' + 125, // '¥' + 165, // '¦' + 117, // '§' + 92, // '¨' + 106, // '©' + 83, // 'ª' + 72, // '«' + 99, // '¬' + 93, // '\xad' + 65, // '®' + 79, // '¯' + 166, // '°' + 237, // '±' + 163, // '²' + 199, // '³' + 190, // '´' + 225, // 'µ' + 209, // '¶' + 203, // '·' + 198, // '¸' + 217, // '¹' + 219, // 'º' + 206, // '»' + 234, // '¼' + 248, // '½' + 158, // '¾' + 239, // '¿' + 255, // 'À' + 255, // 'Á' + 255, // 'Â' + 255, // 'Ã' + 255, // 'Ä' + 255, // 'Å' + 255, // 'Æ' + 255, // 'Ç' + 255, // 'È' + 255, // 'É' + 255, // 'Ê' + 255, // 'Ë' + 255, // 'Ì' + 255, // 'Í' + 255, // 'Î' + 255, // 'Ï' + 255, // 'Ð' + 255, // 'Ñ' + 255, // 'Ò' + 255, // 'Ó' + 255, // 'Ô' + 255, // 'Õ' + 255, // 'Ö' + 255, // '×' + 255, // 'Ø' + 255, // 'Ù' + 255, // 'Ú' + 255, // 'Û' + 255, // 'Ü' + 255, // 'Ý' + 255, // 'Þ' + 255, // 'ß' + 255, // 'à' + 255, // 'á' + 255, // 'â' + 255, // 'ã' + 255, // 'ä' + 255, // 'å' + 255, // 'æ' + 255, // 'ç' + 255, // 'è' + 255, // 'é' + 255, // 'ê' + 255, // 'ë' + 255, // 'ì' + 255, // 'í' + 255, // 'î' + 255, // 'ï' + 255, // 'ð' + 255, // 'ñ' + 255, // 'ò' + 255, // 'ó' + 255, // 'ô' + 255, // 'õ' + 255, // 'ö' + 255, // '÷' + 255, // 'ø' + 255, // 'ù' + 255, // 'ú' + 255, // 'û' + 255, // 'ü' + 255, // 'ý' + 255, // 'þ' + 255, // 'ÿ' +]; diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/search/mod.rs b/third_party/cargo/vendor/bstr-0.2.15/src/search/mod.rs new file mode 100644 index 0000000..a0d1b45 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/search/mod.rs @@ -0,0 +1,8 @@ +pub use self::prefilter::PrefilterState; +pub use self::twoway::TwoWay; + +mod byte_frequencies; +mod prefilter; +#[cfg(test)] +mod tests; +mod twoway; diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/search/prefilter.rs b/third_party/cargo/vendor/bstr-0.2.15/src/search/prefilter.rs new file mode 100644 index 0000000..00e6acf --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/search/prefilter.rs @@ -0,0 +1,424 @@ +use core::mem; + +use ext_slice::ByteSlice; +use search::byte_frequencies::BYTE_FREQUENCIES; + +/// PrefilterState tracks state associated with the effectiveness of a +/// prefilter. It is used to track how many bytes, on average, are skipped by +/// the prefilter. If this average dips below a certain threshold over time, +/// then the state renders the prefilter inert and stops using it. +/// +/// A prefilter state should be created for each search. (Where creating an +/// iterator via, e.g., `find_iter`, is treated as a single search.) +#[derive(Clone, Debug)] +pub struct PrefilterState { + /// The number of skips that has been executed. + skips: usize, + /// The total number of bytes that have been skipped. + skipped: usize, + /// The maximum length of a match. This is used to help determine how many + /// bytes on average should be skipped in order for a prefilter to be + /// effective. + max_match_len: usize, + /// Once this heuristic has been deemed ineffective, it will be inert + /// throughout the rest of its lifetime. This serves as a cheap way to + /// check inertness. + inert: bool, +} + +impl PrefilterState { + /// The minimum number of skip attempts to try before considering whether + /// a prefilter is effective or not. + const MIN_SKIPS: usize = 50; + + /// The minimum amount of bytes that skipping must average. + /// + /// This value was chosen based on varying it and checking the bstr/find/ + /// microbenchmarks. In particular, this can impact the + /// pathological/repeated-{huge,small} benchmarks quite a bit if it's + /// set too low. + const MIN_SKIP_BYTES: usize = 8; + + /// Create a fresh prefilter state. + pub fn new(max_match_len: usize) -> PrefilterState { + if max_match_len == 0 { + return PrefilterState::inert(); + } + PrefilterState { skips: 0, skipped: 0, max_match_len, inert: false } + } + + /// Create a fresh prefilter state that is always inert. + fn inert() -> PrefilterState { + PrefilterState { skips: 0, skipped: 0, max_match_len: 0, inert: true } + } + + /// Update this state with the number of bytes skipped on the last + /// invocation of the prefilter. + #[inline] + pub fn update(&mut self, skipped: usize) { + self.skips += 1; + self.skipped += skipped; + } + + /// Return true if and only if this state indicates that a prefilter is + /// still effective. + #[inline] + pub fn is_effective(&mut self) -> bool { + if self.inert { + return false; + } + if self.skips < PrefilterState::MIN_SKIPS { + return true; + } + if self.skipped >= PrefilterState::MIN_SKIP_BYTES * self.skips { + return true; + } + + // We're inert. + self.inert = true; + false + } +} + +/// A heuristic frequency based prefilter for searching a single needle. +/// +/// This prefilter attempts to pick out the byte in a needle that is predicted +/// to occur least frequently, and search for that using fast vectorized +/// routines. If a rare enough byte could not be found, then this prefilter's +/// constructors will return `None`. +/// +/// This can be combined with `PrefilterState` to dynamically render this +/// prefilter inert if it proves to ineffective. +#[derive(Clone, Debug)] +pub struct Freqy { + /// Whether this prefilter should be used or not. + inert: bool, + /// The length of the needle we're searching for. + needle_len: usize, + /// The rarest byte in the needle, according to pre-computed frequency + /// analysis. + rare1: u8, + /// The leftmost offset of the rarest byte in the needle. + rare1i: usize, + /// The second rarest byte in the needle, according to pre-computed + /// frequency analysis. (This may be equivalent to the rarest byte.) + /// + /// The second rarest byte is used as a type of guard for quickly detecting + /// a mismatch after memchr locates an instance of the rarest byte. This + /// is a hedge against pathological cases where the pre-computed frequency + /// analysis may be off. (But of course, does not prevent *all* + /// pathological cases.) + rare2: u8, + /// The leftmost offset of the second rarest byte in the needle. + rare2i: usize, +} + +impl Freqy { + /// The maximum frequency rank permitted. If the rarest byte in the needle + /// has a frequency rank above this value, then Freqy is not used. + const MAX_RANK: usize = 200; + + /// Return a fresh prefilter state that can be used with this prefilter. A + /// prefilter state is used to track the effectiveness of a prefilter for + /// speeding up searches. Therefore, the prefilter state should generally + /// be reused on subsequent searches (such as in an iterator). For searches + /// on a different haystack, then a new prefilter state should be used. + pub fn prefilter_state(&self) -> PrefilterState { + if self.inert { + PrefilterState::inert() + } else { + PrefilterState::new(self.needle_len) + } + } + + /// Returns a valid but inert prefilter. This is valid for both the forward + /// and reverse direction. + /// + /// It is never correct to use an inert prefilter. The results of finding + /// the next (or previous) candidate are unspecified. + fn inert() -> Freqy { + Freqy { + inert: true, + needle_len: 0, + rare1: 0, + rare1i: 0, + rare2: 0, + rare2i: 0, + } + } + + /// Return search info for the given needle in the forward direction. + pub fn forward(needle: &[u8]) -> Freqy { + if needle.is_empty() { + return Freqy::inert(); + } + + // Find the rarest two bytes. Try to make them distinct (but it's not + // required). + let (mut rare1, mut rare1i) = (needle[0], 0); + let (mut rare2, mut rare2i) = (needle[0], 0); + if needle.len() >= 2 { + rare2 = needle[1]; + rare2i = 1; + } + if Freqy::rank(rare2) < Freqy::rank(rare1) { + mem::swap(&mut rare1, &mut rare2); + mem::swap(&mut rare1i, &mut rare2i); + } + for (i, b) in needle.bytes().enumerate().skip(2) { + if Freqy::rank(b) < Freqy::rank(rare1) { + rare2 = rare1; + rare2i = rare1i; + rare1 = b; + rare1i = i; + } else if b != rare1 && Freqy::rank(b) < Freqy::rank(rare2) { + rare2 = b; + rare2i = i; + } + } + if Freqy::rank(rare1) > Freqy::MAX_RANK { + return Freqy::inert(); + } + let needle_len = needle.len(); + Freqy { inert: false, needle_len, rare1, rare1i, rare2, rare2i } + } + + /// Return search info for the given needle in the reverse direction. + pub fn reverse(needle: &[u8]) -> Freqy { + if needle.is_empty() { + return Freqy::inert(); + } + + // Find the rarest two bytes. Try to make them distinct (but it's not + // required). In reverse, the offsets correspond to the number of bytes + // from the end of the needle. So `0` is the last byte in the needle. + let (mut rare1i, mut rare2i) = (0, 0); + if needle.len() >= 2 { + rare2i += 1; + } + let mut rare1 = needle[needle.len() - rare1i - 1]; + let mut rare2 = needle[needle.len() - rare2i - 1]; + if Freqy::rank(rare2) < Freqy::rank(rare1) { + mem::swap(&mut rare1, &mut rare2); + mem::swap(&mut rare1i, &mut rare2i); + } + for (i, b) in needle.bytes().rev().enumerate().skip(2) { + if Freqy::rank(b) < Freqy::rank(rare1) { + rare2 = rare1; + rare2i = rare1i; + rare1 = b; + rare1i = i; + } else if b != rare1 && Freqy::rank(b) < Freqy::rank(rare2) { + rare2 = b; + rare2i = i; + } + } + if Freqy::rank(rare1) > Freqy::MAX_RANK { + return Freqy::inert(); + } + let needle_len = needle.len(); + Freqy { inert: false, needle_len, rare1, rare1i, rare2, rare2i } + } + + /// Look for a possible occurrence of needle. The position returned + /// corresponds to the beginning of the occurrence, if one exists. + /// + /// Callers may assume that this never returns false negatives (i.e., it + /// never misses an actual occurrence), but must check that the returned + /// position corresponds to a match. That is, it can return false + /// positives. + /// + /// This should only be used when Freqy is constructed for forward + /// searching. + pub fn find_candidate( + &self, + prestate: &mut PrefilterState, + haystack: &[u8], + ) -> Option { + debug_assert!(!self.inert); + + let mut i = 0; + while prestate.is_effective() { + // Use a fast vectorized implementation to skip to the next + // occurrence of the rarest byte (heuristically chosen) in the + // needle. + i += match haystack[i..].find_byte(self.rare1) { + None => return None, + Some(found) => { + prestate.update(found); + found + } + }; + + // If we can't align our first match with the haystack, then a + // match is impossible. + if i < self.rare1i { + i += 1; + continue; + } + + // Align our rare2 byte with the haystack. A mismatch means that + // a match is impossible. + let aligned_rare2i = i - self.rare1i + self.rare2i; + if haystack.get(aligned_rare2i) != Some(&self.rare2) { + i += 1; + continue; + } + + // We've done what we can. There might be a match here. + return Some(i - self.rare1i); + } + // The only way we get here is if we believe our skipping heuristic + // has become ineffective. We're allowed to return false positives, + // so return the position at which we advanced to, aligned to the + // haystack. + Some(i.saturating_sub(self.rare1i)) + } + + /// Look for a possible occurrence of needle, in reverse, starting from the + /// end of the given haystack. The position returned corresponds to the + /// position immediately after the end of the occurrence, if one exists. + /// + /// Callers may assume that this never returns false negatives (i.e., it + /// never misses an actual occurrence), but must check that the returned + /// position corresponds to a match. That is, it can return false + /// positives. + /// + /// This should only be used when Freqy is constructed for reverse + /// searching. + pub fn rfind_candidate( + &self, + prestate: &mut PrefilterState, + haystack: &[u8], + ) -> Option { + debug_assert!(!self.inert); + + let mut i = haystack.len(); + while prestate.is_effective() { + // Use a fast vectorized implementation to skip to the next + // occurrence of the rarest byte (heuristically chosen) in the + // needle. + i = match haystack[..i].rfind_byte(self.rare1) { + None => return None, + Some(found) => { + prestate.update(i - found); + found + } + }; + + // If we can't align our first match with the haystack, then a + // match is impossible. + if i + self.rare1i + 1 > haystack.len() { + continue; + } + + // Align our rare2 byte with the haystack. A mismatch means that + // a match is impossible. + let aligned = match (i + self.rare1i).checked_sub(self.rare2i) { + None => continue, + Some(aligned) => aligned, + }; + if haystack.get(aligned) != Some(&self.rare2) { + continue; + } + + // We've done what we can. There might be a match here. + return Some(i + self.rare1i + 1); + } + // The only way we get here is if we believe our skipping heuristic + // has become ineffective. We're allowed to return false positives, + // so return the position at which we advanced to, aligned to the + // haystack. + Some(i + self.rare1i + 1) + } + + /// Return the heuristical frequency rank of the given byte. A lower rank + /// means the byte is believed to occur less frequently. + fn rank(b: u8) -> usize { + BYTE_FREQUENCIES[b as usize] as usize + } +} + +#[cfg(test)] +mod tests { + use super::*; + use ext_slice::B; + + #[test] + fn freqy_forward() { + // N.B. We sometimes use uppercase here since that mostly ensures freqy + // will be constructable. Lowercase letters may be too common for freqy + // to work. + + let s = Freqy::forward(B("BAR")); + let mut pre = s.prefilter_state(); + assert_eq!(Some(0), s.find_candidate(&mut pre, B("BARFOO"))); + + let s = Freqy::forward(B("BAR")); + let mut pre = s.prefilter_state(); + assert_eq!(Some(3), s.find_candidate(&mut pre, B("FOOBAR"))); + + let s = Freqy::forward(B("zyzy")); + let mut pre = s.prefilter_state(); + assert_eq!(Some(0), s.find_candidate(&mut pre, B("zyzz"))); + + let s = Freqy::forward(B("zyzy")); + let mut pre = s.prefilter_state(); + assert_eq!(Some(2), s.find_candidate(&mut pre, B("zzzy"))); + + let s = Freqy::forward(B("zyzy")); + let mut pre = s.prefilter_state(); + assert_eq!(None, s.find_candidate(&mut pre, B("zazb"))); + + let s = Freqy::forward(B("yzyz")); + let mut pre = s.prefilter_state(); + assert_eq!(Some(0), s.find_candidate(&mut pre, B("yzyy"))); + + let s = Freqy::forward(B("yzyz")); + let mut pre = s.prefilter_state(); + assert_eq!(Some(2), s.find_candidate(&mut pre, B("yyyz"))); + + let s = Freqy::forward(B("yzyz")); + let mut pre = s.prefilter_state(); + assert_eq!(None, s.find_candidate(&mut pre, B("yayb"))); + } + + #[test] + fn freqy_reverse() { + // N.B. We sometimes use uppercase here since that mostly ensures freqy + // will be constructable. Lowercase letters may be too common for freqy + // to work. + + let s = Freqy::reverse(B("BAR")); + let mut pre = s.prefilter_state(); + assert_eq!(Some(3), s.rfind_candidate(&mut pre, B("BARFOO"))); + + let s = Freqy::reverse(B("BAR")); + let mut pre = s.prefilter_state(); + assert_eq!(Some(6), s.rfind_candidate(&mut pre, B("FOOBAR"))); + + let s = Freqy::reverse(B("zyzy")); + let mut pre = s.prefilter_state(); + assert_eq!(Some(2), s.rfind_candidate(&mut pre, B("zyzz"))); + + let s = Freqy::reverse(B("zyzy")); + let mut pre = s.prefilter_state(); + assert_eq!(Some(4), s.rfind_candidate(&mut pre, B("zzzy"))); + + let s = Freqy::reverse(B("zyzy")); + let mut pre = s.prefilter_state(); + assert_eq!(None, s.rfind_candidate(&mut pre, B("zazb"))); + + let s = Freqy::reverse(B("yzyz")); + let mut pre = s.prefilter_state(); + assert_eq!(Some(2), s.rfind_candidate(&mut pre, B("yzyy"))); + + let s = Freqy::reverse(B("yzyz")); + let mut pre = s.prefilter_state(); + assert_eq!(Some(4), s.rfind_candidate(&mut pre, B("yyyz"))); + + let s = Freqy::reverse(B("yzyz")); + let mut pre = s.prefilter_state(); + assert_eq!(None, s.rfind_candidate(&mut pre, B("yayb"))); + } +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/search/tests.rs b/third_party/cargo/vendor/bstr-0.2.15/src/search/tests.rs new file mode 100644 index 0000000..827df92 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/search/tests.rs @@ -0,0 +1,225 @@ +use search::twoway::TwoWay; + +/// Each test is a (needle, haystack, expected_fwd, expected_rev) tuple. +type SearchTest = (&'static str, &'static str, Option, Option); + +const SEARCH_TESTS: &'static [SearchTest] = &[ + ("", "", Some(0), Some(0)), + ("", "a", Some(0), Some(1)), + ("", "ab", Some(0), Some(2)), + ("", "abc", Some(0), Some(3)), + ("a", "", None, None), + ("a", "a", Some(0), Some(0)), + ("a", "aa", Some(0), Some(1)), + ("a", "ba", Some(1), Some(1)), + ("a", "bba", Some(2), Some(2)), + ("a", "bbba", Some(3), Some(3)), + ("a", "bbbab", Some(3), Some(3)), + ("a", "bbbabb", Some(3), Some(3)), + ("a", "bbbabbb", Some(3), Some(3)), + ("a", "bbbbbb", None, None), + ("ab", "", None, None), + ("ab", "a", None, None), + ("ab", "b", None, None), + ("ab", "ab", Some(0), Some(0)), + ("ab", "aab", Some(1), Some(1)), + ("ab", "aaab", Some(2), Some(2)), + ("ab", "abaab", Some(0), Some(3)), + ("ab", "baaab", Some(3), Some(3)), + ("ab", "acb", None, None), + ("ab", "abba", Some(0), Some(0)), + ("abc", "ab", None, None), + ("abc", "abc", Some(0), Some(0)), + ("abc", "abcz", Some(0), Some(0)), + ("abc", "abczz", Some(0), Some(0)), + ("abc", "zabc", Some(1), Some(1)), + ("abc", "zzabc", Some(2), Some(2)), + ("abc", "azbc", None, None), + ("abc", "abzc", None, None), + ("abczdef", "abczdefzzzzzzzzzzzzzzzzzzzz", Some(0), Some(0)), + ("abczdef", "zzzzzzzzzzzzzzzzzzzzabczdef", Some(20), Some(20)), + // Failures caught by quickcheck. + ("\u{0}\u{15}", "\u{0}\u{15}\u{15}\u{0}", Some(0), Some(0)), + ("\u{0}\u{1e}", "\u{1e}\u{0}", None, None), +]; + +#[test] +fn unit_twoway_fwd() { + run_search_tests_fwd("TwoWay", |n, h| TwoWay::forward(n).find(h)); +} + +#[test] +fn unit_twoway_rev() { + run_search_tests_rev("TwoWay", |n, h| TwoWay::reverse(n).rfind(h)); +} + +/// Run the substring search tests. `name` should be the type of searcher used, +/// for diagnostics. `search` should be a closure that accepts a needle and a +/// haystack and returns the starting position of the first occurrence of +/// needle in the haystack, or `None` if one doesn't exist. +fn run_search_tests_fwd( + name: &str, + mut search: impl FnMut(&[u8], &[u8]) -> Option, +) { + for &(needle, haystack, expected_fwd, _) in SEARCH_TESTS { + let (n, h) = (needle.as_bytes(), haystack.as_bytes()); + assert_eq!( + expected_fwd, + search(n, h), + "{}: needle: {:?}, haystack: {:?}, expected: {:?}", + name, + n, + h, + expected_fwd + ); + } +} + +/// Run the substring search tests. `name` should be the type of searcher used, +/// for diagnostics. `search` should be a closure that accepts a needle and a +/// haystack and returns the starting position of the last occurrence of +/// needle in the haystack, or `None` if one doesn't exist. +fn run_search_tests_rev( + name: &str, + mut search: impl FnMut(&[u8], &[u8]) -> Option, +) { + for &(needle, haystack, _, expected_rev) in SEARCH_TESTS { + let (n, h) = (needle.as_bytes(), haystack.as_bytes()); + assert_eq!( + expected_rev, + search(n, h), + "{}: needle: {:?}, haystack: {:?}, expected: {:?}", + name, + n, + h, + expected_rev + ); + } +} + +quickcheck! { + fn qc_twoway_fwd_prefix_is_substring(bs: Vec) -> bool { + prop_prefix_is_substring(false, &bs, |n, h| TwoWay::forward(n).find(h)) + } + + fn qc_twoway_fwd_suffix_is_substring(bs: Vec) -> bool { + prop_suffix_is_substring(false, &bs, |n, h| TwoWay::forward(n).find(h)) + } + + fn qc_twoway_rev_prefix_is_substring(bs: Vec) -> bool { + prop_prefix_is_substring(true, &bs, |n, h| TwoWay::reverse(n).rfind(h)) + } + + fn qc_twoway_rev_suffix_is_substring(bs: Vec) -> bool { + prop_suffix_is_substring(true, &bs, |n, h| TwoWay::reverse(n).rfind(h)) + } + + fn qc_twoway_fwd_matches_naive( + needle: Vec, + haystack: Vec + ) -> bool { + prop_matches_naive( + false, + &needle, + &haystack, + |n, h| TwoWay::forward(n).find(h), + ) + } + + fn qc_twoway_rev_matches_naive( + needle: Vec, + haystack: Vec + ) -> bool { + prop_matches_naive( + true, + &needle, + &haystack, + |n, h| TwoWay::reverse(n).rfind(h), + ) + } +} + +/// Check that every prefix of the given byte string is a substring. +fn prop_prefix_is_substring( + reverse: bool, + bs: &[u8], + mut search: impl FnMut(&[u8], &[u8]) -> Option, +) -> bool { + if bs.is_empty() { + return true; + } + for i in 0..(bs.len() - 1) { + let prefix = &bs[..i]; + if reverse { + assert_eq!(naive_rfind(prefix, bs), search(prefix, bs)); + } else { + assert_eq!(naive_find(prefix, bs), search(prefix, bs)); + } + } + true +} + +/// Check that every suffix of the given byte string is a substring. +fn prop_suffix_is_substring( + reverse: bool, + bs: &[u8], + mut search: impl FnMut(&[u8], &[u8]) -> Option, +) -> bool { + if bs.is_empty() { + return true; + } + for i in 0..(bs.len() - 1) { + let suffix = &bs[i..]; + if reverse { + assert_eq!(naive_rfind(suffix, bs), search(suffix, bs)); + } else { + assert_eq!(naive_find(suffix, bs), search(suffix, bs)); + } + } + true +} + +/// Check that naive substring search matches the result of the given search +/// algorithm. +fn prop_matches_naive( + reverse: bool, + needle: &[u8], + haystack: &[u8], + mut search: impl FnMut(&[u8], &[u8]) -> Option, +) -> bool { + if reverse { + naive_rfind(needle, haystack) == search(needle, haystack) + } else { + naive_find(needle, haystack) == search(needle, haystack) + } +} + +/// Naively search forwards for the given needle in the given haystack. +fn naive_find(needle: &[u8], haystack: &[u8]) -> Option { + if needle.is_empty() { + return Some(0); + } else if haystack.len() < needle.len() { + return None; + } + for i in 0..(haystack.len() - needle.len() + 1) { + if needle == &haystack[i..i + needle.len()] { + return Some(i); + } + } + None +} + +/// Naively search in reverse for the given needle in the given haystack. +fn naive_rfind(needle: &[u8], haystack: &[u8]) -> Option { + if needle.is_empty() { + return Some(haystack.len()); + } else if haystack.len() < needle.len() { + return None; + } + for i in (0..(haystack.len() - needle.len() + 1)).rev() { + if needle == &haystack[i..i + needle.len()] { + return Some(i); + } + } + None +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/search/twoway.rs b/third_party/cargo/vendor/bstr-0.2.15/src/search/twoway.rs new file mode 100644 index 0000000..5f1e8cf --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/search/twoway.rs @@ -0,0 +1,871 @@ +use core::cmp; + +use cow::CowBytes; +use ext_slice::ByteSlice; +use search::prefilter::{Freqy, PrefilterState}; + +/// An implementation of the TwoWay substring search algorithm, with heuristics +/// for accelerating search based on frequency analysis. +/// +/// This searcher supports forward and reverse search, although not +/// simultaneously. It runs in O(n + m) time and O(1) space, where +/// `n ~ len(needle)` and `m ~ len(haystack)`. +/// +/// The implementation here roughly matches that which was developed by +/// Crochemore and Perrin in their 1991 paper "Two-way string-matching." The +/// only change in this implementation is the use of zero-based indices and +/// the addition of heuristics for a fast skip loop. That is, this will detect +/// bytes that are believed to be rare in the needle and use fast vectorized +/// instructions to find their occurrences quickly. The Two-Way algorithm is +/// then used to confirm whether a match at that location occurred. +/// +/// The heuristic for fast skipping is automatically shut off if it's +/// detected to be ineffective at search time. Generally, this only occurs in +/// pathological cases. But this is generally necessary in order to preserve +/// a `O(n + m)` time bound. +/// +/// The code below is fairly complex and not obviously correct at all. It's +/// likely necessary to read the Two-Way paper cited above in order to fully +/// grok this code. +#[derive(Clone, Debug)] +pub struct TwoWay<'b> { + /// The needle that we're looking for. + needle: CowBytes<'b>, + /// An implementation of a fast skip loop based on hard-coded frequency + /// data. This is only used when conditions are deemed favorable. + freqy: Freqy, + /// A critical position in needle. Specifically, this position corresponds + /// to beginning of either the minimal or maximal suffix in needle. (N.B. + /// See SuffixType below for why "minimal" isn't quite the correct word + /// here.) + /// + /// This is the position at which every search begins. Namely, search + /// starts by scanning text to the right of this position, and only if + /// there's a match does the text to the left of this position get scanned. + critical_pos: usize, + /// The amount we shift by in the Two-Way search algorithm. This + /// corresponds to the "small period" and "large period" cases. + shift: Shift, +} + +impl<'b> TwoWay<'b> { + /// Create a searcher that uses the Two-Way algorithm by searching forwards + /// through any haystack. + pub fn forward(needle: &'b [u8]) -> TwoWay<'b> { + let freqy = Freqy::forward(needle); + if needle.is_empty() { + return TwoWay { + needle: CowBytes::new(needle), + freqy, + critical_pos: 0, + shift: Shift::Large { shift: 0 }, + }; + } + + let min_suffix = Suffix::forward(needle, SuffixKind::Minimal); + let max_suffix = Suffix::forward(needle, SuffixKind::Maximal); + let (period_lower_bound, critical_pos) = + if min_suffix.pos > max_suffix.pos { + (min_suffix.period, min_suffix.pos) + } else { + (max_suffix.period, max_suffix.pos) + }; + let shift = Shift::forward(needle, period_lower_bound, critical_pos); + let needle = CowBytes::new(needle); + TwoWay { needle, freqy, critical_pos, shift } + } + + /// Create a searcher that uses the Two-Way algorithm by searching in + /// reverse through any haystack. + pub fn reverse(needle: &'b [u8]) -> TwoWay<'b> { + let freqy = Freqy::reverse(needle); + if needle.is_empty() { + return TwoWay { + needle: CowBytes::new(needle), + freqy, + critical_pos: 0, + shift: Shift::Large { shift: 0 }, + }; + } + + let min_suffix = Suffix::reverse(needle, SuffixKind::Minimal); + let max_suffix = Suffix::reverse(needle, SuffixKind::Maximal); + let (period_lower_bound, critical_pos) = + if min_suffix.pos < max_suffix.pos { + (min_suffix.period, min_suffix.pos) + } else { + (max_suffix.period, max_suffix.pos) + }; + let shift = Shift::reverse(needle, period_lower_bound, critical_pos); + let needle = CowBytes::new(needle); + TwoWay { needle, freqy, critical_pos, shift } + } + + /// Return a fresh prefilter state that can be used with this searcher. + /// A prefilter state is used to track the effectiveness of a searcher's + /// prefilter for speeding up searches. Therefore, the prefilter state + /// should generally be reused on subsequent searches (such as in an + /// iterator). For searches on a different haystack, then a new prefilter + /// state should be used. + /// + /// This always initializes a valid prefilter state even if this searcher + /// does not have a prefilter enabled. + pub fn prefilter_state(&self) -> PrefilterState { + self.freqy.prefilter_state() + } + + /// Return the needle used by this searcher. + pub fn needle(&self) -> &[u8] { + self.needle.as_slice() + } + + /// Convert this searched into an owned version, where the needle is + /// copied if it isn't already owned. + #[cfg(feature = "std")] + pub fn into_owned(self) -> TwoWay<'static> { + TwoWay { + needle: self.needle.into_owned(), + freqy: self.freqy, + critical_pos: self.critical_pos, + shift: self.shift, + } + } + + /// Find the position of the first occurrence of this searcher's needle in + /// the given haystack. If one does not exist, then return None. + /// + /// This will automatically initialize prefilter state. This should only + /// be used for one-off searches. + pub fn find(&self, haystack: &[u8]) -> Option { + self.find_with(&mut self.prefilter_state(), haystack) + } + + /// Find the position of the last occurrence of this searcher's needle + /// in the given haystack. If one does not exist, then return None. + /// + /// This will automatically initialize prefilter state. This should only + /// be used for one-off searches. + pub fn rfind(&self, haystack: &[u8]) -> Option { + self.rfind_with(&mut self.prefilter_state(), haystack) + } + + /// Find the position of the first occurrence of this searcher's needle in + /// the given haystack. If one does not exist, then return None. + /// + /// This accepts prefilter state that is useful when using the same + /// searcher multiple times, such as in an iterator. + pub fn find_with( + &self, + prestate: &mut PrefilterState, + haystack: &[u8], + ) -> Option { + if self.needle.is_empty() { + return Some(0); + } else if haystack.len() < self.needle.len() { + return None; + } else if self.needle.len() == 1 { + return haystack.find_byte(self.needle[0]); + } + match self.shift { + Shift::Small { period } => { + self.find_small(prestate, haystack, period) + } + Shift::Large { shift } => { + self.find_large(prestate, haystack, shift) + } + } + } + + /// Find the position of the last occurrence of this searcher's needle + /// in the given haystack. If one does not exist, then return None. + /// + /// This accepts prefilter state that is useful when using the same + /// searcher multiple times, such as in an iterator. + pub fn rfind_with( + &self, + prestate: &mut PrefilterState, + haystack: &[u8], + ) -> Option { + if self.needle.is_empty() { + return Some(haystack.len()); + } else if haystack.len() < self.needle.len() { + return None; + } else if self.needle.len() == 1 { + return haystack.rfind_byte(self.needle[0]); + } + match self.shift { + Shift::Small { period } => { + self.rfind_small(prestate, haystack, period) + } + Shift::Large { shift } => { + self.rfind_large(prestate, haystack, shift) + } + } + } + + // Below is the actual implementation of TwoWay searching, including both + // forwards and backwards searching. Each forward and reverse search has + // two fairly similar implementations, each handling the small and large + // period cases, for a total 4 different search routines. + // + // On top of that, each search implementation can be accelerated by a + // Freqy prefilter, but it is not always enabled. To avoid its overhead + // when its disabled, we explicitly inline each search implementation based + // on whether Freqy will be used or not. This brings us up to a total of + // 8 monomorphized versions of the search code. + + #[inline(never)] + fn find_small( + &self, + prestate: &mut PrefilterState, + haystack: &[u8], + period: usize, + ) -> Option { + if prestate.is_effective() { + self.find_small_imp(prestate, true, haystack, period) + } else { + self.find_small_imp(prestate, false, haystack, period) + } + } + + #[inline(always)] + fn find_small_imp( + &self, + prestate: &mut PrefilterState, + prefilter: bool, + haystack: &[u8], + period: usize, + ) -> Option { + let needle = self.needle.as_slice(); + let mut pos = 0; + let mut shift = 0; + while pos + needle.len() <= haystack.len() { + let mut i = cmp::max(self.critical_pos, shift); + if prefilter && prestate.is_effective() { + match self.freqy.find_candidate(prestate, &haystack[pos..]) { + None => return None, + Some(found) => { + shift = 0; + i = self.critical_pos; + pos += found; + if pos + needle.len() > haystack.len() { + return None; + } + } + } + } + while i < needle.len() && needle[i] == haystack[pos + i] { + i += 1; + } + if i < needle.len() { + pos += i - self.critical_pos + 1; + shift = 0; + } else { + let mut j = self.critical_pos; + while j > shift && needle[j] == haystack[pos + j] { + j -= 1; + } + if j <= shift && needle[shift] == haystack[pos + shift] { + return Some(pos); + } + pos += period; + shift = needle.len() - period; + } + } + None + } + + #[inline(never)] + fn find_large( + &self, + prestate: &mut PrefilterState, + haystack: &[u8], + shift: usize, + ) -> Option { + if prestate.is_effective() { + self.find_large_imp(prestate, true, haystack, shift) + } else { + self.find_large_imp(prestate, false, haystack, shift) + } + } + + #[inline(always)] + fn find_large_imp( + &self, + prestate: &mut PrefilterState, + prefilter: bool, + haystack: &[u8], + shift: usize, + ) -> Option { + let needle = self.needle.as_slice(); + let mut pos = 0; + while pos + needle.len() <= haystack.len() { + let mut i = self.critical_pos; + if prefilter && prestate.is_effective() { + match self.freqy.find_candidate(prestate, &haystack[pos..]) { + None => return None, + Some(found) => { + pos += found; + if pos + needle.len() > haystack.len() { + return None; + } + } + } + } + while i < needle.len() && needle[i] == haystack[pos + i] { + i += 1; + } + if i < needle.len() { + pos += i - self.critical_pos + 1; + } else { + let mut j = self.critical_pos; + while j > 0 && needle[j] == haystack[pos + j] { + j -= 1; + } + if j == 0 && needle[0] == haystack[pos] { + return Some(pos); + } + pos += shift; + } + } + None + } + + #[inline(never)] + fn rfind_small( + &self, + prestate: &mut PrefilterState, + haystack: &[u8], + period: usize, + ) -> Option { + if prestate.is_effective() { + self.rfind_small_imp(prestate, true, haystack, period) + } else { + self.rfind_small_imp(prestate, false, haystack, period) + } + } + + #[inline(always)] + fn rfind_small_imp( + &self, + prestate: &mut PrefilterState, + prefilter: bool, + haystack: &[u8], + period: usize, + ) -> Option { + let needle = &*self.needle; + let nlen = needle.len(); + let mut pos = haystack.len(); + let mut shift = nlen; + while pos >= nlen { + let mut i = cmp::min(self.critical_pos, shift); + if prefilter && prestate.is_effective() { + match self.freqy.rfind_candidate(prestate, &haystack[..pos]) { + None => return None, + Some(found) => { + shift = nlen; + i = self.critical_pos; + pos = found; + if pos < nlen { + return None; + } + } + } + } + while i > 0 && needle[i - 1] == haystack[pos - nlen + i - 1] { + i -= 1; + } + if i > 0 || needle[0] != haystack[pos - nlen] { + pos -= self.critical_pos - i + 1; + shift = nlen; + } else { + let mut j = self.critical_pos; + while j < shift && needle[j] == haystack[pos - nlen + j] { + j += 1; + } + if j == shift { + return Some(pos - nlen); + } + pos -= period; + shift = period; + } + } + None + } + + #[inline(never)] + fn rfind_large( + &self, + prestate: &mut PrefilterState, + haystack: &[u8], + shift: usize, + ) -> Option { + if prestate.is_effective() { + self.rfind_large_imp(prestate, true, haystack, shift) + } else { + self.rfind_large_imp(prestate, false, haystack, shift) + } + } + + #[inline(always)] + fn rfind_large_imp( + &self, + prestate: &mut PrefilterState, + prefilter: bool, + haystack: &[u8], + shift: usize, + ) -> Option { + let needle = &*self.needle; + let nlen = needle.len(); + let mut pos = haystack.len(); + while pos >= nlen { + if prefilter && prestate.is_effective() { + match self.freqy.rfind_candidate(prestate, &haystack[..pos]) { + None => return None, + Some(found) => { + pos = found; + if pos < nlen { + return None; + } + } + } + } + + let mut i = self.critical_pos; + while i > 0 && needle[i - 1] == haystack[pos - nlen + i - 1] { + i -= 1; + } + if i > 0 || needle[0] != haystack[pos - nlen] { + pos -= self.critical_pos - i + 1; + } else { + let mut j = self.critical_pos; + while j < nlen && needle[j] == haystack[pos - nlen + j] { + j += 1; + } + if j == nlen { + return Some(pos - nlen); + } + pos -= shift; + } + } + None + } +} + +/// A representation of the amount we're allowed to shift by during Two-Way +/// search. +/// +/// When computing a critical factorization of the needle, we find the position +/// of the critical factorization by finding the needle's maximal (or minimal) +/// suffix, along with the period of that suffix. It turns out that the period +/// of that suffix is a lower bound on the period of the needle itself. +/// +/// This lower bound is equivalent to the actual period of the needle in +/// some cases. To describe that case, we denote the needle as `x` where +/// `x = uv` and `v` is the lexicographic maximal suffix of `v`. The lower +/// bound given here is always the period of `v`, which is `<= period(x)`. The +/// case where `period(v) == period(x)` occurs when `len(u) < (len(x) / 2)` and +/// where `u` is a suffix of `v[0..period(v)]`. +/// +/// This case is important because the search algorithm for when the +/// periods are equivalent is slightly different than the search algorithm +/// for when the periods are not equivalent. In particular, when they aren't +/// equivalent, we know that the period of the needle is no less than half its +/// length. In this case, we shift by an amount less than or equal to the +/// period of the needle (determined by the maximum length of the components +/// of the critical factorization of `x`, i.e., `max(len(u), len(v))`).. +/// +/// The above two cases are represented by the variants below. Each entails +/// a different instantiation of the Two-Way search algorithm. +/// +/// N.B. If we could find a way to compute the exact period in all cases, +/// then we could collapse this case analysis and simplify the algorithm. The +/// Two-Way paper suggests this is possible, but more reading is required to +/// grok why the authors didn't pursue that path. +#[derive(Clone, Debug)] +enum Shift { + Small { period: usize }, + Large { shift: usize }, +} + +impl Shift { + /// Compute the shift for a given needle in the forward direction. + /// + /// This requires a lower bound on the period and a critical position. + /// These can be computed by extracting both the minimal and maximal + /// lexicographic suffixes, and choosing the right-most starting position. + /// The lower bound on the period is then the period of the chosen suffix. + fn forward( + needle: &[u8], + period_lower_bound: usize, + critical_pos: usize, + ) -> Shift { + let large = cmp::max(critical_pos, needle.len() - critical_pos); + if critical_pos * 2 >= needle.len() { + return Shift::Large { shift: large }; + } + + let (u, v) = needle.split_at(critical_pos); + if !v[..period_lower_bound].ends_with(u) { + return Shift::Large { shift: large }; + } + Shift::Small { period: period_lower_bound } + } + + /// Compute the shift for a given needle in the reverse direction. + /// + /// This requires a lower bound on the period and a critical position. + /// These can be computed by extracting both the minimal and maximal + /// lexicographic suffixes, and choosing the left-most starting position. + /// The lower bound on the period is then the period of the chosen suffix. + fn reverse( + needle: &[u8], + period_lower_bound: usize, + critical_pos: usize, + ) -> Shift { + let large = cmp::max(critical_pos, needle.len() - critical_pos); + if (needle.len() - critical_pos) * 2 >= needle.len() { + return Shift::Large { shift: large }; + } + + let (v, u) = needle.split_at(critical_pos); + if !v[v.len() - period_lower_bound..].starts_with(u) { + return Shift::Large { shift: large }; + } + Shift::Small { period: period_lower_bound } + } +} + +/// A suffix extracted from a needle along with its period. +#[derive(Debug)] +struct Suffix { + /// The starting position of this suffix. + /// + /// If this is a forward suffix, then `&bytes[pos..]` can be used. If this + /// is a reverse suffix, then `&bytes[..pos]` can be used. That is, for + /// forward suffixes, this is an inclusive starting position, where as for + /// reverse suffixes, this is an exclusive ending position. + pos: usize, + /// The period of this suffix. + /// + /// Note that this is NOT necessarily the period of the string from which + /// this suffix comes from. (It is always less than or equal to the period + /// of the original string.) + period: usize, +} + +impl Suffix { + fn forward(needle: &[u8], kind: SuffixKind) -> Suffix { + debug_assert!(!needle.is_empty()); + + // suffix represents our maximal (or minimal) suffix, along with + // its period. + let mut suffix = Suffix { pos: 0, period: 1 }; + // The start of a suffix in `needle` that we are considering as a + // more maximal (or minimal) suffix than what's in `suffix`. + let mut candidate_start = 1; + // The current offset of our suffixes that we're comparing. + // + // When the characters at this offset are the same, then we mush on + // to the next position since no decision is possible. When the + // candidate's character is greater (or lesser) than the corresponding + // character than our current maximal (or minimal) suffix, then the + // current suffix is changed over to the candidate and we restart our + // search. Otherwise, the candidate suffix is no good and we restart + // our search on the next candidate. + // + // The three cases above correspond to the three cases in the loop + // below. + let mut offset = 0; + + while candidate_start + offset < needle.len() { + let current = needle[suffix.pos + offset]; + let candidate = needle[candidate_start + offset]; + match kind.cmp(current, candidate) { + SuffixOrdering::Accept => { + suffix = Suffix { pos: candidate_start, period: 1 }; + candidate_start += 1; + offset = 0; + } + SuffixOrdering::Skip => { + candidate_start += offset + 1; + offset = 0; + suffix.period = candidate_start - suffix.pos; + } + SuffixOrdering::Push => { + if offset + 1 == suffix.period { + candidate_start += suffix.period; + offset = 0; + } else { + offset += 1; + } + } + } + } + suffix + } + + fn reverse(needle: &[u8], kind: SuffixKind) -> Suffix { + debug_assert!(!needle.is_empty()); + + // See the comments in `forward` for how this works. + let mut suffix = Suffix { pos: needle.len(), period: 1 }; + if needle.len() == 1 { + return suffix; + } + let mut candidate_start = needle.len() - 1; + let mut offset = 0; + + while offset < candidate_start { + let current = needle[suffix.pos - offset - 1]; + let candidate = needle[candidate_start - offset - 1]; + match kind.cmp(current, candidate) { + SuffixOrdering::Accept => { + suffix = Suffix { pos: candidate_start, period: 1 }; + candidate_start -= 1; + offset = 0; + } + SuffixOrdering::Skip => { + candidate_start -= offset + 1; + offset = 0; + suffix.period = suffix.pos - candidate_start; + } + SuffixOrdering::Push => { + if offset + 1 == suffix.period { + candidate_start -= suffix.period; + offset = 0; + } else { + offset += 1; + } + } + } + } + suffix + } +} + +/// The kind of suffix to extract. +#[derive(Clone, Copy, Debug)] +enum SuffixKind { + /// Extract the smallest lexicographic suffix from a string. + /// + /// Technically, this doesn't actually pick the smallest lexicographic + /// suffix. e.g., Given the choice between `a` and `aa`, this will choose + /// the latter over the former, even though `a < aa`. The reasoning for + /// this isn't clear from the paper, but it still smells like a minimal + /// suffix. + Minimal, + /// Extract the largest lexicographic suffix from a string. + /// + /// Unlike `Minimal`, this really does pick the maximum suffix. e.g., Given + /// the choice between `z` and `zz`, this will choose the latter over the + /// former. + Maximal, +} + +/// The result of comparing corresponding bytes between two suffixes. +#[derive(Clone, Copy, Debug)] +enum SuffixOrdering { + /// This occurs when the given candidate byte indicates that the candidate + /// suffix is better than the current maximal (or minimal) suffix. That is, + /// the current candidate suffix should supplant the current maximal (or + /// minimal) suffix. + Accept, + /// This occurs when the given candidate byte excludes the candidate suffix + /// from being better than the current maximal (or minimal) suffix. That + /// is, the current candidate suffix should be dropped and the next one + /// should be considered. + Skip, + /// This occurs when no decision to accept or skip the candidate suffix + /// can be made, e.g., when corresponding bytes are equivalent. In this + /// case, the next corresponding bytes should be compared. + Push, +} + +impl SuffixKind { + /// Returns true if and only if the given candidate byte indicates that + /// it should replace the current suffix as the maximal (or minimal) + /// suffix. + fn cmp(self, current: u8, candidate: u8) -> SuffixOrdering { + use self::SuffixOrdering::*; + + match self { + SuffixKind::Minimal if candidate < current => Accept, + SuffixKind::Minimal if candidate > current => Skip, + SuffixKind::Minimal => Push, + SuffixKind::Maximal if candidate > current => Accept, + SuffixKind::Maximal if candidate < current => Skip, + SuffixKind::Maximal => Push, + } + } +} + +// N.B. There are more holistic tests in src/search/tests.rs. +#[cfg(test)] +mod tests { + use super::*; + use ext_slice::B; + + /// Convenience wrapper for computing the suffix as a byte string. + fn get_suffix_forward(needle: &[u8], kind: SuffixKind) -> (&[u8], usize) { + let s = Suffix::forward(needle, kind); + (&needle[s.pos..], s.period) + } + + /// Convenience wrapper for computing the reverse suffix as a byte string. + fn get_suffix_reverse(needle: &[u8], kind: SuffixKind) -> (&[u8], usize) { + let s = Suffix::reverse(needle, kind); + (&needle[..s.pos], s.period) + } + + /// Return all of the non-empty suffixes in the given byte string. + fn suffixes(bytes: &[u8]) -> Vec<&[u8]> { + (0..bytes.len()).map(|i| &bytes[i..]).collect() + } + + /// Return the lexicographically maximal suffix of the given byte string. + fn naive_maximal_suffix_forward(needle: &[u8]) -> &[u8] { + let mut sufs = suffixes(needle); + sufs.sort(); + sufs.pop().unwrap() + } + + /// Return the lexicographically maximal suffix of the reverse of the given + /// byte string. + fn naive_maximal_suffix_reverse(needle: &[u8]) -> Vec { + let mut reversed = needle.to_vec(); + reversed.reverse(); + let mut got = naive_maximal_suffix_forward(&reversed).to_vec(); + got.reverse(); + got + } + + #[test] + fn suffix_forward() { + macro_rules! assert_suffix_min { + ($given:expr, $expected:expr, $period:expr) => { + let (got_suffix, got_period) = + get_suffix_forward($given.as_bytes(), SuffixKind::Minimal); + assert_eq!((B($expected), $period), (got_suffix, got_period)); + }; + } + + macro_rules! assert_suffix_max { + ($given:expr, $expected:expr, $period:expr) => { + let (got_suffix, got_period) = + get_suffix_forward($given.as_bytes(), SuffixKind::Maximal); + assert_eq!((B($expected), $period), (got_suffix, got_period)); + }; + } + + assert_suffix_min!("a", "a", 1); + assert_suffix_max!("a", "a", 1); + + assert_suffix_min!("ab", "ab", 2); + assert_suffix_max!("ab", "b", 1); + + assert_suffix_min!("ba", "a", 1); + assert_suffix_max!("ba", "ba", 2); + + assert_suffix_min!("abc", "abc", 3); + assert_suffix_max!("abc", "c", 1); + + assert_suffix_min!("acb", "acb", 3); + assert_suffix_max!("acb", "cb", 2); + + assert_suffix_min!("cba", "a", 1); + assert_suffix_max!("cba", "cba", 3); + + assert_suffix_min!("abcabc", "abcabc", 3); + assert_suffix_max!("abcabc", "cabc", 3); + + assert_suffix_min!("abcabcabc", "abcabcabc", 3); + assert_suffix_max!("abcabcabc", "cabcabc", 3); + + assert_suffix_min!("abczz", "abczz", 5); + assert_suffix_max!("abczz", "zz", 1); + + assert_suffix_min!("zzabc", "abc", 3); + assert_suffix_max!("zzabc", "zzabc", 5); + + assert_suffix_min!("aaa", "aaa", 1); + assert_suffix_max!("aaa", "aaa", 1); + + assert_suffix_min!("foobar", "ar", 2); + assert_suffix_max!("foobar", "r", 1); + } + + #[test] + fn suffix_reverse() { + macro_rules! assert_suffix_min { + ($given:expr, $expected:expr, $period:expr) => { + let (got_suffix, got_period) = + get_suffix_reverse($given.as_bytes(), SuffixKind::Minimal); + assert_eq!((B($expected), $period), (got_suffix, got_period)); + }; + } + + macro_rules! assert_suffix_max { + ($given:expr, $expected:expr, $period:expr) => { + let (got_suffix, got_period) = + get_suffix_reverse($given.as_bytes(), SuffixKind::Maximal); + assert_eq!((B($expected), $period), (got_suffix, got_period)); + }; + } + + assert_suffix_min!("a", "a", 1); + assert_suffix_max!("a", "a", 1); + + assert_suffix_min!("ab", "a", 1); + assert_suffix_max!("ab", "ab", 2); + + assert_suffix_min!("ba", "ba", 2); + assert_suffix_max!("ba", "b", 1); + + assert_suffix_min!("abc", "a", 1); + assert_suffix_max!("abc", "abc", 3); + + assert_suffix_min!("acb", "a", 1); + assert_suffix_max!("acb", "ac", 2); + + assert_suffix_min!("cba", "cba", 3); + assert_suffix_max!("cba", "c", 1); + + assert_suffix_min!("abcabc", "abca", 3); + assert_suffix_max!("abcabc", "abcabc", 3); + + assert_suffix_min!("abcabcabc", "abcabca", 3); + assert_suffix_max!("abcabcabc", "abcabcabc", 3); + + assert_suffix_min!("abczz", "a", 1); + assert_suffix_max!("abczz", "abczz", 5); + + assert_suffix_min!("zzabc", "zza", 3); + assert_suffix_max!("zzabc", "zz", 1); + + assert_suffix_min!("aaa", "aaa", 1); + assert_suffix_max!("aaa", "aaa", 1); + } + + quickcheck! { + fn qc_suffix_forward_maximal(bytes: Vec) -> bool { + if bytes.is_empty() { + return true; + } + + let (got, _) = get_suffix_forward(&bytes, SuffixKind::Maximal); + let expected = naive_maximal_suffix_forward(&bytes); + got == expected + } + + fn qc_suffix_reverse_maximal(bytes: Vec) -> bool { + if bytes.is_empty() { + return true; + } + + let (got, _) = get_suffix_reverse(&bytes, SuffixKind::Maximal); + let expected = naive_maximal_suffix_reverse(&bytes); + expected == got + } + } +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/tests.rs b/third_party/cargo/vendor/bstr-0.2.15/src/tests.rs new file mode 100644 index 0000000..f4179fd --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/tests.rs @@ -0,0 +1,32 @@ +/// A sequence of tests for checking whether lossy decoding uses the maximal +/// subpart strategy correctly. Namely, if a sequence of otherwise invalid +/// UTF-8 bytes is a valid prefix of a valid UTF-8 sequence, then the entire +/// prefix is replaced by a single replacement codepoint. In all other cases, +/// each invalid byte is replaced by a single replacement codepoint. +/// +/// The first element in each tuple is the expected result of lossy decoding, +/// while the second element is the input given. +pub const LOSSY_TESTS: &[(&str, &[u8])] = &[ + ("a", b"a"), + ("\u{FFFD}", b"\xFF"), + ("\u{FFFD}\u{FFFD}", b"\xFF\xFF"), + ("β\u{FFFD}", b"\xCE\xB2\xFF"), + ("☃\u{FFFD}", b"\xE2\x98\x83\xFF"), + ("𝝱\u{FFFD}", b"\xF0\x9D\x9D\xB1\xFF"), + ("\u{FFFD}\u{FFFD}", b"\xCE\xF0"), + ("\u{FFFD}\u{FFFD}", b"\xCE\xFF"), + ("\u{FFFD}\u{FFFD}", b"\xE2\x98\xF0"), + ("\u{FFFD}\u{FFFD}", b"\xE2\x98\xFF"), + ("\u{FFFD}", b"\xF0\x9D\x9D"), + ("\u{FFFD}\u{FFFD}", b"\xF0\x9D\x9D\xF0"), + ("\u{FFFD}\u{FFFD}", b"\xF0\x9D\x9D\xFF"), + ("\u{FFFD}", b"\xCE"), + ("a\u{FFFD}", b"a\xCE"), + ("\u{FFFD}", b"\xE2\x98"), + ("a\u{FFFD}", b"a\xE2\x98"), + ("\u{FFFD}", b"\xF0\x9D\x9C"), + ("a\u{FFFD}", b"a\xF0\x9D\x9C"), + ("a\u{FFFD}\u{FFFD}\u{FFFD}z", b"a\xED\xA0\x80z"), + ("☃βツ\u{FFFD}", b"\xe2\x98\x83\xce\xb2\xe3\x83\x84\xFF"), + ("a\u{FFFD}\u{FFFD}\u{FFFD}b", b"\x61\xF1\x80\x80\xE1\x80\xC2\x62"), +]; diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/data/GraphemeBreakTest.txt b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/data/GraphemeBreakTest.txt new file mode 100644 index 0000000..fb4fec9 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/data/GraphemeBreakTest.txt @@ -0,0 +1,630 @@ +# GraphemeBreakTest-12.1.0.txt +# Date: 2019-03-10, 10:53:12 GMT +# © 2019 Unicode®, Inc. +# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. +# For terms of use, see http://www.unicode.org/terms_of_use.html +# +# Unicode Character Database +# For documentation, see http://www.unicode.org/reports/tr44/ +# +# Default Grapheme_Cluster_Break Test +# +# Format: +# (# )? +# contains hex Unicode code points, with +# ÷ wherever there is a break opportunity, and +# × wherever there is not. +# the format can change, but currently it shows: +# - the sample character name +# - (x) the Grapheme_Cluster_Break property value for the sample character +# - [x] the rule that determines whether there is a break or not, +# as listed in the Rules section of GraphemeBreakTest.html +# +# These samples may be extended or changed in the future. +# +÷ 0020 ÷ 0020 ÷ # ÷ [0.2] SPACE (Other) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 0020 × 0308 ÷ 0020 ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 0020 ÷ 000D ÷ # ÷ [0.2] SPACE (Other) ÷ [5.0] (CR) ÷ [0.3] +÷ 0020 × 0308 ÷ 000D ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (CR) ÷ [0.3] +÷ 0020 ÷ 000A ÷ # ÷ [0.2] SPACE (Other) ÷ [5.0] (LF) ÷ [0.3] +÷ 0020 × 0308 ÷ 000A ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (LF) ÷ [0.3] +÷ 0020 ÷ 0001 ÷ # ÷ [0.2] SPACE (Other) ÷ [5.0] (Control) ÷ [0.3] +÷ 0020 × 0308 ÷ 0001 ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (Control) ÷ [0.3] +÷ 0020 × 034F ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 0020 × 0308 × 034F ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 0020 ÷ 1F1E6 ÷ # ÷ [0.2] SPACE (Other) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0020 × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0020 ÷ 0600 ÷ # ÷ [0.2] SPACE (Other) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 0020 × 0308 ÷ 0600 ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 0020 × 0903 ÷ # ÷ [0.2] SPACE (Other) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 0020 × 0308 × 0903 ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 0020 ÷ 1100 ÷ # ÷ [0.2] SPACE (Other) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 0020 × 0308 ÷ 1100 ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 0020 ÷ 1160 ÷ # ÷ [0.2] SPACE (Other) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 0020 × 0308 ÷ 1160 ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 0020 ÷ 11A8 ÷ # ÷ [0.2] SPACE (Other) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 0020 × 0308 ÷ 11A8 ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 0020 ÷ AC00 ÷ # ÷ [0.2] SPACE (Other) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 0020 × 0308 ÷ AC00 ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 0020 ÷ AC01 ÷ # ÷ [0.2] SPACE (Other) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 0020 × 0308 ÷ AC01 ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 0020 ÷ 231A ÷ # ÷ [0.2] SPACE (Other) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0020 × 0308 ÷ 231A ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0020 × 0300 ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 0020 × 0308 × 0300 ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 0020 × 200D ÷ # ÷ [0.2] SPACE (Other) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 0020 × 0308 × 200D ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 0020 ÷ 0378 ÷ # ÷ [0.2] SPACE (Other) ÷ [999.0] (Other) ÷ [0.3] +÷ 0020 × 0308 ÷ 0378 ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] (Other) ÷ [0.3] +÷ 000D ÷ 0020 ÷ # ÷ [0.2] (CR) ÷ [4.0] SPACE (Other) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 0020 ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 000D ÷ 000D ÷ # ÷ [0.2] (CR) ÷ [4.0] (CR) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 000D ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (CR) ÷ [0.3] +÷ 000D × 000A ÷ # ÷ [0.2] (CR) × [3.0] (LF) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 000A ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (LF) ÷ [0.3] +÷ 000D ÷ 0001 ÷ # ÷ [0.2] (CR) ÷ [4.0] (Control) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 0001 ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (Control) ÷ [0.3] +÷ 000D ÷ 034F ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 000D ÷ 0308 × 034F ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 000D ÷ 1F1E6 ÷ # ÷ [0.2] (CR) ÷ [4.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 1F1E6 ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 000D ÷ 0600 ÷ # ÷ [0.2] (CR) ÷ [4.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 0600 ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 000D ÷ 0903 ÷ # ÷ [0.2] (CR) ÷ [4.0] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 000D ÷ 0308 × 0903 ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 000D ÷ 1100 ÷ # ÷ [0.2] (CR) ÷ [4.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 1100 ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 000D ÷ 1160 ÷ # ÷ [0.2] (CR) ÷ [4.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 1160 ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 000D ÷ 11A8 ÷ # ÷ [0.2] (CR) ÷ [4.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 11A8 ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 000D ÷ AC00 ÷ # ÷ [0.2] (CR) ÷ [4.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 000D ÷ 0308 ÷ AC00 ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 000D ÷ AC01 ÷ # ÷ [0.2] (CR) ÷ [4.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 000D ÷ 0308 ÷ AC01 ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 000D ÷ 231A ÷ # ÷ [0.2] (CR) ÷ [4.0] WATCH (ExtPict) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 231A ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 000D ÷ 0300 ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 000D ÷ 0308 × 0300 ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 000D ÷ 200D ÷ # ÷ [0.2] (CR) ÷ [4.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 000D ÷ 0308 × 200D ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 000D ÷ 0378 ÷ # ÷ [0.2] (CR) ÷ [4.0] (Other) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 0378 ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] (Other) ÷ [0.3] +÷ 000A ÷ 0020 ÷ # ÷ [0.2] (LF) ÷ [4.0] SPACE (Other) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 0020 ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 000A ÷ 000D ÷ # ÷ [0.2] (LF) ÷ [4.0] (CR) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 000D ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (CR) ÷ [0.3] +÷ 000A ÷ 000A ÷ # ÷ [0.2] (LF) ÷ [4.0] (LF) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 000A ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (LF) ÷ [0.3] +÷ 000A ÷ 0001 ÷ # ÷ [0.2] (LF) ÷ [4.0] (Control) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 0001 ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (Control) ÷ [0.3] +÷ 000A ÷ 034F ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 000A ÷ 0308 × 034F ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 000A ÷ 1F1E6 ÷ # ÷ [0.2] (LF) ÷ [4.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 1F1E6 ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 000A ÷ 0600 ÷ # ÷ [0.2] (LF) ÷ [4.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 0600 ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 000A ÷ 0903 ÷ # ÷ [0.2] (LF) ÷ [4.0] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 000A ÷ 0308 × 0903 ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 000A ÷ 1100 ÷ # ÷ [0.2] (LF) ÷ [4.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 1100 ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 000A ÷ 1160 ÷ # ÷ [0.2] (LF) ÷ [4.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 1160 ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 000A ÷ 11A8 ÷ # ÷ [0.2] (LF) ÷ [4.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 11A8 ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 000A ÷ AC00 ÷ # ÷ [0.2] (LF) ÷ [4.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 000A ÷ 0308 ÷ AC00 ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 000A ÷ AC01 ÷ # ÷ [0.2] (LF) ÷ [4.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 000A ÷ 0308 ÷ AC01 ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 000A ÷ 231A ÷ # ÷ [0.2] (LF) ÷ [4.0] WATCH (ExtPict) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 231A ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 000A ÷ 0300 ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 000A ÷ 0308 × 0300 ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 000A ÷ 200D ÷ # ÷ [0.2] (LF) ÷ [4.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 000A ÷ 0308 × 200D ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 000A ÷ 0378 ÷ # ÷ [0.2] (LF) ÷ [4.0] (Other) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 0378 ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] (Other) ÷ [0.3] +÷ 0001 ÷ 0020 ÷ # ÷ [0.2] (Control) ÷ [4.0] SPACE (Other) ÷ [0.3] +÷ 0001 ÷ 0308 ÷ 0020 ÷ # ÷ [0.2] (Control) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 0001 ÷ 000D ÷ # ÷ [0.2] (Control) ÷ [4.0] (CR) ÷ [0.3] +÷ 0001 ÷ 0308 ÷ 000D ÷ # ÷ [0.2] (Control) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (CR) ÷ [0.3] +÷ 0001 ÷ 000A ÷ # ÷ [0.2] (Control) ÷ [4.0] (LF) ÷ [0.3] +÷ 0001 ÷ 0308 ÷ 000A ÷ # ÷ [0.2] (Control) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (LF) ÷ [0.3] +÷ 0001 ÷ 0001 ÷ # ÷ [0.2] (Control) ÷ [4.0] (Control) ÷ [0.3] +÷ 0001 ÷ 0308 ÷ 0001 ÷ # ÷ [0.2] (Control) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (Control) ÷ [0.3] +÷ 0001 ÷ 034F ÷ # ÷ [0.2] (Control) ÷ [4.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 0001 ÷ 0308 × 034F ÷ # ÷ [0.2] (Control) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 0001 ÷ 1F1E6 ÷ # ÷ [0.2] (Control) ÷ [4.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0001 ÷ 0308 ÷ 1F1E6 ÷ # ÷ [0.2] (Control) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0001 ÷ 0600 ÷ # ÷ [0.2] (Control) ÷ [4.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 0001 ÷ 0308 ÷ 0600 ÷ # ÷ [0.2] (Control) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 0001 ÷ 0903 ÷ # ÷ [0.2] (Control) ÷ [4.0] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 0001 ÷ 0308 × 0903 ÷ # ÷ [0.2] (Control) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 0001 ÷ 1100 ÷ # ÷ [0.2] (Control) ÷ [4.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 0001 ÷ 0308 ÷ 1100 ÷ # ÷ [0.2] (Control) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 0001 ÷ 1160 ÷ # ÷ [0.2] (Control) ÷ [4.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 0001 ÷ 0308 ÷ 1160 ÷ # ÷ [0.2] (Control) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 0001 ÷ 11A8 ÷ # ÷ [0.2] (Control) ÷ [4.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 0001 ÷ 0308 ÷ 11A8 ÷ # ÷ [0.2] (Control) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 0001 ÷ AC00 ÷ # ÷ [0.2] (Control) ÷ [4.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 0001 ÷ 0308 ÷ AC00 ÷ # ÷ [0.2] (Control) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 0001 ÷ AC01 ÷ # ÷ [0.2] (Control) ÷ [4.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 0001 ÷ 0308 ÷ AC01 ÷ # ÷ [0.2] (Control) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 0001 ÷ 231A ÷ # ÷ [0.2] (Control) ÷ [4.0] WATCH (ExtPict) ÷ [0.3] +÷ 0001 ÷ 0308 ÷ 231A ÷ # ÷ [0.2] (Control) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0001 ÷ 0300 ÷ # ÷ [0.2] (Control) ÷ [4.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 0001 ÷ 0308 × 0300 ÷ # ÷ [0.2] (Control) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 0001 ÷ 200D ÷ # ÷ [0.2] (Control) ÷ [4.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 0001 ÷ 0308 × 200D ÷ # ÷ [0.2] (Control) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 0001 ÷ 0378 ÷ # ÷ [0.2] (Control) ÷ [4.0] (Other) ÷ [0.3] +÷ 0001 ÷ 0308 ÷ 0378 ÷ # ÷ [0.2] (Control) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] (Other) ÷ [0.3] +÷ 034F ÷ 0020 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 034F × 0308 ÷ 0020 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 034F ÷ 000D ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) ÷ [5.0] (CR) ÷ [0.3] +÷ 034F × 0308 ÷ 000D ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (CR) ÷ [0.3] +÷ 034F ÷ 000A ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) ÷ [5.0] (LF) ÷ [0.3] +÷ 034F × 0308 ÷ 000A ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (LF) ÷ [0.3] +÷ 034F ÷ 0001 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) ÷ [5.0] (Control) ÷ [0.3] +÷ 034F × 0308 ÷ 0001 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (Control) ÷ [0.3] +÷ 034F × 034F ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 034F × 0308 × 034F ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 034F ÷ 1F1E6 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 034F × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 034F ÷ 0600 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 034F × 0308 ÷ 0600 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 034F × 0903 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 034F × 0308 × 0903 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 034F ÷ 1100 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 034F × 0308 ÷ 1100 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 034F ÷ 1160 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 034F × 0308 ÷ 1160 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 034F ÷ 11A8 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 034F × 0308 ÷ 11A8 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 034F ÷ AC00 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 034F × 0308 ÷ AC00 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 034F ÷ AC01 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 034F × 0308 ÷ AC01 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 034F ÷ 231A ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 034F × 0308 ÷ 231A ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 034F × 0300 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 034F × 0308 × 0300 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 034F × 200D ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 034F × 0308 × 200D ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 034F ÷ 0378 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) ÷ [999.0] (Other) ÷ [0.3] +÷ 034F × 0308 ÷ 0378 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] (Other) ÷ [0.3] +÷ 1F1E6 ÷ 0020 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 0020 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 1F1E6 ÷ 000D ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [5.0] (CR) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 000D ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (CR) ÷ [0.3] +÷ 1F1E6 ÷ 000A ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [5.0] (LF) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 000A ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (LF) ÷ [0.3] +÷ 1F1E6 ÷ 0001 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [5.0] (Control) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 0001 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (Control) ÷ [0.3] +÷ 1F1E6 × 034F ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 1F1E6 × 0308 × 034F ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 1F1E6 × 1F1E6 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [12.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 1F1E6 ÷ 0600 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 0600 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 1F1E6 × 0903 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 1F1E6 × 0308 × 0903 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 1F1E6 ÷ 1100 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 1100 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 1F1E6 ÷ 1160 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 1160 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 1F1E6 ÷ 11A8 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 11A8 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 1F1E6 ÷ AC00 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ AC00 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 1F1E6 ÷ AC01 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ AC01 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 1F1E6 ÷ 231A ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 231A ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 1F1E6 × 0300 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 1F1E6 × 0308 × 0300 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 1F1E6 × 200D ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 1F1E6 × 0308 × 200D ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 1F1E6 ÷ 0378 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] (Other) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 0378 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] (Other) ÷ [0.3] +÷ 0600 × 0020 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.2] SPACE (Other) ÷ [0.3] +÷ 0600 × 0308 ÷ 0020 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 0600 ÷ 000D ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) ÷ [5.0] (CR) ÷ [0.3] +÷ 0600 × 0308 ÷ 000D ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (CR) ÷ [0.3] +÷ 0600 ÷ 000A ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) ÷ [5.0] (LF) ÷ [0.3] +÷ 0600 × 0308 ÷ 000A ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (LF) ÷ [0.3] +÷ 0600 ÷ 0001 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) ÷ [5.0] (Control) ÷ [0.3] +÷ 0600 × 0308 ÷ 0001 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (Control) ÷ [0.3] +÷ 0600 × 034F ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 0600 × 0308 × 034F ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 0600 × 1F1E6 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0600 × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0600 × 0600 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.2] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 0600 × 0308 ÷ 0600 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 0600 × 0903 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 0600 × 0308 × 0903 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 0600 × 1100 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.2] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 0600 × 0308 ÷ 1100 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 0600 × 1160 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.2] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 0600 × 0308 ÷ 1160 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 0600 × 11A8 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.2] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 0600 × 0308 ÷ 11A8 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 0600 × AC00 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.2] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 0600 × 0308 ÷ AC00 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 0600 × AC01 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.2] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 0600 × 0308 ÷ AC01 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 0600 × 231A ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.2] WATCH (ExtPict) ÷ [0.3] +÷ 0600 × 0308 ÷ 231A ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0600 × 0300 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 0600 × 0308 × 0300 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 0600 × 200D ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 0600 × 0308 × 200D ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 0600 × 0378 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.2] (Other) ÷ [0.3] +÷ 0600 × 0308 ÷ 0378 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] (Other) ÷ [0.3] +÷ 0903 ÷ 0020 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 0903 × 0308 ÷ 0020 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 0903 ÷ 000D ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [5.0] (CR) ÷ [0.3] +÷ 0903 × 0308 ÷ 000D ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (CR) ÷ [0.3] +÷ 0903 ÷ 000A ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [5.0] (LF) ÷ [0.3] +÷ 0903 × 0308 ÷ 000A ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (LF) ÷ [0.3] +÷ 0903 ÷ 0001 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [5.0] (Control) ÷ [0.3] +÷ 0903 × 0308 ÷ 0001 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (Control) ÷ [0.3] +÷ 0903 × 034F ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 0903 × 0308 × 034F ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 0903 ÷ 1F1E6 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0903 × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0903 ÷ 0600 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 0903 × 0308 ÷ 0600 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 0903 × 0903 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 0903 × 0308 × 0903 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 0903 ÷ 1100 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 0903 × 0308 ÷ 1100 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 0903 ÷ 1160 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 0903 × 0308 ÷ 1160 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 0903 ÷ 11A8 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 0903 × 0308 ÷ 11A8 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 0903 ÷ AC00 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 0903 × 0308 ÷ AC00 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 0903 ÷ AC01 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 0903 × 0308 ÷ AC01 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 0903 ÷ 231A ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0903 × 0308 ÷ 231A ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0903 × 0300 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 0903 × 0308 × 0300 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 0903 × 200D ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 0903 × 0308 × 200D ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 0903 ÷ 0378 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [999.0] (Other) ÷ [0.3] +÷ 0903 × 0308 ÷ 0378 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] (Other) ÷ [0.3] +÷ 1100 ÷ 0020 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 1100 × 0308 ÷ 0020 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 1100 ÷ 000D ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) ÷ [5.0] (CR) ÷ [0.3] +÷ 1100 × 0308 ÷ 000D ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (CR) ÷ [0.3] +÷ 1100 ÷ 000A ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) ÷ [5.0] (LF) ÷ [0.3] +÷ 1100 × 0308 ÷ 000A ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (LF) ÷ [0.3] +÷ 1100 ÷ 0001 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) ÷ [5.0] (Control) ÷ [0.3] +÷ 1100 × 0308 ÷ 0001 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (Control) ÷ [0.3] +÷ 1100 × 034F ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 1100 × 0308 × 034F ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 1100 ÷ 1F1E6 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 1100 × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 1100 ÷ 0600 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 1100 × 0308 ÷ 0600 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 1100 × 0903 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 1100 × 0308 × 0903 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 1100 × 1100 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [6.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 1100 × 0308 ÷ 1100 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 1100 × 1160 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [6.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 1100 × 0308 ÷ 1160 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 1100 ÷ 11A8 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 1100 × 0308 ÷ 11A8 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 1100 × AC00 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [6.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 1100 × 0308 ÷ AC00 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 1100 × AC01 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [6.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 1100 × 0308 ÷ AC01 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 1100 ÷ 231A ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 1100 × 0308 ÷ 231A ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 1100 × 0300 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 1100 × 0308 × 0300 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 1100 × 200D ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 1100 × 0308 × 200D ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 1100 ÷ 0378 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) ÷ [999.0] (Other) ÷ [0.3] +÷ 1100 × 0308 ÷ 0378 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] (Other) ÷ [0.3] +÷ 1160 ÷ 0020 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 1160 × 0308 ÷ 0020 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 1160 ÷ 000D ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) ÷ [5.0] (CR) ÷ [0.3] +÷ 1160 × 0308 ÷ 000D ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (CR) ÷ [0.3] +÷ 1160 ÷ 000A ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) ÷ [5.0] (LF) ÷ [0.3] +÷ 1160 × 0308 ÷ 000A ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (LF) ÷ [0.3] +÷ 1160 ÷ 0001 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) ÷ [5.0] (Control) ÷ [0.3] +÷ 1160 × 0308 ÷ 0001 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (Control) ÷ [0.3] +÷ 1160 × 034F ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 1160 × 0308 × 034F ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 1160 ÷ 1F1E6 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 1160 × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 1160 ÷ 0600 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 1160 × 0308 ÷ 0600 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 1160 × 0903 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 1160 × 0308 × 0903 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 1160 ÷ 1100 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 1160 × 0308 ÷ 1100 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 1160 × 1160 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [7.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 1160 × 0308 ÷ 1160 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 1160 × 11A8 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [7.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 1160 × 0308 ÷ 11A8 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 1160 ÷ AC00 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 1160 × 0308 ÷ AC00 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 1160 ÷ AC01 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 1160 × 0308 ÷ AC01 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 1160 ÷ 231A ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 1160 × 0308 ÷ 231A ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 1160 × 0300 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 1160 × 0308 × 0300 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 1160 × 200D ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 1160 × 0308 × 200D ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 1160 ÷ 0378 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) ÷ [999.0] (Other) ÷ [0.3] +÷ 1160 × 0308 ÷ 0378 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] (Other) ÷ [0.3] +÷ 11A8 ÷ 0020 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 11A8 × 0308 ÷ 0020 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 11A8 ÷ 000D ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) ÷ [5.0] (CR) ÷ [0.3] +÷ 11A8 × 0308 ÷ 000D ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (CR) ÷ [0.3] +÷ 11A8 ÷ 000A ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) ÷ [5.0] (LF) ÷ [0.3] +÷ 11A8 × 0308 ÷ 000A ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (LF) ÷ [0.3] +÷ 11A8 ÷ 0001 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) ÷ [5.0] (Control) ÷ [0.3] +÷ 11A8 × 0308 ÷ 0001 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (Control) ÷ [0.3] +÷ 11A8 × 034F ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 11A8 × 0308 × 034F ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 11A8 ÷ 1F1E6 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 11A8 × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 11A8 ÷ 0600 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 11A8 × 0308 ÷ 0600 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 11A8 × 0903 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 11A8 × 0308 × 0903 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 11A8 ÷ 1100 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 11A8 × 0308 ÷ 1100 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 11A8 ÷ 1160 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 11A8 × 0308 ÷ 1160 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 11A8 × 11A8 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [8.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 11A8 × 0308 ÷ 11A8 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 11A8 ÷ AC00 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 11A8 × 0308 ÷ AC00 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 11A8 ÷ AC01 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 11A8 × 0308 ÷ AC01 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 11A8 ÷ 231A ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 11A8 × 0308 ÷ 231A ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 11A8 × 0300 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 11A8 × 0308 × 0300 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 11A8 × 200D ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 11A8 × 0308 × 200D ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 11A8 ÷ 0378 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) ÷ [999.0] (Other) ÷ [0.3] +÷ 11A8 × 0308 ÷ 0378 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] (Other) ÷ [0.3] +÷ AC00 ÷ 0020 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ AC00 × 0308 ÷ 0020 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ AC00 ÷ 000D ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) ÷ [5.0] (CR) ÷ [0.3] +÷ AC00 × 0308 ÷ 000D ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (CR) ÷ [0.3] +÷ AC00 ÷ 000A ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) ÷ [5.0] (LF) ÷ [0.3] +÷ AC00 × 0308 ÷ 000A ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (LF) ÷ [0.3] +÷ AC00 ÷ 0001 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) ÷ [5.0] (Control) ÷ [0.3] +÷ AC00 × 0308 ÷ 0001 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (Control) ÷ [0.3] +÷ AC00 × 034F ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ AC00 × 0308 × 034F ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ AC00 ÷ 1F1E6 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ AC00 × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ AC00 ÷ 0600 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ AC00 × 0308 ÷ 0600 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ AC00 × 0903 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ AC00 × 0308 × 0903 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ AC00 ÷ 1100 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ AC00 × 0308 ÷ 1100 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ AC00 × 1160 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [7.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ AC00 × 0308 ÷ 1160 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ AC00 × 11A8 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [7.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ AC00 × 0308 ÷ 11A8 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ AC00 ÷ AC00 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ AC00 × 0308 ÷ AC00 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ AC00 ÷ AC01 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ AC00 × 0308 ÷ AC01 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ AC00 ÷ 231A ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ AC00 × 0308 ÷ 231A ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ AC00 × 0300 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ AC00 × 0308 × 0300 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ AC00 × 200D ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ AC00 × 0308 × 200D ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ AC00 ÷ 0378 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) ÷ [999.0] (Other) ÷ [0.3] +÷ AC00 × 0308 ÷ 0378 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] (Other) ÷ [0.3] +÷ AC01 ÷ 0020 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ AC01 × 0308 ÷ 0020 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ AC01 ÷ 000D ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) ÷ [5.0] (CR) ÷ [0.3] +÷ AC01 × 0308 ÷ 000D ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (CR) ÷ [0.3] +÷ AC01 ÷ 000A ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) ÷ [5.0] (LF) ÷ [0.3] +÷ AC01 × 0308 ÷ 000A ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (LF) ÷ [0.3] +÷ AC01 ÷ 0001 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) ÷ [5.0] (Control) ÷ [0.3] +÷ AC01 × 0308 ÷ 0001 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (Control) ÷ [0.3] +÷ AC01 × 034F ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ AC01 × 0308 × 034F ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ AC01 ÷ 1F1E6 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ AC01 × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ AC01 ÷ 0600 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ AC01 × 0308 ÷ 0600 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ AC01 × 0903 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ AC01 × 0308 × 0903 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ AC01 ÷ 1100 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ AC01 × 0308 ÷ 1100 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ AC01 ÷ 1160 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ AC01 × 0308 ÷ 1160 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ AC01 × 11A8 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [8.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ AC01 × 0308 ÷ 11A8 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ AC01 ÷ AC00 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ AC01 × 0308 ÷ AC00 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ AC01 ÷ AC01 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ AC01 × 0308 ÷ AC01 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ AC01 ÷ 231A ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ AC01 × 0308 ÷ 231A ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ AC01 × 0300 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ AC01 × 0308 × 0300 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ AC01 × 200D ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ AC01 × 0308 × 200D ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ AC01 ÷ 0378 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) ÷ [999.0] (Other) ÷ [0.3] +÷ AC01 × 0308 ÷ 0378 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] (Other) ÷ [0.3] +÷ 231A ÷ 0020 ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 231A × 0308 ÷ 0020 ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 231A ÷ 000D ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [5.0] (CR) ÷ [0.3] +÷ 231A × 0308 ÷ 000D ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (CR) ÷ [0.3] +÷ 231A ÷ 000A ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [5.0] (LF) ÷ [0.3] +÷ 231A × 0308 ÷ 000A ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (LF) ÷ [0.3] +÷ 231A ÷ 0001 ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [5.0] (Control) ÷ [0.3] +÷ 231A × 0308 ÷ 0001 ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (Control) ÷ [0.3] +÷ 231A × 034F ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 231A × 0308 × 034F ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 231A ÷ 1F1E6 ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 231A × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 231A ÷ 0600 ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 231A × 0308 ÷ 0600 ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 231A × 0903 ÷ # ÷ [0.2] WATCH (ExtPict) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 231A × 0308 × 0903 ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 231A ÷ 1100 ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 231A × 0308 ÷ 1100 ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 231A ÷ 1160 ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 231A × 0308 ÷ 1160 ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 231A ÷ 11A8 ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 231A × 0308 ÷ 11A8 ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 231A ÷ AC00 ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 231A × 0308 ÷ AC00 ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 231A ÷ AC01 ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 231A × 0308 ÷ AC01 ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 231A ÷ 231A ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 231A × 0308 ÷ 231A ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 231A × 0300 ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 231A × 0308 × 0300 ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 231A × 200D ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 231A × 0308 × 200D ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 231A ÷ 0378 ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] (Other) ÷ [0.3] +÷ 231A × 0308 ÷ 0378 ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] (Other) ÷ [0.3] +÷ 0300 ÷ 0020 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 0300 × 0308 ÷ 0020 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 0300 ÷ 000D ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [5.0] (CR) ÷ [0.3] +÷ 0300 × 0308 ÷ 000D ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (CR) ÷ [0.3] +÷ 0300 ÷ 000A ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [5.0] (LF) ÷ [0.3] +÷ 0300 × 0308 ÷ 000A ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (LF) ÷ [0.3] +÷ 0300 ÷ 0001 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [5.0] (Control) ÷ [0.3] +÷ 0300 × 0308 ÷ 0001 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (Control) ÷ [0.3] +÷ 0300 × 034F ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 0300 × 0308 × 034F ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 0300 ÷ 1F1E6 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0300 × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0300 ÷ 0600 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 0300 × 0308 ÷ 0600 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 0300 × 0903 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 0300 × 0308 × 0903 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 0300 ÷ 1100 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 0300 × 0308 ÷ 1100 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 0300 ÷ 1160 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 0300 × 0308 ÷ 1160 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 0300 ÷ 11A8 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 0300 × 0308 ÷ 11A8 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 0300 ÷ AC00 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 0300 × 0308 ÷ AC00 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 0300 ÷ AC01 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 0300 × 0308 ÷ AC01 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 0300 ÷ 231A ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0300 × 0308 ÷ 231A ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0300 × 0300 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 0300 × 0308 × 0300 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 0300 × 200D ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 0300 × 0308 × 200D ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 0300 ÷ 0378 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [999.0] (Other) ÷ [0.3] +÷ 0300 × 0308 ÷ 0378 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] (Other) ÷ [0.3] +÷ 200D ÷ 0020 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 200D × 0308 ÷ 0020 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 200D ÷ 000D ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [5.0] (CR) ÷ [0.3] +÷ 200D × 0308 ÷ 000D ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (CR) ÷ [0.3] +÷ 200D ÷ 000A ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [5.0] (LF) ÷ [0.3] +÷ 200D × 0308 ÷ 000A ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (LF) ÷ [0.3] +÷ 200D ÷ 0001 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [5.0] (Control) ÷ [0.3] +÷ 200D × 0308 ÷ 0001 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (Control) ÷ [0.3] +÷ 200D × 034F ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 200D × 0308 × 034F ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 200D ÷ 1F1E6 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 200D × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 200D ÷ 0600 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 200D × 0308 ÷ 0600 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 200D × 0903 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 200D × 0308 × 0903 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 200D ÷ 1100 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 200D × 0308 ÷ 1100 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 200D ÷ 1160 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 200D × 0308 ÷ 1160 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 200D ÷ 11A8 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 200D × 0308 ÷ 11A8 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 200D ÷ AC00 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 200D × 0308 ÷ AC00 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 200D ÷ AC01 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 200D × 0308 ÷ AC01 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 200D ÷ 231A ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 200D × 0308 ÷ 231A ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 200D × 0300 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 200D × 0308 × 0300 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 200D × 200D ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 200D × 0308 × 200D ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 200D ÷ 0378 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [999.0] (Other) ÷ [0.3] +÷ 200D × 0308 ÷ 0378 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] (Other) ÷ [0.3] +÷ 0378 ÷ 0020 ÷ # ÷ [0.2] (Other) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 0378 × 0308 ÷ 0020 ÷ # ÷ [0.2] (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 0378 ÷ 000D ÷ # ÷ [0.2] (Other) ÷ [5.0] (CR) ÷ [0.3] +÷ 0378 × 0308 ÷ 000D ÷ # ÷ [0.2] (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (CR) ÷ [0.3] +÷ 0378 ÷ 000A ÷ # ÷ [0.2] (Other) ÷ [5.0] (LF) ÷ [0.3] +÷ 0378 × 0308 ÷ 000A ÷ # ÷ [0.2] (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (LF) ÷ [0.3] +÷ 0378 ÷ 0001 ÷ # ÷ [0.2] (Other) ÷ [5.0] (Control) ÷ [0.3] +÷ 0378 × 0308 ÷ 0001 ÷ # ÷ [0.2] (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (Control) ÷ [0.3] +÷ 0378 × 034F ÷ # ÷ [0.2] (Other) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 0378 × 0308 × 034F ÷ # ÷ [0.2] (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 0378 ÷ 1F1E6 ÷ # ÷ [0.2] (Other) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0378 × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0378 ÷ 0600 ÷ # ÷ [0.2] (Other) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 0378 × 0308 ÷ 0600 ÷ # ÷ [0.2] (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 0378 × 0903 ÷ # ÷ [0.2] (Other) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 0378 × 0308 × 0903 ÷ # ÷ [0.2] (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 0378 ÷ 1100 ÷ # ÷ [0.2] (Other) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 0378 × 0308 ÷ 1100 ÷ # ÷ [0.2] (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 0378 ÷ 1160 ÷ # ÷ [0.2] (Other) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 0378 × 0308 ÷ 1160 ÷ # ÷ [0.2] (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 0378 ÷ 11A8 ÷ # ÷ [0.2] (Other) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 0378 × 0308 ÷ 11A8 ÷ # ÷ [0.2] (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 0378 ÷ AC00 ÷ # ÷ [0.2] (Other) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 0378 × 0308 ÷ AC00 ÷ # ÷ [0.2] (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 0378 ÷ AC01 ÷ # ÷ [0.2] (Other) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 0378 × 0308 ÷ AC01 ÷ # ÷ [0.2] (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 0378 ÷ 231A ÷ # ÷ [0.2] (Other) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0378 × 0308 ÷ 231A ÷ # ÷ [0.2] (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0378 × 0300 ÷ # ÷ [0.2] (Other) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 0378 × 0308 × 0300 ÷ # ÷ [0.2] (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 0378 × 200D ÷ # ÷ [0.2] (Other) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 0378 × 0308 × 200D ÷ # ÷ [0.2] (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 0378 ÷ 0378 ÷ # ÷ [0.2] (Other) ÷ [999.0] (Other) ÷ [0.3] +÷ 0378 × 0308 ÷ 0378 ÷ # ÷ [0.2] (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] (Other) ÷ [0.3] +÷ 000D × 000A ÷ 0061 ÷ 000A ÷ 0308 ÷ # ÷ [0.2] (CR) × [3.0] (LF) ÷ [4.0] LATIN SMALL LETTER A (Other) ÷ [5.0] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [0.3] +÷ 0061 × 0308 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [0.3] +÷ 0020 × 200D ÷ 0646 ÷ # ÷ [0.2] SPACE (Other) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [999.0] ARABIC LETTER NOON (Other) ÷ [0.3] +÷ 0646 × 200D ÷ 0020 ÷ # ÷ [0.2] ARABIC LETTER NOON (Other) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 1100 × 1100 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [6.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ AC00 × 11A8 ÷ 1100 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [7.0] HANGUL JONGSEONG KIYEOK (T) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ AC01 × 11A8 ÷ 1100 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [8.0] HANGUL JONGSEONG KIYEOK (T) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 1F1E6 × 1F1E7 ÷ 1F1E8 ÷ 0062 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [12.0] REGIONAL INDICATOR SYMBOL LETTER B (RI) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER C (RI) ÷ [999.0] LATIN SMALL LETTER B (Other) ÷ [0.3] +÷ 0061 ÷ 1F1E6 × 1F1E7 ÷ 1F1E8 ÷ 0062 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Other) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [13.0] REGIONAL INDICATOR SYMBOL LETTER B (RI) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER C (RI) ÷ [999.0] LATIN SMALL LETTER B (Other) ÷ [0.3] +÷ 0061 ÷ 1F1E6 × 1F1E7 × 200D ÷ 1F1E8 ÷ 0062 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Other) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [13.0] REGIONAL INDICATOR SYMBOL LETTER B (RI) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER C (RI) ÷ [999.0] LATIN SMALL LETTER B (Other) ÷ [0.3] +÷ 0061 ÷ 1F1E6 × 200D ÷ 1F1E7 × 1F1E8 ÷ 0062 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Other) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER B (RI) × [13.0] REGIONAL INDICATOR SYMBOL LETTER C (RI) ÷ [999.0] LATIN SMALL LETTER B (Other) ÷ [0.3] +÷ 0061 ÷ 1F1E6 × 1F1E7 ÷ 1F1E8 × 1F1E9 ÷ 0062 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Other) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [13.0] REGIONAL INDICATOR SYMBOL LETTER B (RI) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER C (RI) × [13.0] REGIONAL INDICATOR SYMBOL LETTER D (RI) ÷ [999.0] LATIN SMALL LETTER B (Other) ÷ [0.3] +÷ 0061 × 200D ÷ # ÷ [0.2] LATIN SMALL LETTER A (Other) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 0061 × 0308 ÷ 0062 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] LATIN SMALL LETTER B (Other) ÷ [0.3] +÷ 0061 × 0903 ÷ 0062 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Other) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [999.0] LATIN SMALL LETTER B (Other) ÷ [0.3] +÷ 0061 ÷ 0600 × 0062 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Other) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) × [9.2] LATIN SMALL LETTER B (Other) ÷ [0.3] +÷ 1F476 × 1F3FF ÷ 1F476 ÷ # ÷ [0.2] BABY (ExtPict) × [9.0] EMOJI MODIFIER FITZPATRICK TYPE-6 (Extend) ÷ [999.0] BABY (ExtPict) ÷ [0.3] +÷ 0061 × 1F3FF ÷ 1F476 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Other) × [9.0] EMOJI MODIFIER FITZPATRICK TYPE-6 (Extend) ÷ [999.0] BABY (ExtPict) ÷ [0.3] +÷ 0061 × 1F3FF ÷ 1F476 × 200D × 1F6D1 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Other) × [9.0] EMOJI MODIFIER FITZPATRICK TYPE-6 (Extend) ÷ [999.0] BABY (ExtPict) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [11.0] OCTAGONAL SIGN (ExtPict) ÷ [0.3] +÷ 1F476 × 1F3FF × 0308 × 200D × 1F476 × 1F3FF ÷ # ÷ [0.2] BABY (ExtPict) × [9.0] EMOJI MODIFIER FITZPATRICK TYPE-6 (Extend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [11.0] BABY (ExtPict) × [9.0] EMOJI MODIFIER FITZPATRICK TYPE-6 (Extend) ÷ [0.3] +÷ 1F6D1 × 200D × 1F6D1 ÷ # ÷ [0.2] OCTAGONAL SIGN (ExtPict) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [11.0] OCTAGONAL SIGN (ExtPict) ÷ [0.3] +÷ 0061 × 200D ÷ 1F6D1 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Other) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [999.0] OCTAGONAL SIGN (ExtPict) ÷ [0.3] +÷ 2701 × 200D × 2701 ÷ # ÷ [0.2] UPPER BLADE SCISSORS (Other) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [11.0] UPPER BLADE SCISSORS (Other) ÷ [0.3] +÷ 0061 × 200D ÷ 2701 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Other) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [999.0] UPPER BLADE SCISSORS (Other) ÷ [0.3] +# +# Lines: 602 +# +# EOF diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/data/LICENSE-UNICODE b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/data/LICENSE-UNICODE new file mode 100644 index 0000000..ad06935 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/data/LICENSE-UNICODE @@ -0,0 +1,45 @@ +UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE +See Terms of Use for definitions of Unicode Inc.'s +Data Files and Software. + +NOTICE TO USER: Carefully read the following legal agreement. +BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S +DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), +YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE +TERMS AND CONDITIONS OF THIS AGREEMENT. +IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE +THE DATA FILES OR SOFTWARE. + +COPYRIGHT AND PERMISSION NOTICE + +Copyright © 1991-2019 Unicode, Inc. All rights reserved. +Distributed under the Terms of Use in https://www.unicode.org/copyright.html. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Unicode data files and any associated documentation +(the "Data Files") or Unicode software and any associated documentation +(the "Software") to deal in the Data Files or Software +without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, and/or sell copies of +the Data Files or Software, and to permit persons to whom the Data Files +or Software are furnished to do so, provided that either +(a) this copyright and permission notice appear with all copies +of the Data Files or Software, or +(b) this copyright and permission notice appear in associated +Documentation. + +THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT OF THIRD PARTY RIGHTS. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS +NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL +DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THE DATA FILES OR SOFTWARE. + +Except as contained in this notice, the name of a copyright holder +shall not be used in advertising or otherwise to promote the sale, +use or other dealings in these Data Files or Software without prior +written authorization of the copyright holder. diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/data/SentenceBreakTest.txt b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/data/SentenceBreakTest.txt new file mode 100644 index 0000000..7c1c34a --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/data/SentenceBreakTest.txt @@ -0,0 +1,530 @@ +# SentenceBreakTest-12.1.0.txt +# Date: 2019-03-10, 10:53:28 GMT +# © 2019 Unicode®, Inc. +# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. +# For terms of use, see http://www.unicode.org/terms_of_use.html +# +# Unicode Character Database +# For documentation, see http://www.unicode.org/reports/tr44/ +# +# Default Sentence_Break Test +# +# Format: +# (# )? +# contains hex Unicode code points, with +# ÷ wherever there is a break opportunity, and +# × wherever there is not. +# the format can change, but currently it shows: +# - the sample character name +# - (x) the Sentence_Break property value for the sample character +# - [x] the rule that determines whether there is a break or not, +# as listed in the Rules section of SentenceBreakTest.html +# +# These samples may be extended or changed in the future. +# +÷ 0001 × 0001 ÷ # ÷ [0.2] (Other) × [998.0] (Other) ÷ [0.3] +÷ 0001 × 0308 × 0001 ÷ # ÷ [0.2] (Other) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Other) ÷ [0.3] +÷ 0001 × 000D ÷ # ÷ [0.2] (Other) × [998.0] (CR) ÷ [0.3] +÷ 0001 × 0308 × 000D ÷ # ÷ [0.2] (Other) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (CR) ÷ [0.3] +÷ 0001 × 000A ÷ # ÷ [0.2] (Other) × [998.0] (LF) ÷ [0.3] +÷ 0001 × 0308 × 000A ÷ # ÷ [0.2] (Other) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (LF) ÷ [0.3] +÷ 0001 × 0085 ÷ # ÷ [0.2] (Other) × [998.0] (Sep) ÷ [0.3] +÷ 0001 × 0308 × 0085 ÷ # ÷ [0.2] (Other) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Sep) ÷ [0.3] +÷ 0001 × 0009 ÷ # ÷ [0.2] (Other) × [998.0] (Sp) ÷ [0.3] +÷ 0001 × 0308 × 0009 ÷ # ÷ [0.2] (Other) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Sp) ÷ [0.3] +÷ 0001 × 0061 ÷ # ÷ [0.2] (Other) × [998.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 0001 × 0308 × 0061 ÷ # ÷ [0.2] (Other) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 0001 × 0041 ÷ # ÷ [0.2] (Other) × [998.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 0001 × 0308 × 0041 ÷ # ÷ [0.2] (Other) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 0001 × 01BB ÷ # ÷ [0.2] (Other) × [998.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 0001 × 0308 × 01BB ÷ # ÷ [0.2] (Other) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 0001 × 0030 ÷ # ÷ [0.2] (Other) × [998.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0001 × 0308 × 0030 ÷ # ÷ [0.2] (Other) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0001 × 002E ÷ # ÷ [0.2] (Other) × [998.0] FULL STOP (ATerm) ÷ [0.3] +÷ 0001 × 0308 × 002E ÷ # ÷ [0.2] (Other) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] FULL STOP (ATerm) ÷ [0.3] +÷ 0001 × 0021 ÷ # ÷ [0.2] (Other) × [998.0] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 0001 × 0308 × 0021 ÷ # ÷ [0.2] (Other) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 0001 × 0022 ÷ # ÷ [0.2] (Other) × [998.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 0001 × 0308 × 0022 ÷ # ÷ [0.2] (Other) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 0001 × 002C ÷ # ÷ [0.2] (Other) × [998.0] COMMA (SContinue) ÷ [0.3] +÷ 0001 × 0308 × 002C ÷ # ÷ [0.2] (Other) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] COMMA (SContinue) ÷ [0.3] +÷ 0001 × 00AD ÷ # ÷ [0.2] (Other) × [5.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0001 × 0308 × 00AD ÷ # ÷ [0.2] (Other) × [5.0] COMBINING DIAERESIS (Extend_FE) × [5.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0001 × 0300 ÷ # ÷ [0.2] (Other) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0001 × 0308 × 0300 ÷ # ÷ [0.2] (Other) × [5.0] COMBINING DIAERESIS (Extend_FE) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 000D ÷ 0001 ÷ # ÷ [0.2] (CR) ÷ [4.0] (Other) ÷ [0.3] +÷ 000D ÷ 0308 × 0001 ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Other) ÷ [0.3] +÷ 000D ÷ 000D ÷ # ÷ [0.2] (CR) ÷ [4.0] (CR) ÷ [0.3] +÷ 000D ÷ 0308 × 000D ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (CR) ÷ [0.3] +÷ 000D × 000A ÷ # ÷ [0.2] (CR) × [3.0] (LF) ÷ [0.3] +÷ 000D ÷ 0308 × 000A ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (LF) ÷ [0.3] +÷ 000D ÷ 0085 ÷ # ÷ [0.2] (CR) ÷ [4.0] (Sep) ÷ [0.3] +÷ 000D ÷ 0308 × 0085 ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Sep) ÷ [0.3] +÷ 000D ÷ 0009 ÷ # ÷ [0.2] (CR) ÷ [4.0] (Sp) ÷ [0.3] +÷ 000D ÷ 0308 × 0009 ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Sp) ÷ [0.3] +÷ 000D ÷ 0061 ÷ # ÷ [0.2] (CR) ÷ [4.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 000D ÷ 0308 × 0061 ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 000D ÷ 0041 ÷ # ÷ [0.2] (CR) ÷ [4.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 000D ÷ 0308 × 0041 ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 000D ÷ 01BB ÷ # ÷ [0.2] (CR) ÷ [4.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 000D ÷ 0308 × 01BB ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 000D ÷ 0030 ÷ # ÷ [0.2] (CR) ÷ [4.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 000D ÷ 0308 × 0030 ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 000D ÷ 002E ÷ # ÷ [0.2] (CR) ÷ [4.0] FULL STOP (ATerm) ÷ [0.3] +÷ 000D ÷ 0308 × 002E ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] FULL STOP (ATerm) ÷ [0.3] +÷ 000D ÷ 0021 ÷ # ÷ [0.2] (CR) ÷ [4.0] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 000D ÷ 0308 × 0021 ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 000D ÷ 0022 ÷ # ÷ [0.2] (CR) ÷ [4.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 000D ÷ 0308 × 0022 ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 000D ÷ 002C ÷ # ÷ [0.2] (CR) ÷ [4.0] COMMA (SContinue) ÷ [0.3] +÷ 000D ÷ 0308 × 002C ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] COMMA (SContinue) ÷ [0.3] +÷ 000D ÷ 00AD ÷ # ÷ [0.2] (CR) ÷ [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 000D ÷ 0308 × 00AD ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [5.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 000D ÷ 0300 ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 000D ÷ 0308 × 0300 ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 000A ÷ 0001 ÷ # ÷ [0.2] (LF) ÷ [4.0] (Other) ÷ [0.3] +÷ 000A ÷ 0308 × 0001 ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Other) ÷ [0.3] +÷ 000A ÷ 000D ÷ # ÷ [0.2] (LF) ÷ [4.0] (CR) ÷ [0.3] +÷ 000A ÷ 0308 × 000D ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (CR) ÷ [0.3] +÷ 000A ÷ 000A ÷ # ÷ [0.2] (LF) ÷ [4.0] (LF) ÷ [0.3] +÷ 000A ÷ 0308 × 000A ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (LF) ÷ [0.3] +÷ 000A ÷ 0085 ÷ # ÷ [0.2] (LF) ÷ [4.0] (Sep) ÷ [0.3] +÷ 000A ÷ 0308 × 0085 ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Sep) ÷ [0.3] +÷ 000A ÷ 0009 ÷ # ÷ [0.2] (LF) ÷ [4.0] (Sp) ÷ [0.3] +÷ 000A ÷ 0308 × 0009 ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Sp) ÷ [0.3] +÷ 000A ÷ 0061 ÷ # ÷ [0.2] (LF) ÷ [4.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 000A ÷ 0308 × 0061 ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 000A ÷ 0041 ÷ # ÷ [0.2] (LF) ÷ [4.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 000A ÷ 0308 × 0041 ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 000A ÷ 01BB ÷ # ÷ [0.2] (LF) ÷ [4.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 000A ÷ 0308 × 01BB ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 000A ÷ 0030 ÷ # ÷ [0.2] (LF) ÷ [4.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 000A ÷ 0308 × 0030 ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 000A ÷ 002E ÷ # ÷ [0.2] (LF) ÷ [4.0] FULL STOP (ATerm) ÷ [0.3] +÷ 000A ÷ 0308 × 002E ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] FULL STOP (ATerm) ÷ [0.3] +÷ 000A ÷ 0021 ÷ # ÷ [0.2] (LF) ÷ [4.0] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 000A ÷ 0308 × 0021 ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 000A ÷ 0022 ÷ # ÷ [0.2] (LF) ÷ [4.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 000A ÷ 0308 × 0022 ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 000A ÷ 002C ÷ # ÷ [0.2] (LF) ÷ [4.0] COMMA (SContinue) ÷ [0.3] +÷ 000A ÷ 0308 × 002C ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] COMMA (SContinue) ÷ [0.3] +÷ 000A ÷ 00AD ÷ # ÷ [0.2] (LF) ÷ [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 000A ÷ 0308 × 00AD ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [5.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 000A ÷ 0300 ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 000A ÷ 0308 × 0300 ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0085 ÷ 0001 ÷ # ÷ [0.2] (Sep) ÷ [4.0] (Other) ÷ [0.3] +÷ 0085 ÷ 0308 × 0001 ÷ # ÷ [0.2] (Sep) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Other) ÷ [0.3] +÷ 0085 ÷ 000D ÷ # ÷ [0.2] (Sep) ÷ [4.0] (CR) ÷ [0.3] +÷ 0085 ÷ 0308 × 000D ÷ # ÷ [0.2] (Sep) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (CR) ÷ [0.3] +÷ 0085 ÷ 000A ÷ # ÷ [0.2] (Sep) ÷ [4.0] (LF) ÷ [0.3] +÷ 0085 ÷ 0308 × 000A ÷ # ÷ [0.2] (Sep) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (LF) ÷ [0.3] +÷ 0085 ÷ 0085 ÷ # ÷ [0.2] (Sep) ÷ [4.0] (Sep) ÷ [0.3] +÷ 0085 ÷ 0308 × 0085 ÷ # ÷ [0.2] (Sep) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Sep) ÷ [0.3] +÷ 0085 ÷ 0009 ÷ # ÷ [0.2] (Sep) ÷ [4.0] (Sp) ÷ [0.3] +÷ 0085 ÷ 0308 × 0009 ÷ # ÷ [0.2] (Sep) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Sp) ÷ [0.3] +÷ 0085 ÷ 0061 ÷ # ÷ [0.2] (Sep) ÷ [4.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 0085 ÷ 0308 × 0061 ÷ # ÷ [0.2] (Sep) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 0085 ÷ 0041 ÷ # ÷ [0.2] (Sep) ÷ [4.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 0085 ÷ 0308 × 0041 ÷ # ÷ [0.2] (Sep) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 0085 ÷ 01BB ÷ # ÷ [0.2] (Sep) ÷ [4.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 0085 ÷ 0308 × 01BB ÷ # ÷ [0.2] (Sep) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 0085 ÷ 0030 ÷ # ÷ [0.2] (Sep) ÷ [4.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0085 ÷ 0308 × 0030 ÷ # ÷ [0.2] (Sep) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0085 ÷ 002E ÷ # ÷ [0.2] (Sep) ÷ [4.0] FULL STOP (ATerm) ÷ [0.3] +÷ 0085 ÷ 0308 × 002E ÷ # ÷ [0.2] (Sep) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] FULL STOP (ATerm) ÷ [0.3] +÷ 0085 ÷ 0021 ÷ # ÷ [0.2] (Sep) ÷ [4.0] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 0085 ÷ 0308 × 0021 ÷ # ÷ [0.2] (Sep) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 0085 ÷ 0022 ÷ # ÷ [0.2] (Sep) ÷ [4.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 0085 ÷ 0308 × 0022 ÷ # ÷ [0.2] (Sep) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 0085 ÷ 002C ÷ # ÷ [0.2] (Sep) ÷ [4.0] COMMA (SContinue) ÷ [0.3] +÷ 0085 ÷ 0308 × 002C ÷ # ÷ [0.2] (Sep) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] COMMA (SContinue) ÷ [0.3] +÷ 0085 ÷ 00AD ÷ # ÷ [0.2] (Sep) ÷ [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0085 ÷ 0308 × 00AD ÷ # ÷ [0.2] (Sep) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [5.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0085 ÷ 0300 ÷ # ÷ [0.2] (Sep) ÷ [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0085 ÷ 0308 × 0300 ÷ # ÷ [0.2] (Sep) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0009 × 0001 ÷ # ÷ [0.2] (Sp) × [998.0] (Other) ÷ [0.3] +÷ 0009 × 0308 × 0001 ÷ # ÷ [0.2] (Sp) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Other) ÷ [0.3] +÷ 0009 × 000D ÷ # ÷ [0.2] (Sp) × [998.0] (CR) ÷ [0.3] +÷ 0009 × 0308 × 000D ÷ # ÷ [0.2] (Sp) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (CR) ÷ [0.3] +÷ 0009 × 000A ÷ # ÷ [0.2] (Sp) × [998.0] (LF) ÷ [0.3] +÷ 0009 × 0308 × 000A ÷ # ÷ [0.2] (Sp) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (LF) ÷ [0.3] +÷ 0009 × 0085 ÷ # ÷ [0.2] (Sp) × [998.0] (Sep) ÷ [0.3] +÷ 0009 × 0308 × 0085 ÷ # ÷ [0.2] (Sp) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Sep) ÷ [0.3] +÷ 0009 × 0009 ÷ # ÷ [0.2] (Sp) × [998.0] (Sp) ÷ [0.3] +÷ 0009 × 0308 × 0009 ÷ # ÷ [0.2] (Sp) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Sp) ÷ [0.3] +÷ 0009 × 0061 ÷ # ÷ [0.2] (Sp) × [998.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 0009 × 0308 × 0061 ÷ # ÷ [0.2] (Sp) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 0009 × 0041 ÷ # ÷ [0.2] (Sp) × [998.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 0009 × 0308 × 0041 ÷ # ÷ [0.2] (Sp) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 0009 × 01BB ÷ # ÷ [0.2] (Sp) × [998.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 0009 × 0308 × 01BB ÷ # ÷ [0.2] (Sp) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 0009 × 0030 ÷ # ÷ [0.2] (Sp) × [998.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0009 × 0308 × 0030 ÷ # ÷ [0.2] (Sp) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0009 × 002E ÷ # ÷ [0.2] (Sp) × [998.0] FULL STOP (ATerm) ÷ [0.3] +÷ 0009 × 0308 × 002E ÷ # ÷ [0.2] (Sp) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] FULL STOP (ATerm) ÷ [0.3] +÷ 0009 × 0021 ÷ # ÷ [0.2] (Sp) × [998.0] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 0009 × 0308 × 0021 ÷ # ÷ [0.2] (Sp) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 0009 × 0022 ÷ # ÷ [0.2] (Sp) × [998.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 0009 × 0308 × 0022 ÷ # ÷ [0.2] (Sp) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 0009 × 002C ÷ # ÷ [0.2] (Sp) × [998.0] COMMA (SContinue) ÷ [0.3] +÷ 0009 × 0308 × 002C ÷ # ÷ [0.2] (Sp) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] COMMA (SContinue) ÷ [0.3] +÷ 0009 × 00AD ÷ # ÷ [0.2] (Sp) × [5.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0009 × 0308 × 00AD ÷ # ÷ [0.2] (Sp) × [5.0] COMBINING DIAERESIS (Extend_FE) × [5.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0009 × 0300 ÷ # ÷ [0.2] (Sp) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0009 × 0308 × 0300 ÷ # ÷ [0.2] (Sp) × [5.0] COMBINING DIAERESIS (Extend_FE) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0061 × 0001 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [998.0] (Other) ÷ [0.3] +÷ 0061 × 0308 × 0001 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Other) ÷ [0.3] +÷ 0061 × 000D ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [998.0] (CR) ÷ [0.3] +÷ 0061 × 0308 × 000D ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (CR) ÷ [0.3] +÷ 0061 × 000A ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [998.0] (LF) ÷ [0.3] +÷ 0061 × 0308 × 000A ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (LF) ÷ [0.3] +÷ 0061 × 0085 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [998.0] (Sep) ÷ [0.3] +÷ 0061 × 0308 × 0085 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Sep) ÷ [0.3] +÷ 0061 × 0009 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [998.0] (Sp) ÷ [0.3] +÷ 0061 × 0308 × 0009 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Sp) ÷ [0.3] +÷ 0061 × 0061 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [998.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 0061 × 0308 × 0061 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 0061 × 0041 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [998.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 0061 × 0308 × 0041 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 0061 × 01BB ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [998.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 0061 × 0308 × 01BB ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 0061 × 0030 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [998.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0061 × 0308 × 0030 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0061 × 002E ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [998.0] FULL STOP (ATerm) ÷ [0.3] +÷ 0061 × 0308 × 002E ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] FULL STOP (ATerm) ÷ [0.3] +÷ 0061 × 0021 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [998.0] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 0061 × 0308 × 0021 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 0061 × 0022 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [998.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 0061 × 0308 × 0022 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 0061 × 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [998.0] COMMA (SContinue) ÷ [0.3] +÷ 0061 × 0308 × 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] COMMA (SContinue) ÷ [0.3] +÷ 0061 × 00AD ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [5.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0061 × 0308 × 00AD ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [5.0] COMBINING DIAERESIS (Extend_FE) × [5.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0061 × 0300 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0061 × 0308 × 0300 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [5.0] COMBINING DIAERESIS (Extend_FE) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0041 × 0001 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [998.0] (Other) ÷ [0.3] +÷ 0041 × 0308 × 0001 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Other) ÷ [0.3] +÷ 0041 × 000D ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [998.0] (CR) ÷ [0.3] +÷ 0041 × 0308 × 000D ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (CR) ÷ [0.3] +÷ 0041 × 000A ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [998.0] (LF) ÷ [0.3] +÷ 0041 × 0308 × 000A ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (LF) ÷ [0.3] +÷ 0041 × 0085 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [998.0] (Sep) ÷ [0.3] +÷ 0041 × 0308 × 0085 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Sep) ÷ [0.3] +÷ 0041 × 0009 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [998.0] (Sp) ÷ [0.3] +÷ 0041 × 0308 × 0009 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Sp) ÷ [0.3] +÷ 0041 × 0061 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [998.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 0041 × 0308 × 0061 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 0041 × 0041 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [998.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 0041 × 0308 × 0041 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 0041 × 01BB ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [998.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 0041 × 0308 × 01BB ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 0041 × 0030 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [998.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0041 × 0308 × 0030 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0041 × 002E ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [998.0] FULL STOP (ATerm) ÷ [0.3] +÷ 0041 × 0308 × 002E ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] FULL STOP (ATerm) ÷ [0.3] +÷ 0041 × 0021 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [998.0] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 0041 × 0308 × 0021 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 0041 × 0022 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [998.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 0041 × 0308 × 0022 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 0041 × 002C ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [998.0] COMMA (SContinue) ÷ [0.3] +÷ 0041 × 0308 × 002C ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] COMMA (SContinue) ÷ [0.3] +÷ 0041 × 00AD ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [5.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0041 × 0308 × 00AD ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [5.0] COMBINING DIAERESIS (Extend_FE) × [5.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0041 × 0300 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0041 × 0308 × 0300 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (Upper) × [5.0] COMBINING DIAERESIS (Extend_FE) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 01BB × 0001 ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [998.0] (Other) ÷ [0.3] +÷ 01BB × 0308 × 0001 ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Other) ÷ [0.3] +÷ 01BB × 000D ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [998.0] (CR) ÷ [0.3] +÷ 01BB × 0308 × 000D ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (CR) ÷ [0.3] +÷ 01BB × 000A ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [998.0] (LF) ÷ [0.3] +÷ 01BB × 0308 × 000A ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (LF) ÷ [0.3] +÷ 01BB × 0085 ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [998.0] (Sep) ÷ [0.3] +÷ 01BB × 0308 × 0085 ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Sep) ÷ [0.3] +÷ 01BB × 0009 ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [998.0] (Sp) ÷ [0.3] +÷ 01BB × 0308 × 0009 ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Sp) ÷ [0.3] +÷ 01BB × 0061 ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [998.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 01BB × 0308 × 0061 ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 01BB × 0041 ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [998.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 01BB × 0308 × 0041 ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 01BB × 01BB ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [998.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 01BB × 0308 × 01BB ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 01BB × 0030 ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [998.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 01BB × 0308 × 0030 ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 01BB × 002E ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [998.0] FULL STOP (ATerm) ÷ [0.3] +÷ 01BB × 0308 × 002E ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] FULL STOP (ATerm) ÷ [0.3] +÷ 01BB × 0021 ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [998.0] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 01BB × 0308 × 0021 ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 01BB × 0022 ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [998.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 01BB × 0308 × 0022 ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 01BB × 002C ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [998.0] COMMA (SContinue) ÷ [0.3] +÷ 01BB × 0308 × 002C ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] COMMA (SContinue) ÷ [0.3] +÷ 01BB × 00AD ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [5.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 01BB × 0308 × 00AD ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [5.0] COMBINING DIAERESIS (Extend_FE) × [5.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 01BB × 0300 ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 01BB × 0308 × 0300 ÷ # ÷ [0.2] LATIN LETTER TWO WITH STROKE (OLetter) × [5.0] COMBINING DIAERESIS (Extend_FE) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0030 × 0001 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [998.0] (Other) ÷ [0.3] +÷ 0030 × 0308 × 0001 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Other) ÷ [0.3] +÷ 0030 × 000D ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [998.0] (CR) ÷ [0.3] +÷ 0030 × 0308 × 000D ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (CR) ÷ [0.3] +÷ 0030 × 000A ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [998.0] (LF) ÷ [0.3] +÷ 0030 × 0308 × 000A ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (LF) ÷ [0.3] +÷ 0030 × 0085 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [998.0] (Sep) ÷ [0.3] +÷ 0030 × 0308 × 0085 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Sep) ÷ [0.3] +÷ 0030 × 0009 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [998.0] (Sp) ÷ [0.3] +÷ 0030 × 0308 × 0009 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Sp) ÷ [0.3] +÷ 0030 × 0061 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [998.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 0030 × 0308 × 0061 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 0030 × 0041 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [998.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 0030 × 0308 × 0041 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 0030 × 01BB ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [998.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 0030 × 0308 × 01BB ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 0030 × 0030 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [998.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0030 × 0308 × 0030 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0030 × 002E ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [998.0] FULL STOP (ATerm) ÷ [0.3] +÷ 0030 × 0308 × 002E ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] FULL STOP (ATerm) ÷ [0.3] +÷ 0030 × 0021 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [998.0] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 0030 × 0308 × 0021 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 0030 × 0022 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [998.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 0030 × 0308 × 0022 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 0030 × 002C ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [998.0] COMMA (SContinue) ÷ [0.3] +÷ 0030 × 0308 × 002C ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] COMMA (SContinue) ÷ [0.3] +÷ 0030 × 00AD ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [5.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0030 × 0308 × 00AD ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [5.0] COMBINING DIAERESIS (Extend_FE) × [5.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0030 × 0300 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0030 × 0308 × 0300 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [5.0] COMBINING DIAERESIS (Extend_FE) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 002E ÷ 0001 ÷ # ÷ [0.2] FULL STOP (ATerm) ÷ [11.0] (Other) ÷ [0.3] +÷ 002E × 0308 ÷ 0001 ÷ # ÷ [0.2] FULL STOP (ATerm) × [5.0] COMBINING DIAERESIS (Extend_FE) ÷ [11.0] (Other) ÷ [0.3] +÷ 002E × 000D ÷ # ÷ [0.2] FULL STOP (ATerm) × [9.0] (CR) ÷ [0.3] +÷ 002E × 0308 × 000D ÷ # ÷ [0.2] FULL STOP (ATerm) × [5.0] COMBINING DIAERESIS (Extend_FE) × [9.0] (CR) ÷ [0.3] +÷ 002E × 000A ÷ # ÷ [0.2] FULL STOP (ATerm) × [9.0] (LF) ÷ [0.3] +÷ 002E × 0308 × 000A ÷ # ÷ [0.2] FULL STOP (ATerm) × [5.0] COMBINING DIAERESIS (Extend_FE) × [9.0] (LF) ÷ [0.3] +÷ 002E × 0085 ÷ # ÷ [0.2] FULL STOP (ATerm) × [9.0] (Sep) ÷ [0.3] +÷ 002E × 0308 × 0085 ÷ # ÷ [0.2] FULL STOP (ATerm) × [5.0] COMBINING DIAERESIS (Extend_FE) × [9.0] (Sep) ÷ [0.3] +÷ 002E × 0009 ÷ # ÷ [0.2] FULL STOP (ATerm) × [9.0] (Sp) ÷ [0.3] +÷ 002E × 0308 × 0009 ÷ # ÷ [0.2] FULL STOP (ATerm) × [5.0] COMBINING DIAERESIS (Extend_FE) × [9.0] (Sp) ÷ [0.3] +÷ 002E × 0061 ÷ # ÷ [0.2] FULL STOP (ATerm) × [8.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 002E × 0308 × 0061 ÷ # ÷ [0.2] FULL STOP (ATerm) × [5.0] COMBINING DIAERESIS (Extend_FE) × [8.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 002E ÷ 0041 ÷ # ÷ [0.2] FULL STOP (ATerm) ÷ [11.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 002E × 0308 ÷ 0041 ÷ # ÷ [0.2] FULL STOP (ATerm) × [5.0] COMBINING DIAERESIS (Extend_FE) ÷ [11.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 002E ÷ 01BB ÷ # ÷ [0.2] FULL STOP (ATerm) ÷ [11.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 002E × 0308 ÷ 01BB ÷ # ÷ [0.2] FULL STOP (ATerm) × [5.0] COMBINING DIAERESIS (Extend_FE) ÷ [11.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 002E × 0030 ÷ # ÷ [0.2] FULL STOP (ATerm) × [6.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 002E × 0308 × 0030 ÷ # ÷ [0.2] FULL STOP (ATerm) × [5.0] COMBINING DIAERESIS (Extend_FE) × [6.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 002E × 002E ÷ # ÷ [0.2] FULL STOP (ATerm) × [8.1] FULL STOP (ATerm) ÷ [0.3] +÷ 002E × 0308 × 002E ÷ # ÷ [0.2] FULL STOP (ATerm) × [5.0] COMBINING DIAERESIS (Extend_FE) × [8.1] FULL STOP (ATerm) ÷ [0.3] +÷ 002E × 0021 ÷ # ÷ [0.2] FULL STOP (ATerm) × [8.1] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 002E × 0308 × 0021 ÷ # ÷ [0.2] FULL STOP (ATerm) × [5.0] COMBINING DIAERESIS (Extend_FE) × [8.1] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 002E × 0022 ÷ # ÷ [0.2] FULL STOP (ATerm) × [9.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 002E × 0308 × 0022 ÷ # ÷ [0.2] FULL STOP (ATerm) × [5.0] COMBINING DIAERESIS (Extend_FE) × [9.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 002E × 002C ÷ # ÷ [0.2] FULL STOP (ATerm) × [8.1] COMMA (SContinue) ÷ [0.3] +÷ 002E × 0308 × 002C ÷ # ÷ [0.2] FULL STOP (ATerm) × [5.0] COMBINING DIAERESIS (Extend_FE) × [8.1] COMMA (SContinue) ÷ [0.3] +÷ 002E × 00AD ÷ # ÷ [0.2] FULL STOP (ATerm) × [5.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 002E × 0308 × 00AD ÷ # ÷ [0.2] FULL STOP (ATerm) × [5.0] COMBINING DIAERESIS (Extend_FE) × [5.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 002E × 0300 ÷ # ÷ [0.2] FULL STOP (ATerm) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 002E × 0308 × 0300 ÷ # ÷ [0.2] FULL STOP (ATerm) × [5.0] COMBINING DIAERESIS (Extend_FE) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0021 ÷ 0001 ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) ÷ [11.0] (Other) ÷ [0.3] +÷ 0021 × 0308 ÷ 0001 ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) × [5.0] COMBINING DIAERESIS (Extend_FE) ÷ [11.0] (Other) ÷ [0.3] +÷ 0021 × 000D ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) × [9.0] (CR) ÷ [0.3] +÷ 0021 × 0308 × 000D ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) × [5.0] COMBINING DIAERESIS (Extend_FE) × [9.0] (CR) ÷ [0.3] +÷ 0021 × 000A ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) × [9.0] (LF) ÷ [0.3] +÷ 0021 × 0308 × 000A ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) × [5.0] COMBINING DIAERESIS (Extend_FE) × [9.0] (LF) ÷ [0.3] +÷ 0021 × 0085 ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) × [9.0] (Sep) ÷ [0.3] +÷ 0021 × 0308 × 0085 ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) × [5.0] COMBINING DIAERESIS (Extend_FE) × [9.0] (Sep) ÷ [0.3] +÷ 0021 × 0009 ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) × [9.0] (Sp) ÷ [0.3] +÷ 0021 × 0308 × 0009 ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) × [5.0] COMBINING DIAERESIS (Extend_FE) × [9.0] (Sp) ÷ [0.3] +÷ 0021 ÷ 0061 ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) ÷ [11.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 0021 × 0308 ÷ 0061 ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) × [5.0] COMBINING DIAERESIS (Extend_FE) ÷ [11.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 0021 ÷ 0041 ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) ÷ [11.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 0021 × 0308 ÷ 0041 ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) × [5.0] COMBINING DIAERESIS (Extend_FE) ÷ [11.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 0021 ÷ 01BB ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) ÷ [11.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 0021 × 0308 ÷ 01BB ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) × [5.0] COMBINING DIAERESIS (Extend_FE) ÷ [11.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 0021 ÷ 0030 ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) ÷ [11.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0021 × 0308 ÷ 0030 ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) × [5.0] COMBINING DIAERESIS (Extend_FE) ÷ [11.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0021 × 002E ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) × [8.1] FULL STOP (ATerm) ÷ [0.3] +÷ 0021 × 0308 × 002E ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) × [5.0] COMBINING DIAERESIS (Extend_FE) × [8.1] FULL STOP (ATerm) ÷ [0.3] +÷ 0021 × 0021 ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) × [8.1] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 0021 × 0308 × 0021 ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) × [5.0] COMBINING DIAERESIS (Extend_FE) × [8.1] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 0021 × 0022 ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) × [9.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 0021 × 0308 × 0022 ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) × [5.0] COMBINING DIAERESIS (Extend_FE) × [9.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 0021 × 002C ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) × [8.1] COMMA (SContinue) ÷ [0.3] +÷ 0021 × 0308 × 002C ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) × [5.0] COMBINING DIAERESIS (Extend_FE) × [8.1] COMMA (SContinue) ÷ [0.3] +÷ 0021 × 00AD ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) × [5.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0021 × 0308 × 00AD ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) × [5.0] COMBINING DIAERESIS (Extend_FE) × [5.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0021 × 0300 ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0021 × 0308 × 0300 ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) × [5.0] COMBINING DIAERESIS (Extend_FE) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0022 × 0001 ÷ # ÷ [0.2] QUOTATION MARK (Close) × [998.0] (Other) ÷ [0.3] +÷ 0022 × 0308 × 0001 ÷ # ÷ [0.2] QUOTATION MARK (Close) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Other) ÷ [0.3] +÷ 0022 × 000D ÷ # ÷ [0.2] QUOTATION MARK (Close) × [998.0] (CR) ÷ [0.3] +÷ 0022 × 0308 × 000D ÷ # ÷ [0.2] QUOTATION MARK (Close) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (CR) ÷ [0.3] +÷ 0022 × 000A ÷ # ÷ [0.2] QUOTATION MARK (Close) × [998.0] (LF) ÷ [0.3] +÷ 0022 × 0308 × 000A ÷ # ÷ [0.2] QUOTATION MARK (Close) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (LF) ÷ [0.3] +÷ 0022 × 0085 ÷ # ÷ [0.2] QUOTATION MARK (Close) × [998.0] (Sep) ÷ [0.3] +÷ 0022 × 0308 × 0085 ÷ # ÷ [0.2] QUOTATION MARK (Close) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Sep) ÷ [0.3] +÷ 0022 × 0009 ÷ # ÷ [0.2] QUOTATION MARK (Close) × [998.0] (Sp) ÷ [0.3] +÷ 0022 × 0308 × 0009 ÷ # ÷ [0.2] QUOTATION MARK (Close) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Sp) ÷ [0.3] +÷ 0022 × 0061 ÷ # ÷ [0.2] QUOTATION MARK (Close) × [998.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 0022 × 0308 × 0061 ÷ # ÷ [0.2] QUOTATION MARK (Close) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 0022 × 0041 ÷ # ÷ [0.2] QUOTATION MARK (Close) × [998.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 0022 × 0308 × 0041 ÷ # ÷ [0.2] QUOTATION MARK (Close) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 0022 × 01BB ÷ # ÷ [0.2] QUOTATION MARK (Close) × [998.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 0022 × 0308 × 01BB ÷ # ÷ [0.2] QUOTATION MARK (Close) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 0022 × 0030 ÷ # ÷ [0.2] QUOTATION MARK (Close) × [998.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0022 × 0308 × 0030 ÷ # ÷ [0.2] QUOTATION MARK (Close) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0022 × 002E ÷ # ÷ [0.2] QUOTATION MARK (Close) × [998.0] FULL STOP (ATerm) ÷ [0.3] +÷ 0022 × 0308 × 002E ÷ # ÷ [0.2] QUOTATION MARK (Close) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] FULL STOP (ATerm) ÷ [0.3] +÷ 0022 × 0021 ÷ # ÷ [0.2] QUOTATION MARK (Close) × [998.0] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 0022 × 0308 × 0021 ÷ # ÷ [0.2] QUOTATION MARK (Close) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 0022 × 0022 ÷ # ÷ [0.2] QUOTATION MARK (Close) × [998.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 0022 × 0308 × 0022 ÷ # ÷ [0.2] QUOTATION MARK (Close) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 0022 × 002C ÷ # ÷ [0.2] QUOTATION MARK (Close) × [998.0] COMMA (SContinue) ÷ [0.3] +÷ 0022 × 0308 × 002C ÷ # ÷ [0.2] QUOTATION MARK (Close) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] COMMA (SContinue) ÷ [0.3] +÷ 0022 × 00AD ÷ # ÷ [0.2] QUOTATION MARK (Close) × [5.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0022 × 0308 × 00AD ÷ # ÷ [0.2] QUOTATION MARK (Close) × [5.0] COMBINING DIAERESIS (Extend_FE) × [5.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0022 × 0300 ÷ # ÷ [0.2] QUOTATION MARK (Close) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0022 × 0308 × 0300 ÷ # ÷ [0.2] QUOTATION MARK (Close) × [5.0] COMBINING DIAERESIS (Extend_FE) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 002C × 0001 ÷ # ÷ [0.2] COMMA (SContinue) × [998.0] (Other) ÷ [0.3] +÷ 002C × 0308 × 0001 ÷ # ÷ [0.2] COMMA (SContinue) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Other) ÷ [0.3] +÷ 002C × 000D ÷ # ÷ [0.2] COMMA (SContinue) × [998.0] (CR) ÷ [0.3] +÷ 002C × 0308 × 000D ÷ # ÷ [0.2] COMMA (SContinue) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (CR) ÷ [0.3] +÷ 002C × 000A ÷ # ÷ [0.2] COMMA (SContinue) × [998.0] (LF) ÷ [0.3] +÷ 002C × 0308 × 000A ÷ # ÷ [0.2] COMMA (SContinue) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (LF) ÷ [0.3] +÷ 002C × 0085 ÷ # ÷ [0.2] COMMA (SContinue) × [998.0] (Sep) ÷ [0.3] +÷ 002C × 0308 × 0085 ÷ # ÷ [0.2] COMMA (SContinue) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Sep) ÷ [0.3] +÷ 002C × 0009 ÷ # ÷ [0.2] COMMA (SContinue) × [998.0] (Sp) ÷ [0.3] +÷ 002C × 0308 × 0009 ÷ # ÷ [0.2] COMMA (SContinue) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Sp) ÷ [0.3] +÷ 002C × 0061 ÷ # ÷ [0.2] COMMA (SContinue) × [998.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 002C × 0308 × 0061 ÷ # ÷ [0.2] COMMA (SContinue) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 002C × 0041 ÷ # ÷ [0.2] COMMA (SContinue) × [998.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 002C × 0308 × 0041 ÷ # ÷ [0.2] COMMA (SContinue) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 002C × 01BB ÷ # ÷ [0.2] COMMA (SContinue) × [998.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 002C × 0308 × 01BB ÷ # ÷ [0.2] COMMA (SContinue) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 002C × 0030 ÷ # ÷ [0.2] COMMA (SContinue) × [998.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 002C × 0308 × 0030 ÷ # ÷ [0.2] COMMA (SContinue) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 002C × 002E ÷ # ÷ [0.2] COMMA (SContinue) × [998.0] FULL STOP (ATerm) ÷ [0.3] +÷ 002C × 0308 × 002E ÷ # ÷ [0.2] COMMA (SContinue) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] FULL STOP (ATerm) ÷ [0.3] +÷ 002C × 0021 ÷ # ÷ [0.2] COMMA (SContinue) × [998.0] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 002C × 0308 × 0021 ÷ # ÷ [0.2] COMMA (SContinue) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 002C × 0022 ÷ # ÷ [0.2] COMMA (SContinue) × [998.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 002C × 0308 × 0022 ÷ # ÷ [0.2] COMMA (SContinue) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 002C × 002C ÷ # ÷ [0.2] COMMA (SContinue) × [998.0] COMMA (SContinue) ÷ [0.3] +÷ 002C × 0308 × 002C ÷ # ÷ [0.2] COMMA (SContinue) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] COMMA (SContinue) ÷ [0.3] +÷ 002C × 00AD ÷ # ÷ [0.2] COMMA (SContinue) × [5.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 002C × 0308 × 00AD ÷ # ÷ [0.2] COMMA (SContinue) × [5.0] COMBINING DIAERESIS (Extend_FE) × [5.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 002C × 0300 ÷ # ÷ [0.2] COMMA (SContinue) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 002C × 0308 × 0300 ÷ # ÷ [0.2] COMMA (SContinue) × [5.0] COMBINING DIAERESIS (Extend_FE) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 00AD × 0001 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [998.0] (Other) ÷ [0.3] +÷ 00AD × 0308 × 0001 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Other) ÷ [0.3] +÷ 00AD × 000D ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [998.0] (CR) ÷ [0.3] +÷ 00AD × 0308 × 000D ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (CR) ÷ [0.3] +÷ 00AD × 000A ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [998.0] (LF) ÷ [0.3] +÷ 00AD × 0308 × 000A ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (LF) ÷ [0.3] +÷ 00AD × 0085 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [998.0] (Sep) ÷ [0.3] +÷ 00AD × 0308 × 0085 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Sep) ÷ [0.3] +÷ 00AD × 0009 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [998.0] (Sp) ÷ [0.3] +÷ 00AD × 0308 × 0009 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Sp) ÷ [0.3] +÷ 00AD × 0061 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [998.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 00AD × 0308 × 0061 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 00AD × 0041 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [998.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 00AD × 0308 × 0041 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 00AD × 01BB ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [998.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 00AD × 0308 × 01BB ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 00AD × 0030 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [998.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 00AD × 0308 × 0030 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 00AD × 002E ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [998.0] FULL STOP (ATerm) ÷ [0.3] +÷ 00AD × 0308 × 002E ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] FULL STOP (ATerm) ÷ [0.3] +÷ 00AD × 0021 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [998.0] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 00AD × 0308 × 0021 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 00AD × 0022 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [998.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 00AD × 0308 × 0022 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 00AD × 002C ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [998.0] COMMA (SContinue) ÷ [0.3] +÷ 00AD × 0308 × 002C ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] COMMA (SContinue) ÷ [0.3] +÷ 00AD × 00AD ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [5.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 00AD × 0308 × 00AD ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [5.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 00AD × 0300 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 00AD × 0308 × 0300 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0300 × 0001 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [998.0] (Other) ÷ [0.3] +÷ 0300 × 0308 × 0001 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Other) ÷ [0.3] +÷ 0300 × 000D ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [998.0] (CR) ÷ [0.3] +÷ 0300 × 0308 × 000D ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (CR) ÷ [0.3] +÷ 0300 × 000A ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [998.0] (LF) ÷ [0.3] +÷ 0300 × 0308 × 000A ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (LF) ÷ [0.3] +÷ 0300 × 0085 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [998.0] (Sep) ÷ [0.3] +÷ 0300 × 0308 × 0085 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Sep) ÷ [0.3] +÷ 0300 × 0009 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [998.0] (Sp) ÷ [0.3] +÷ 0300 × 0308 × 0009 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] (Sp) ÷ [0.3] +÷ 0300 × 0061 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [998.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 0300 × 0308 × 0061 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN SMALL LETTER A (Lower) ÷ [0.3] +÷ 0300 × 0041 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [998.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 0300 × 0308 × 0041 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN CAPITAL LETTER A (Upper) ÷ [0.3] +÷ 0300 × 01BB ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [998.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 0300 × 0308 × 01BB ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN LETTER TWO WITH STROKE (OLetter) ÷ [0.3] +÷ 0300 × 0030 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [998.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0300 × 0308 × 0030 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0300 × 002E ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [998.0] FULL STOP (ATerm) ÷ [0.3] +÷ 0300 × 0308 × 002E ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] FULL STOP (ATerm) ÷ [0.3] +÷ 0300 × 0021 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [998.0] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 0300 × 0308 × 0021 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] EXCLAMATION MARK (STerm) ÷ [0.3] +÷ 0300 × 0022 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [998.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 0300 × 0308 × 0022 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] QUOTATION MARK (Close) ÷ [0.3] +÷ 0300 × 002C ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [998.0] COMMA (SContinue) ÷ [0.3] +÷ 0300 × 0308 × 002C ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [998.0] COMMA (SContinue) ÷ [0.3] +÷ 0300 × 00AD ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [5.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0300 × 0308 × 00AD ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [5.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0300 × 0300 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0300 × 0308 × 0300 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 000D × 000A ÷ 0061 × 000A ÷ 0308 ÷ # ÷ [0.2] (CR) × [3.0] (LF) ÷ [4.0] LATIN SMALL LETTER A (Lower) × [998.0] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [0.3] +÷ 0061 × 0308 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Lower) × [5.0] COMBINING DIAERESIS (Extend_FE) ÷ [0.3] +÷ 0020 × 200D × 0646 ÷ # ÷ [0.2] SPACE (Sp) × [5.0] ZERO WIDTH JOINER (Extend_FE) × [998.0] ARABIC LETTER NOON (OLetter) ÷ [0.3] +÷ 0646 × 200D × 0020 ÷ # ÷ [0.2] ARABIC LETTER NOON (OLetter) × [5.0] ZERO WIDTH JOINER (Extend_FE) × [998.0] SPACE (Sp) ÷ [0.3] +÷ 0028 × 0022 × 0047 × 006F × 002E × 0022 × 0029 × 0020 ÷ 0028 × 0048 × 0065 × 0020 × 0064 × 0069 × 0064 × 002E × 0029 ÷ # ÷ [0.2] LEFT PARENTHESIS (Close) × [998.0] QUOTATION MARK (Close) × [998.0] LATIN CAPITAL LETTER G (Upper) × [998.0] LATIN SMALL LETTER O (Lower) × [998.0] FULL STOP (ATerm) × [9.0] QUOTATION MARK (Close) × [9.0] RIGHT PARENTHESIS (Close) × [9.0] SPACE (Sp) ÷ [11.0] LEFT PARENTHESIS (Close) × [998.0] LATIN CAPITAL LETTER H (Upper) × [998.0] LATIN SMALL LETTER E (Lower) × [998.0] SPACE (Sp) × [998.0] LATIN SMALL LETTER D (Lower) × [998.0] LATIN SMALL LETTER I (Lower) × [998.0] LATIN SMALL LETTER D (Lower) × [998.0] FULL STOP (ATerm) × [9.0] RIGHT PARENTHESIS (Close) ÷ [0.3] +÷ 0028 × 201C × 0047 × 006F × 003F × 201D × 0029 × 0020 ÷ 0028 × 0048 × 0065 × 0020 × 0064 × 0069 × 0064 × 002E × 0029 ÷ # ÷ [0.2] LEFT PARENTHESIS (Close) × [998.0] LEFT DOUBLE QUOTATION MARK (Close) × [998.0] LATIN CAPITAL LETTER G (Upper) × [998.0] LATIN SMALL LETTER O (Lower) × [998.0] QUESTION MARK (STerm) × [9.0] RIGHT DOUBLE QUOTATION MARK (Close) × [9.0] RIGHT PARENTHESIS (Close) × [9.0] SPACE (Sp) ÷ [11.0] LEFT PARENTHESIS (Close) × [998.0] LATIN CAPITAL LETTER H (Upper) × [998.0] LATIN SMALL LETTER E (Lower) × [998.0] SPACE (Sp) × [998.0] LATIN SMALL LETTER D (Lower) × [998.0] LATIN SMALL LETTER I (Lower) × [998.0] LATIN SMALL LETTER D (Lower) × [998.0] FULL STOP (ATerm) × [9.0] RIGHT PARENTHESIS (Close) ÷ [0.3] +÷ 0055 × 002E × 0053 × 002E × 0041 × 0300 × 002E × 0020 × 0069 × 0073 ÷ # ÷ [0.2] LATIN CAPITAL LETTER U (Upper) × [998.0] FULL STOP (ATerm) × [7.0] LATIN CAPITAL LETTER S (Upper) × [998.0] FULL STOP (ATerm) × [7.0] LATIN CAPITAL LETTER A (Upper) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) × [998.0] FULL STOP (ATerm) × [8.0] SPACE (Sp) × [8.0] LATIN SMALL LETTER I (Lower) × [998.0] LATIN SMALL LETTER S (Lower) ÷ [0.3] +÷ 0055 × 002E × 0053 × 002E × 0041 × 0300 × 003F × 0020 ÷ 0048 × 0065 ÷ # ÷ [0.2] LATIN CAPITAL LETTER U (Upper) × [998.0] FULL STOP (ATerm) × [7.0] LATIN CAPITAL LETTER S (Upper) × [998.0] FULL STOP (ATerm) × [7.0] LATIN CAPITAL LETTER A (Upper) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) × [998.0] QUESTION MARK (STerm) × [9.0] SPACE (Sp) ÷ [11.0] LATIN CAPITAL LETTER H (Upper) × [998.0] LATIN SMALL LETTER E (Lower) ÷ [0.3] +÷ 0055 × 002E × 0053 × 002E × 0041 × 0300 × 002E ÷ # ÷ [0.2] LATIN CAPITAL LETTER U (Upper) × [998.0] FULL STOP (ATerm) × [7.0] LATIN CAPITAL LETTER S (Upper) × [998.0] FULL STOP (ATerm) × [7.0] LATIN CAPITAL LETTER A (Upper) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) × [998.0] FULL STOP (ATerm) ÷ [0.3] +÷ 0033 × 002E × 0034 ÷ # ÷ [0.2] DIGIT THREE (Numeric) × [998.0] FULL STOP (ATerm) × [6.0] DIGIT FOUR (Numeric) ÷ [0.3] +÷ 0063 × 002E × 0064 ÷ # ÷ [0.2] LATIN SMALL LETTER C (Lower) × [998.0] FULL STOP (ATerm) × [8.0] LATIN SMALL LETTER D (Lower) ÷ [0.3] +÷ 0043 × 002E × 0064 ÷ # ÷ [0.2] LATIN CAPITAL LETTER C (Upper) × [998.0] FULL STOP (ATerm) × [8.0] LATIN SMALL LETTER D (Lower) ÷ [0.3] +÷ 0063 × 002E × 0044 ÷ # ÷ [0.2] LATIN SMALL LETTER C (Lower) × [998.0] FULL STOP (ATerm) × [7.0] LATIN CAPITAL LETTER D (Upper) ÷ [0.3] +÷ 0043 × 002E × 0044 ÷ # ÷ [0.2] LATIN CAPITAL LETTER C (Upper) × [998.0] FULL STOP (ATerm) × [7.0] LATIN CAPITAL LETTER D (Upper) ÷ [0.3] +÷ 0065 × 0074 × 0063 × 002E × 0029 × 2019 × 00A0 × 0074 × 0068 × 0065 ÷ # ÷ [0.2] LATIN SMALL LETTER E (Lower) × [998.0] LATIN SMALL LETTER T (Lower) × [998.0] LATIN SMALL LETTER C (Lower) × [998.0] FULL STOP (ATerm) × [8.0] RIGHT PARENTHESIS (Close) × [8.0] RIGHT SINGLE QUOTATION MARK (Close) × [8.0] NO-BREAK SPACE (Sp) × [8.0] LATIN SMALL LETTER T (Lower) × [998.0] LATIN SMALL LETTER H (Lower) × [998.0] LATIN SMALL LETTER E (Lower) ÷ [0.3] +÷ 0065 × 0074 × 0063 × 002E × 0029 × 2019 × 00A0 ÷ 0054 × 0068 × 0065 ÷ # ÷ [0.2] LATIN SMALL LETTER E (Lower) × [998.0] LATIN SMALL LETTER T (Lower) × [998.0] LATIN SMALL LETTER C (Lower) × [998.0] FULL STOP (ATerm) × [9.0] RIGHT PARENTHESIS (Close) × [9.0] RIGHT SINGLE QUOTATION MARK (Close) × [9.0] NO-BREAK SPACE (Sp) ÷ [11.0] LATIN CAPITAL LETTER T (Upper) × [998.0] LATIN SMALL LETTER H (Lower) × [998.0] LATIN SMALL LETTER E (Lower) ÷ [0.3] +÷ 0065 × 0074 × 0063 × 002E × 0029 × 2019 × 00A0 × 2018 × 0028 × 0074 × 0068 × 0065 ÷ # ÷ [0.2] LATIN SMALL LETTER E (Lower) × [998.0] LATIN SMALL LETTER T (Lower) × [998.0] LATIN SMALL LETTER C (Lower) × [998.0] FULL STOP (ATerm) × [8.0] RIGHT PARENTHESIS (Close) × [8.0] RIGHT SINGLE QUOTATION MARK (Close) × [8.0] NO-BREAK SPACE (Sp) × [8.0] LEFT SINGLE QUOTATION MARK (Close) × [998.0] LEFT PARENTHESIS (Close) × [998.0] LATIN SMALL LETTER T (Lower) × [998.0] LATIN SMALL LETTER H (Lower) × [998.0] LATIN SMALL LETTER E (Lower) ÷ [0.3] +÷ 0065 × 0074 × 0063 × 002E × 0029 × 2019 × 00A0 ÷ 2018 × 0028 × 0054 × 0068 × 0065 ÷ # ÷ [0.2] LATIN SMALL LETTER E (Lower) × [998.0] LATIN SMALL LETTER T (Lower) × [998.0] LATIN SMALL LETTER C (Lower) × [998.0] FULL STOP (ATerm) × [9.0] RIGHT PARENTHESIS (Close) × [9.0] RIGHT SINGLE QUOTATION MARK (Close) × [9.0] NO-BREAK SPACE (Sp) ÷ [11.0] LEFT SINGLE QUOTATION MARK (Close) × [998.0] LEFT PARENTHESIS (Close) × [998.0] LATIN CAPITAL LETTER T (Upper) × [998.0] LATIN SMALL LETTER H (Lower) × [998.0] LATIN SMALL LETTER E (Lower) ÷ [0.3] +÷ 0065 × 0074 × 0063 × 002E × 0029 × 2019 × 00A0 × 0308 × 0074 × 0068 × 0065 ÷ # ÷ [0.2] LATIN SMALL LETTER E (Lower) × [998.0] LATIN SMALL LETTER T (Lower) × [998.0] LATIN SMALL LETTER C (Lower) × [998.0] FULL STOP (ATerm) × [8.0] RIGHT PARENTHESIS (Close) × [8.0] RIGHT SINGLE QUOTATION MARK (Close) × [8.0] NO-BREAK SPACE (Sp) × [5.0] COMBINING DIAERESIS (Extend_FE) × [8.0] LATIN SMALL LETTER T (Lower) × [998.0] LATIN SMALL LETTER H (Lower) × [998.0] LATIN SMALL LETTER E (Lower) ÷ [0.3] +÷ 0065 × 0074 × 0063 × 002E × 0029 × 2019 × 00A0 × 0308 ÷ 0054 × 0068 × 0065 ÷ # ÷ [0.2] LATIN SMALL LETTER E (Lower) × [998.0] LATIN SMALL LETTER T (Lower) × [998.0] LATIN SMALL LETTER C (Lower) × [998.0] FULL STOP (ATerm) × [9.0] RIGHT PARENTHESIS (Close) × [9.0] RIGHT SINGLE QUOTATION MARK (Close) × [9.0] NO-BREAK SPACE (Sp) × [5.0] COMBINING DIAERESIS (Extend_FE) ÷ [11.0] LATIN CAPITAL LETTER T (Upper) × [998.0] LATIN SMALL LETTER H (Lower) × [998.0] LATIN SMALL LETTER E (Lower) ÷ [0.3] +÷ 0065 × 0074 × 0063 × 002E × 0029 × 2019 × 0308 ÷ 0054 × 0068 × 0065 ÷ # ÷ [0.2] LATIN SMALL LETTER E (Lower) × [998.0] LATIN SMALL LETTER T (Lower) × [998.0] LATIN SMALL LETTER C (Lower) × [998.0] FULL STOP (ATerm) × [9.0] RIGHT PARENTHESIS (Close) × [9.0] RIGHT SINGLE QUOTATION MARK (Close) × [5.0] COMBINING DIAERESIS (Extend_FE) ÷ [11.0] LATIN CAPITAL LETTER T (Upper) × [998.0] LATIN SMALL LETTER H (Lower) × [998.0] LATIN SMALL LETTER E (Lower) ÷ [0.3] +÷ 0065 × 0074 × 0063 × 002E × 0029 × 000A ÷ 0308 × 0054 × 0068 × 0065 ÷ # ÷ [0.2] LATIN SMALL LETTER E (Lower) × [998.0] LATIN SMALL LETTER T (Lower) × [998.0] LATIN SMALL LETTER C (Lower) × [998.0] FULL STOP (ATerm) × [9.0] RIGHT PARENTHESIS (Close) × [9.0] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_FE) × [998.0] LATIN CAPITAL LETTER T (Upper) × [998.0] LATIN SMALL LETTER H (Lower) × [998.0] LATIN SMALL LETTER E (Lower) ÷ [0.3] +÷ 0074 × 0068 × 0065 × 0020 × 0072 × 0065 × 0073 × 0070 × 002E × 0020 × 006C × 0065 × 0061 × 0064 × 0065 × 0072 × 0073 × 0020 × 0061 × 0072 × 0065 ÷ # ÷ [0.2] LATIN SMALL LETTER T (Lower) × [998.0] LATIN SMALL LETTER H (Lower) × [998.0] LATIN SMALL LETTER E (Lower) × [998.0] SPACE (Sp) × [998.0] LATIN SMALL LETTER R (Lower) × [998.0] LATIN SMALL LETTER E (Lower) × [998.0] LATIN SMALL LETTER S (Lower) × [998.0] LATIN SMALL LETTER P (Lower) × [998.0] FULL STOP (ATerm) × [8.0] SPACE (Sp) × [8.0] LATIN SMALL LETTER L (Lower) × [998.0] LATIN SMALL LETTER E (Lower) × [998.0] LATIN SMALL LETTER A (Lower) × [998.0] LATIN SMALL LETTER D (Lower) × [998.0] LATIN SMALL LETTER E (Lower) × [998.0] LATIN SMALL LETTER R (Lower) × [998.0] LATIN SMALL LETTER S (Lower) × [998.0] SPACE (Sp) × [998.0] LATIN SMALL LETTER A (Lower) × [998.0] LATIN SMALL LETTER R (Lower) × [998.0] LATIN SMALL LETTER E (Lower) ÷ [0.3] +÷ 5B57 × 002E ÷ 5B57 ÷ # ÷ [0.2] CJK UNIFIED IDEOGRAPH-5B57 (OLetter) × [998.0] FULL STOP (ATerm) ÷ [11.0] CJK UNIFIED IDEOGRAPH-5B57 (OLetter) ÷ [0.3] +÷ 0065 × 0074 × 0063 × 002E ÷ 5B83 ÷ # ÷ [0.2] LATIN SMALL LETTER E (Lower) × [998.0] LATIN SMALL LETTER T (Lower) × [998.0] LATIN SMALL LETTER C (Lower) × [998.0] FULL STOP (ATerm) ÷ [11.0] CJK UNIFIED IDEOGRAPH-5B83 (OLetter) ÷ [0.3] +÷ 0065 × 0074 × 0063 × 002E × 3002 ÷ # ÷ [0.2] LATIN SMALL LETTER E (Lower) × [998.0] LATIN SMALL LETTER T (Lower) × [998.0] LATIN SMALL LETTER C (Lower) × [998.0] FULL STOP (ATerm) × [8.1] IDEOGRAPHIC FULL STOP (STerm) ÷ [0.3] +÷ 5B57 × 3002 ÷ 5B83 ÷ # ÷ [0.2] CJK UNIFIED IDEOGRAPH-5B57 (OLetter) × [998.0] IDEOGRAPHIC FULL STOP (STerm) ÷ [11.0] CJK UNIFIED IDEOGRAPH-5B83 (OLetter) ÷ [0.3] +÷ 0021 × 0020 × 0020 ÷ # ÷ [0.2] EXCLAMATION MARK (STerm) × [9.0] SPACE (Sp) × [10.0] SPACE (Sp) ÷ [0.3] +÷ 2060 × 0028 × 2060 × 0022 × 2060 × 0047 × 2060 × 006F × 2060 × 002E × 2060 × 0022 × 2060 × 0029 × 2060 × 0020 × 2060 ÷ 0028 × 2060 × 0048 × 2060 × 0065 × 2060 × 0020 × 2060 × 0064 × 2060 × 0069 × 2060 × 0064 × 2060 × 002E × 2060 × 0029 × 2060 × 2060 ÷ # ÷ [0.2] WORD JOINER (Format_FE) × [998.0] LEFT PARENTHESIS (Close) × [5.0] WORD JOINER (Format_FE) × [998.0] QUOTATION MARK (Close) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN CAPITAL LETTER G (Upper) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER O (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] FULL STOP (ATerm) × [5.0] WORD JOINER (Format_FE) × [9.0] QUOTATION MARK (Close) × [5.0] WORD JOINER (Format_FE) × [9.0] RIGHT PARENTHESIS (Close) × [5.0] WORD JOINER (Format_FE) × [9.0] SPACE (Sp) × [5.0] WORD JOINER (Format_FE) ÷ [11.0] LEFT PARENTHESIS (Close) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN CAPITAL LETTER H (Upper) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER E (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] SPACE (Sp) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER D (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER I (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER D (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] FULL STOP (ATerm) × [5.0] WORD JOINER (Format_FE) × [9.0] RIGHT PARENTHESIS (Close) × [5.0] WORD JOINER (Format_FE) × [5.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 2060 × 0028 × 2060 × 201C × 2060 × 0047 × 2060 × 006F × 2060 × 003F × 2060 × 201D × 2060 × 0029 × 2060 × 0020 × 2060 ÷ 0028 × 2060 × 0048 × 2060 × 0065 × 2060 × 0020 × 2060 × 0064 × 2060 × 0069 × 2060 × 0064 × 2060 × 002E × 2060 × 0029 × 2060 × 2060 ÷ # ÷ [0.2] WORD JOINER (Format_FE) × [998.0] LEFT PARENTHESIS (Close) × [5.0] WORD JOINER (Format_FE) × [998.0] LEFT DOUBLE QUOTATION MARK (Close) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN CAPITAL LETTER G (Upper) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER O (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] QUESTION MARK (STerm) × [5.0] WORD JOINER (Format_FE) × [9.0] RIGHT DOUBLE QUOTATION MARK (Close) × [5.0] WORD JOINER (Format_FE) × [9.0] RIGHT PARENTHESIS (Close) × [5.0] WORD JOINER (Format_FE) × [9.0] SPACE (Sp) × [5.0] WORD JOINER (Format_FE) ÷ [11.0] LEFT PARENTHESIS (Close) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN CAPITAL LETTER H (Upper) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER E (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] SPACE (Sp) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER D (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER I (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER D (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] FULL STOP (ATerm) × [5.0] WORD JOINER (Format_FE) × [9.0] RIGHT PARENTHESIS (Close) × [5.0] WORD JOINER (Format_FE) × [5.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 2060 × 0055 × 2060 × 002E × 2060 × 0053 × 2060 × 002E × 2060 × 0041 × 2060 × 0300 × 002E × 2060 × 0020 × 2060 × 0069 × 2060 × 0073 × 2060 × 2060 ÷ # ÷ [0.2] WORD JOINER (Format_FE) × [998.0] LATIN CAPITAL LETTER U (Upper) × [5.0] WORD JOINER (Format_FE) × [998.0] FULL STOP (ATerm) × [5.0] WORD JOINER (Format_FE) × [7.0] LATIN CAPITAL LETTER S (Upper) × [5.0] WORD JOINER (Format_FE) × [998.0] FULL STOP (ATerm) × [5.0] WORD JOINER (Format_FE) × [7.0] LATIN CAPITAL LETTER A (Upper) × [5.0] WORD JOINER (Format_FE) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) × [998.0] FULL STOP (ATerm) × [5.0] WORD JOINER (Format_FE) × [8.0] SPACE (Sp) × [5.0] WORD JOINER (Format_FE) × [8.0] LATIN SMALL LETTER I (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER S (Lower) × [5.0] WORD JOINER (Format_FE) × [5.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 2060 × 0055 × 2060 × 002E × 2060 × 0053 × 2060 × 002E × 2060 × 0041 × 2060 × 0300 × 003F × 2060 × 0020 × 2060 ÷ 0048 × 2060 × 0065 × 2060 × 2060 ÷ # ÷ [0.2] WORD JOINER (Format_FE) × [998.0] LATIN CAPITAL LETTER U (Upper) × [5.0] WORD JOINER (Format_FE) × [998.0] FULL STOP (ATerm) × [5.0] WORD JOINER (Format_FE) × [7.0] LATIN CAPITAL LETTER S (Upper) × [5.0] WORD JOINER (Format_FE) × [998.0] FULL STOP (ATerm) × [5.0] WORD JOINER (Format_FE) × [7.0] LATIN CAPITAL LETTER A (Upper) × [5.0] WORD JOINER (Format_FE) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) × [998.0] QUESTION MARK (STerm) × [5.0] WORD JOINER (Format_FE) × [9.0] SPACE (Sp) × [5.0] WORD JOINER (Format_FE) ÷ [11.0] LATIN CAPITAL LETTER H (Upper) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER E (Lower) × [5.0] WORD JOINER (Format_FE) × [5.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 2060 × 0055 × 2060 × 002E × 2060 × 0053 × 2060 × 002E × 2060 × 0041 × 2060 × 0300 × 002E × 2060 × 2060 ÷ # ÷ [0.2] WORD JOINER (Format_FE) × [998.0] LATIN CAPITAL LETTER U (Upper) × [5.0] WORD JOINER (Format_FE) × [998.0] FULL STOP (ATerm) × [5.0] WORD JOINER (Format_FE) × [7.0] LATIN CAPITAL LETTER S (Upper) × [5.0] WORD JOINER (Format_FE) × [998.0] FULL STOP (ATerm) × [5.0] WORD JOINER (Format_FE) × [7.0] LATIN CAPITAL LETTER A (Upper) × [5.0] WORD JOINER (Format_FE) × [5.0] COMBINING GRAVE ACCENT (Extend_FE) × [998.0] FULL STOP (ATerm) × [5.0] WORD JOINER (Format_FE) × [5.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 2060 × 0033 × 2060 × 002E × 2060 × 0034 × 2060 × 2060 ÷ # ÷ [0.2] WORD JOINER (Format_FE) × [998.0] DIGIT THREE (Numeric) × [5.0] WORD JOINER (Format_FE) × [998.0] FULL STOP (ATerm) × [5.0] WORD JOINER (Format_FE) × [6.0] DIGIT FOUR (Numeric) × [5.0] WORD JOINER (Format_FE) × [5.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 2060 × 0063 × 2060 × 002E × 2060 × 0064 × 2060 × 2060 ÷ # ÷ [0.2] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER C (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] FULL STOP (ATerm) × [5.0] WORD JOINER (Format_FE) × [8.0] LATIN SMALL LETTER D (Lower) × [5.0] WORD JOINER (Format_FE) × [5.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 2060 × 0043 × 2060 × 002E × 2060 × 0064 × 2060 × 2060 ÷ # ÷ [0.2] WORD JOINER (Format_FE) × [998.0] LATIN CAPITAL LETTER C (Upper) × [5.0] WORD JOINER (Format_FE) × [998.0] FULL STOP (ATerm) × [5.0] WORD JOINER (Format_FE) × [8.0] LATIN SMALL LETTER D (Lower) × [5.0] WORD JOINER (Format_FE) × [5.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 2060 × 0063 × 2060 × 002E × 2060 × 0044 × 2060 × 2060 ÷ # ÷ [0.2] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER C (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] FULL STOP (ATerm) × [5.0] WORD JOINER (Format_FE) × [7.0] LATIN CAPITAL LETTER D (Upper) × [5.0] WORD JOINER (Format_FE) × [5.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 2060 × 0043 × 2060 × 002E × 2060 × 0044 × 2060 × 2060 ÷ # ÷ [0.2] WORD JOINER (Format_FE) × [998.0] LATIN CAPITAL LETTER C (Upper) × [5.0] WORD JOINER (Format_FE) × [998.0] FULL STOP (ATerm) × [5.0] WORD JOINER (Format_FE) × [7.0] LATIN CAPITAL LETTER D (Upper) × [5.0] WORD JOINER (Format_FE) × [5.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 2060 × 0065 × 2060 × 0074 × 2060 × 0063 × 2060 × 002E × 2060 × 0029 × 2060 × 2019 × 2060 × 00A0 × 2060 × 0074 × 2060 × 0068 × 2060 × 0065 × 2060 × 2060 ÷ # ÷ [0.2] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER E (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER T (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER C (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] FULL STOP (ATerm) × [5.0] WORD JOINER (Format_FE) × [8.0] RIGHT PARENTHESIS (Close) × [5.0] WORD JOINER (Format_FE) × [8.0] RIGHT SINGLE QUOTATION MARK (Close) × [5.0] WORD JOINER (Format_FE) × [8.0] NO-BREAK SPACE (Sp) × [5.0] WORD JOINER (Format_FE) × [8.0] LATIN SMALL LETTER T (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER H (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER E (Lower) × [5.0] WORD JOINER (Format_FE) × [5.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 2060 × 0065 × 2060 × 0074 × 2060 × 0063 × 2060 × 002E × 2060 × 0029 × 2060 × 2019 × 2060 × 00A0 × 2060 ÷ 0054 × 2060 × 0068 × 2060 × 0065 × 2060 × 2060 ÷ # ÷ [0.2] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER E (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER T (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER C (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] FULL STOP (ATerm) × [5.0] WORD JOINER (Format_FE) × [9.0] RIGHT PARENTHESIS (Close) × [5.0] WORD JOINER (Format_FE) × [9.0] RIGHT SINGLE QUOTATION MARK (Close) × [5.0] WORD JOINER (Format_FE) × [9.0] NO-BREAK SPACE (Sp) × [5.0] WORD JOINER (Format_FE) ÷ [11.0] LATIN CAPITAL LETTER T (Upper) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER H (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER E (Lower) × [5.0] WORD JOINER (Format_FE) × [5.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 2060 × 0065 × 2060 × 0074 × 2060 × 0063 × 2060 × 002E × 2060 × 0029 × 2060 × 2019 × 2060 × 00A0 × 2060 × 2018 × 2060 × 0028 × 2060 × 0074 × 2060 × 0068 × 2060 × 0065 × 2060 × 2060 ÷ # ÷ [0.2] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER E (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER T (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER C (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] FULL STOP (ATerm) × [5.0] WORD JOINER (Format_FE) × [8.0] RIGHT PARENTHESIS (Close) × [5.0] WORD JOINER (Format_FE) × [8.0] RIGHT SINGLE QUOTATION MARK (Close) × [5.0] WORD JOINER (Format_FE) × [8.0] NO-BREAK SPACE (Sp) × [5.0] WORD JOINER (Format_FE) × [8.0] LEFT SINGLE QUOTATION MARK (Close) × [5.0] WORD JOINER (Format_FE) × [998.0] LEFT PARENTHESIS (Close) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER T (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER H (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER E (Lower) × [5.0] WORD JOINER (Format_FE) × [5.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 2060 × 0065 × 2060 × 0074 × 2060 × 0063 × 2060 × 002E × 2060 × 0029 × 2060 × 2019 × 2060 × 00A0 × 2060 ÷ 2018 × 2060 × 0028 × 2060 × 0054 × 2060 × 0068 × 2060 × 0065 × 2060 × 2060 ÷ # ÷ [0.2] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER E (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER T (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER C (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] FULL STOP (ATerm) × [5.0] WORD JOINER (Format_FE) × [9.0] RIGHT PARENTHESIS (Close) × [5.0] WORD JOINER (Format_FE) × [9.0] RIGHT SINGLE QUOTATION MARK (Close) × [5.0] WORD JOINER (Format_FE) × [9.0] NO-BREAK SPACE (Sp) × [5.0] WORD JOINER (Format_FE) ÷ [11.0] LEFT SINGLE QUOTATION MARK (Close) × [5.0] WORD JOINER (Format_FE) × [998.0] LEFT PARENTHESIS (Close) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN CAPITAL LETTER T (Upper) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER H (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER E (Lower) × [5.0] WORD JOINER (Format_FE) × [5.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 2060 × 0065 × 2060 × 0074 × 2060 × 0063 × 2060 × 002E × 2060 × 0029 × 2060 × 2019 × 2060 × 00A0 × 2060 × 0308 × 0074 × 2060 × 0068 × 2060 × 0065 × 2060 × 2060 ÷ # ÷ [0.2] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER E (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER T (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER C (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] FULL STOP (ATerm) × [5.0] WORD JOINER (Format_FE) × [8.0] RIGHT PARENTHESIS (Close) × [5.0] WORD JOINER (Format_FE) × [8.0] RIGHT SINGLE QUOTATION MARK (Close) × [5.0] WORD JOINER (Format_FE) × [8.0] NO-BREAK SPACE (Sp) × [5.0] WORD JOINER (Format_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [8.0] LATIN SMALL LETTER T (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER H (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER E (Lower) × [5.0] WORD JOINER (Format_FE) × [5.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 2060 × 0065 × 2060 × 0074 × 2060 × 0063 × 2060 × 002E × 2060 × 0029 × 2060 × 2019 × 2060 × 00A0 × 2060 × 0308 ÷ 0054 × 2060 × 0068 × 2060 × 0065 × 2060 × 2060 ÷ # ÷ [0.2] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER E (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER T (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER C (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] FULL STOP (ATerm) × [5.0] WORD JOINER (Format_FE) × [9.0] RIGHT PARENTHESIS (Close) × [5.0] WORD JOINER (Format_FE) × [9.0] RIGHT SINGLE QUOTATION MARK (Close) × [5.0] WORD JOINER (Format_FE) × [9.0] NO-BREAK SPACE (Sp) × [5.0] WORD JOINER (Format_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) ÷ [11.0] LATIN CAPITAL LETTER T (Upper) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER H (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER E (Lower) × [5.0] WORD JOINER (Format_FE) × [5.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 2060 × 0065 × 2060 × 0074 × 2060 × 0063 × 2060 × 002E × 2060 × 0029 × 2060 × 2019 × 2060 × 0308 ÷ 0054 × 2060 × 0068 × 2060 × 0065 × 2060 × 2060 ÷ # ÷ [0.2] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER E (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER T (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER C (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] FULL STOP (ATerm) × [5.0] WORD JOINER (Format_FE) × [9.0] RIGHT PARENTHESIS (Close) × [5.0] WORD JOINER (Format_FE) × [9.0] RIGHT SINGLE QUOTATION MARK (Close) × [5.0] WORD JOINER (Format_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) ÷ [11.0] LATIN CAPITAL LETTER T (Upper) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER H (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER E (Lower) × [5.0] WORD JOINER (Format_FE) × [5.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 2060 × 0065 × 2060 × 0074 × 2060 × 0063 × 2060 × 002E × 2060 × 0029 × 2060 × 000A ÷ 2060 × 0308 × 2060 × 0054 × 2060 × 0068 × 2060 × 0065 × 2060 × 2060 ÷ # ÷ [0.2] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER E (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER T (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER C (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] FULL STOP (ATerm) × [5.0] WORD JOINER (Format_FE) × [9.0] RIGHT PARENTHESIS (Close) × [5.0] WORD JOINER (Format_FE) × [9.0] (LF) ÷ [4.0] WORD JOINER (Format_FE) × [5.0] COMBINING DIAERESIS (Extend_FE) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN CAPITAL LETTER T (Upper) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER H (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER E (Lower) × [5.0] WORD JOINER (Format_FE) × [5.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 2060 × 0074 × 2060 × 0068 × 2060 × 0065 × 2060 × 0020 × 2060 × 0072 × 2060 × 0065 × 2060 × 0073 × 2060 × 0070 × 2060 × 002E × 2060 × 0020 × 2060 × 006C × 2060 × 0065 × 2060 × 0061 × 2060 × 0064 × 2060 × 0065 × 2060 × 0072 × 2060 × 0073 × 2060 × 0020 × 2060 × 0061 × 2060 × 0072 × 2060 × 0065 × 2060 × 2060 ÷ # ÷ [0.2] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER T (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER H (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER E (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] SPACE (Sp) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER R (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER E (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER S (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER P (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] FULL STOP (ATerm) × [5.0] WORD JOINER (Format_FE) × [8.0] SPACE (Sp) × [5.0] WORD JOINER (Format_FE) × [8.0] LATIN SMALL LETTER L (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER E (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER A (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER D (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER E (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER R (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER S (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] SPACE (Sp) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER A (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER R (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER E (Lower) × [5.0] WORD JOINER (Format_FE) × [5.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 2060 × 5B57 × 2060 × 002E × 2060 ÷ 5B57 × 2060 × 2060 ÷ # ÷ [0.2] WORD JOINER (Format_FE) × [998.0] CJK UNIFIED IDEOGRAPH-5B57 (OLetter) × [5.0] WORD JOINER (Format_FE) × [998.0] FULL STOP (ATerm) × [5.0] WORD JOINER (Format_FE) ÷ [11.0] CJK UNIFIED IDEOGRAPH-5B57 (OLetter) × [5.0] WORD JOINER (Format_FE) × [5.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 2060 × 0065 × 2060 × 0074 × 2060 × 0063 × 2060 × 002E × 2060 ÷ 5B83 × 2060 × 2060 ÷ # ÷ [0.2] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER E (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER T (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER C (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] FULL STOP (ATerm) × [5.0] WORD JOINER (Format_FE) ÷ [11.0] CJK UNIFIED IDEOGRAPH-5B83 (OLetter) × [5.0] WORD JOINER (Format_FE) × [5.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 2060 × 0065 × 2060 × 0074 × 2060 × 0063 × 2060 × 002E × 2060 × 3002 × 2060 × 2060 ÷ # ÷ [0.2] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER E (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER T (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] LATIN SMALL LETTER C (Lower) × [5.0] WORD JOINER (Format_FE) × [998.0] FULL STOP (ATerm) × [5.0] WORD JOINER (Format_FE) × [8.1] IDEOGRAPHIC FULL STOP (STerm) × [5.0] WORD JOINER (Format_FE) × [5.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 2060 × 5B57 × 2060 × 3002 × 2060 ÷ 5B83 × 2060 × 2060 ÷ # ÷ [0.2] WORD JOINER (Format_FE) × [998.0] CJK UNIFIED IDEOGRAPH-5B57 (OLetter) × [5.0] WORD JOINER (Format_FE) × [998.0] IDEOGRAPHIC FULL STOP (STerm) × [5.0] WORD JOINER (Format_FE) ÷ [11.0] CJK UNIFIED IDEOGRAPH-5B83 (OLetter) × [5.0] WORD JOINER (Format_FE) × [5.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 2060 × 0021 × 2060 × 0020 × 2060 × 0020 × 2060 × 2060 ÷ # ÷ [0.2] WORD JOINER (Format_FE) × [998.0] EXCLAMATION MARK (STerm) × [5.0] WORD JOINER (Format_FE) × [9.0] SPACE (Sp) × [5.0] WORD JOINER (Format_FE) × [10.0] SPACE (Sp) × [5.0] WORD JOINER (Format_FE) × [5.0] WORD JOINER (Format_FE) ÷ [0.3] +# +# Lines: 502 +# +# EOF diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/data/WordBreakTest.txt b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/data/WordBreakTest.txt new file mode 100644 index 0000000..facd892 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/data/WordBreakTest.txt @@ -0,0 +1,1851 @@ +# WordBreakTest-12.1.0.txt +# Date: 2019-03-10, 10:53:29 GMT +# © 2019 Unicode®, Inc. +# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. +# For terms of use, see http://www.unicode.org/terms_of_use.html +# +# Unicode Character Database +# For documentation, see http://www.unicode.org/reports/tr44/ +# +# Default Word_Break Test +# +# Format: +# (# )? +# contains hex Unicode code points, with +# ÷ wherever there is a break opportunity, and +# × wherever there is not. +# the format can change, but currently it shows: +# - the sample character name +# - (x) the Word_Break property value for the sample character +# - [x] the rule that determines whether there is a break or not, +# as listed in the Rules section of WordBreakTest.html +# +# These samples may be extended or changed in the future. +# +÷ 0001 ÷ 0001 ÷ # ÷ [0.2] (Other) ÷ [999.0] (Other) ÷ [0.3] +÷ 0001 × 0308 ÷ 0001 ÷ # ÷ [0.2] (Other) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 0001 ÷ 000D ÷ # ÷ [0.2] (Other) ÷ [3.2] (CR) ÷ [0.3] +÷ 0001 × 0308 ÷ 000D ÷ # ÷ [0.2] (Other) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 0001 ÷ 000A ÷ # ÷ [0.2] (Other) ÷ [3.2] (LF) ÷ [0.3] +÷ 0001 × 0308 ÷ 000A ÷ # ÷ [0.2] (Other) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 0001 ÷ 000B ÷ # ÷ [0.2] (Other) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0001 × 0308 ÷ 000B ÷ # ÷ [0.2] (Other) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0001 ÷ 3031 ÷ # ÷ [0.2] (Other) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0001 × 0308 ÷ 3031 ÷ # ÷ [0.2] (Other) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0001 ÷ 0041 ÷ # ÷ [0.2] (Other) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0001 × 0308 ÷ 0041 ÷ # ÷ [0.2] (Other) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0001 ÷ 003A ÷ # ÷ [0.2] (Other) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0001 × 0308 ÷ 003A ÷ # ÷ [0.2] (Other) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0001 ÷ 002C ÷ # ÷ [0.2] (Other) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0001 × 0308 ÷ 002C ÷ # ÷ [0.2] (Other) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0001 ÷ 002E ÷ # ÷ [0.2] (Other) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0001 × 0308 ÷ 002E ÷ # ÷ [0.2] (Other) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0001 ÷ 0030 ÷ # ÷ [0.2] (Other) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0001 × 0308 ÷ 0030 ÷ # ÷ [0.2] (Other) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0001 ÷ 005F ÷ # ÷ [0.2] (Other) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0001 × 0308 ÷ 005F ÷ # ÷ [0.2] (Other) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0001 ÷ 1F1E6 ÷ # ÷ [0.2] (Other) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0001 × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] (Other) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0001 ÷ 05D0 ÷ # ÷ [0.2] (Other) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0001 × 0308 ÷ 05D0 ÷ # ÷ [0.2] (Other) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0001 ÷ 0022 ÷ # ÷ [0.2] (Other) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0001 × 0308 ÷ 0022 ÷ # ÷ [0.2] (Other) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0001 ÷ 0027 ÷ # ÷ [0.2] (Other) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0001 × 0308 ÷ 0027 ÷ # ÷ [0.2] (Other) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0001 ÷ 231A ÷ # ÷ [0.2] (Other) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0001 × 0308 ÷ 231A ÷ # ÷ [0.2] (Other) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0001 ÷ 0020 ÷ # ÷ [0.2] (Other) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0001 × 0308 ÷ 0020 ÷ # ÷ [0.2] (Other) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0001 × 00AD ÷ # ÷ [0.2] (Other) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0001 × 0308 × 00AD ÷ # ÷ [0.2] (Other) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0001 × 0300 ÷ # ÷ [0.2] (Other) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0001 × 0308 × 0300 ÷ # ÷ [0.2] (Other) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0001 × 200D ÷ # ÷ [0.2] (Other) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0001 × 0308 × 200D ÷ # ÷ [0.2] (Other) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0001 ÷ 0061 × 2060 ÷ # ÷ [0.2] (Other) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0001 × 0308 ÷ 0061 × 2060 ÷ # ÷ [0.2] (Other) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0001 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] (Other) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0001 × 0308 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] (Other) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0001 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] (Other) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0001 × 0308 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] (Other) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0001 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] (Other) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0001 × 0308 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] (Other) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0001 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] (Other) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0001 × 0308 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] (Other) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0001 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] (Other) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0001 × 0308 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] (Other) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0001 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] (Other) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0001 × 0308 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] (Other) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0001 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] (Other) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0001 × 0308 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] (Other) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0001 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] (Other) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0001 × 0308 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] (Other) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 000D ÷ 0001 ÷ # ÷ [0.2] (CR) ÷ [3.1] (Other) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 0001 ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 000D ÷ 000D ÷ # ÷ [0.2] (CR) ÷ [3.1] (CR) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 000D ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 000D × 000A ÷ # ÷ [0.2] (CR) × [3.0] (LF) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 000A ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 000D ÷ 000B ÷ # ÷ [0.2] (CR) ÷ [3.1] (Newline) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 000B ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 000D ÷ 3031 ÷ # ÷ [0.2] (CR) ÷ [3.1] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 3031 ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 000D ÷ 0041 ÷ # ÷ [0.2] (CR) ÷ [3.1] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 0041 ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 000D ÷ 003A ÷ # ÷ [0.2] (CR) ÷ [3.1] COLON (MidLetter) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 003A ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 000D ÷ 002C ÷ # ÷ [0.2] (CR) ÷ [3.1] COMMA (MidNum) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 002C ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 000D ÷ 002E ÷ # ÷ [0.2] (CR) ÷ [3.1] FULL STOP (MidNumLet) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 002E ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 000D ÷ 0030 ÷ # ÷ [0.2] (CR) ÷ [3.1] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 0030 ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 000D ÷ 005F ÷ # ÷ [0.2] (CR) ÷ [3.1] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 005F ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 000D ÷ 1F1E6 ÷ # ÷ [0.2] (CR) ÷ [3.1] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 1F1E6 ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 000D ÷ 05D0 ÷ # ÷ [0.2] (CR) ÷ [3.1] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 05D0 ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 000D ÷ 0022 ÷ # ÷ [0.2] (CR) ÷ [3.1] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 0022 ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 000D ÷ 0027 ÷ # ÷ [0.2] (CR) ÷ [3.1] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 0027 ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 000D ÷ 231A ÷ # ÷ [0.2] (CR) ÷ [3.1] WATCH (ExtPict) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 231A ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 000D ÷ 0020 ÷ # ÷ [0.2] (CR) ÷ [3.1] SPACE (WSegSpace) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 0020 ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 000D ÷ 00AD ÷ # ÷ [0.2] (CR) ÷ [3.1] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 000D ÷ 0308 × 00AD ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 000D ÷ 0300 ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 000D ÷ 0308 × 0300 ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 000D ÷ 200D ÷ # ÷ [0.2] (CR) ÷ [3.1] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 000D ÷ 0308 × 200D ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 000D ÷ 0061 × 2060 ÷ # ÷ [0.2] (CR) ÷ [3.1] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 0061 × 2060 ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 000D ÷ 0061 ÷ 003A ÷ # ÷ [0.2] (CR) ÷ [3.1] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 000D ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] (CR) ÷ [3.1] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 000D ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] (CR) ÷ [3.1] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 000D ÷ 0061 ÷ 002C ÷ # ÷ [0.2] (CR) ÷ [3.1] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 000D ÷ 0031 ÷ 003A ÷ # ÷ [0.2] (CR) ÷ [3.1] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 000D ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] (CR) ÷ [3.1] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 000D ÷ 0031 ÷ 002C ÷ # ÷ [0.2] (CR) ÷ [3.1] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 000D ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] (CR) ÷ [3.1] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] (CR) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 000A ÷ 0001 ÷ # ÷ [0.2] (LF) ÷ [3.1] (Other) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 0001 ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 000A ÷ 000D ÷ # ÷ [0.2] (LF) ÷ [3.1] (CR) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 000D ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 000A ÷ 000A ÷ # ÷ [0.2] (LF) ÷ [3.1] (LF) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 000A ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 000A ÷ 000B ÷ # ÷ [0.2] (LF) ÷ [3.1] (Newline) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 000B ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 000A ÷ 3031 ÷ # ÷ [0.2] (LF) ÷ [3.1] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 3031 ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 000A ÷ 0041 ÷ # ÷ [0.2] (LF) ÷ [3.1] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 0041 ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 000A ÷ 003A ÷ # ÷ [0.2] (LF) ÷ [3.1] COLON (MidLetter) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 003A ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 000A ÷ 002C ÷ # ÷ [0.2] (LF) ÷ [3.1] COMMA (MidNum) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 002C ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 000A ÷ 002E ÷ # ÷ [0.2] (LF) ÷ [3.1] FULL STOP (MidNumLet) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 002E ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 000A ÷ 0030 ÷ # ÷ [0.2] (LF) ÷ [3.1] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 0030 ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 000A ÷ 005F ÷ # ÷ [0.2] (LF) ÷ [3.1] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 005F ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 000A ÷ 1F1E6 ÷ # ÷ [0.2] (LF) ÷ [3.1] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 1F1E6 ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 000A ÷ 05D0 ÷ # ÷ [0.2] (LF) ÷ [3.1] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 05D0 ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 000A ÷ 0022 ÷ # ÷ [0.2] (LF) ÷ [3.1] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 0022 ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 000A ÷ 0027 ÷ # ÷ [0.2] (LF) ÷ [3.1] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 0027 ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 000A ÷ 231A ÷ # ÷ [0.2] (LF) ÷ [3.1] WATCH (ExtPict) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 231A ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 000A ÷ 0020 ÷ # ÷ [0.2] (LF) ÷ [3.1] SPACE (WSegSpace) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 0020 ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 000A ÷ 00AD ÷ # ÷ [0.2] (LF) ÷ [3.1] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 000A ÷ 0308 × 00AD ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 000A ÷ 0300 ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 000A ÷ 0308 × 0300 ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 000A ÷ 200D ÷ # ÷ [0.2] (LF) ÷ [3.1] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 000A ÷ 0308 × 200D ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 000A ÷ 0061 × 2060 ÷ # ÷ [0.2] (LF) ÷ [3.1] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 0061 × 2060 ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 000A ÷ 0061 ÷ 003A ÷ # ÷ [0.2] (LF) ÷ [3.1] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 000A ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] (LF) ÷ [3.1] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 000A ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] (LF) ÷ [3.1] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 000A ÷ 0061 ÷ 002C ÷ # ÷ [0.2] (LF) ÷ [3.1] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 000A ÷ 0031 ÷ 003A ÷ # ÷ [0.2] (LF) ÷ [3.1] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 000A ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] (LF) ÷ [3.1] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 000A ÷ 0031 ÷ 002C ÷ # ÷ [0.2] (LF) ÷ [3.1] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 000A ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] (LF) ÷ [3.1] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 000B ÷ 0001 ÷ # ÷ [0.2] (Newline) ÷ [3.1] (Other) ÷ [0.3] +÷ 000B ÷ 0308 ÷ 0001 ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 000B ÷ 000D ÷ # ÷ [0.2] (Newline) ÷ [3.1] (CR) ÷ [0.3] +÷ 000B ÷ 0308 ÷ 000D ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 000B ÷ 000A ÷ # ÷ [0.2] (Newline) ÷ [3.1] (LF) ÷ [0.3] +÷ 000B ÷ 0308 ÷ 000A ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 000B ÷ 000B ÷ # ÷ [0.2] (Newline) ÷ [3.1] (Newline) ÷ [0.3] +÷ 000B ÷ 0308 ÷ 000B ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 000B ÷ 3031 ÷ # ÷ [0.2] (Newline) ÷ [3.1] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 000B ÷ 0308 ÷ 3031 ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 000B ÷ 0041 ÷ # ÷ [0.2] (Newline) ÷ [3.1] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 000B ÷ 0308 ÷ 0041 ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 000B ÷ 003A ÷ # ÷ [0.2] (Newline) ÷ [3.1] COLON (MidLetter) ÷ [0.3] +÷ 000B ÷ 0308 ÷ 003A ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 000B ÷ 002C ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMMA (MidNum) ÷ [0.3] +÷ 000B ÷ 0308 ÷ 002C ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 000B ÷ 002E ÷ # ÷ [0.2] (Newline) ÷ [3.1] FULL STOP (MidNumLet) ÷ [0.3] +÷ 000B ÷ 0308 ÷ 002E ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 000B ÷ 0030 ÷ # ÷ [0.2] (Newline) ÷ [3.1] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 000B ÷ 0308 ÷ 0030 ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 000B ÷ 005F ÷ # ÷ [0.2] (Newline) ÷ [3.1] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 000B ÷ 0308 ÷ 005F ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 000B ÷ 1F1E6 ÷ # ÷ [0.2] (Newline) ÷ [3.1] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 000B ÷ 0308 ÷ 1F1E6 ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 000B ÷ 05D0 ÷ # ÷ [0.2] (Newline) ÷ [3.1] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 000B ÷ 0308 ÷ 05D0 ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 000B ÷ 0022 ÷ # ÷ [0.2] (Newline) ÷ [3.1] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 000B ÷ 0308 ÷ 0022 ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 000B ÷ 0027 ÷ # ÷ [0.2] (Newline) ÷ [3.1] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 000B ÷ 0308 ÷ 0027 ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 000B ÷ 231A ÷ # ÷ [0.2] (Newline) ÷ [3.1] WATCH (ExtPict) ÷ [0.3] +÷ 000B ÷ 0308 ÷ 231A ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 000B ÷ 0020 ÷ # ÷ [0.2] (Newline) ÷ [3.1] SPACE (WSegSpace) ÷ [0.3] +÷ 000B ÷ 0308 ÷ 0020 ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 000B ÷ 00AD ÷ # ÷ [0.2] (Newline) ÷ [3.1] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 000B ÷ 0308 × 00AD ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 000B ÷ 0300 ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 000B ÷ 0308 × 0300 ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 000B ÷ 200D ÷ # ÷ [0.2] (Newline) ÷ [3.1] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 000B ÷ 0308 × 200D ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 000B ÷ 0061 × 2060 ÷ # ÷ [0.2] (Newline) ÷ [3.1] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 000B ÷ 0308 ÷ 0061 × 2060 ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 000B ÷ 0061 ÷ 003A ÷ # ÷ [0.2] (Newline) ÷ [3.1] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 000B ÷ 0308 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 000B ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] (Newline) ÷ [3.1] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 000B ÷ 0308 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 000B ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] (Newline) ÷ [3.1] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 000B ÷ 0308 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 000B ÷ 0061 ÷ 002C ÷ # ÷ [0.2] (Newline) ÷ [3.1] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 000B ÷ 0308 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 000B ÷ 0031 ÷ 003A ÷ # ÷ [0.2] (Newline) ÷ [3.1] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 000B ÷ 0308 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 000B ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] (Newline) ÷ [3.1] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 000B ÷ 0308 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 000B ÷ 0031 ÷ 002C ÷ # ÷ [0.2] (Newline) ÷ [3.1] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 000B ÷ 0308 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 000B ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] (Newline) ÷ [3.1] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 000B ÷ 0308 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] (Newline) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 3031 ÷ 0001 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) ÷ [999.0] (Other) ÷ [0.3] +÷ 3031 × 0308 ÷ 0001 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 3031 ÷ 000D ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) ÷ [3.2] (CR) ÷ [0.3] +÷ 3031 × 0308 ÷ 000D ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 3031 ÷ 000A ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) ÷ [3.2] (LF) ÷ [0.3] +÷ 3031 × 0308 ÷ 000A ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 3031 ÷ 000B ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) ÷ [3.2] (Newline) ÷ [0.3] +÷ 3031 × 0308 ÷ 000B ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 3031 × 3031 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [13.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 3031 × 0308 × 3031 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING DIAERESIS (Extend_FE) × [13.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 3031 ÷ 0041 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 3031 × 0308 ÷ 0041 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 3031 ÷ 003A ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 3031 × 0308 ÷ 003A ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 3031 ÷ 002C ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 3031 × 0308 ÷ 002C ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 3031 ÷ 002E ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 3031 × 0308 ÷ 002E ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 3031 ÷ 0030 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 3031 × 0308 ÷ 0030 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 3031 × 005F ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [13.1] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 3031 × 0308 × 005F ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING DIAERESIS (Extend_FE) × [13.1] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 3031 ÷ 1F1E6 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 3031 × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 3031 ÷ 05D0 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 3031 × 0308 ÷ 05D0 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 3031 ÷ 0022 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 3031 × 0308 ÷ 0022 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 3031 ÷ 0027 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 3031 × 0308 ÷ 0027 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 3031 ÷ 231A ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 3031 × 0308 ÷ 231A ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 3031 ÷ 0020 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 3031 × 0308 ÷ 0020 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 3031 × 00AD ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 3031 × 0308 × 00AD ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 3031 × 0300 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 3031 × 0308 × 0300 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 3031 × 200D ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 3031 × 0308 × 200D ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 3031 ÷ 0061 × 2060 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 3031 × 0308 ÷ 0061 × 2060 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 3031 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 3031 × 0308 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 3031 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 3031 × 0308 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 3031 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 3031 × 0308 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 3031 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 3031 × 0308 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 3031 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 3031 × 0308 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 3031 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 3031 × 0308 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 3031 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 3031 × 0308 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 3031 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 3031 × 0308 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0041 ÷ 0001 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) ÷ [999.0] (Other) ÷ [0.3] +÷ 0041 × 0308 ÷ 0001 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 0041 ÷ 000D ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) ÷ [3.2] (CR) ÷ [0.3] +÷ 0041 × 0308 ÷ 000D ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 0041 ÷ 000A ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) ÷ [3.2] (LF) ÷ [0.3] +÷ 0041 × 0308 ÷ 000A ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 0041 ÷ 000B ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0041 × 0308 ÷ 000B ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0041 ÷ 3031 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0041 × 0308 ÷ 3031 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0041 × 0041 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [5.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0041 × 0308 × 0041 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [5.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0041 ÷ 003A ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0041 × 0308 ÷ 003A ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0041 ÷ 002C ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0041 × 0308 ÷ 002C ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0041 ÷ 002E ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0041 × 0308 ÷ 002E ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0041 × 0030 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [9.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0041 × 0308 × 0030 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [9.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0041 × 005F ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0041 × 0308 × 005F ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [13.1] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0041 ÷ 1F1E6 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0041 × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0041 × 05D0 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [5.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0041 × 0308 × 05D0 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [5.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0041 ÷ 0022 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0041 × 0308 ÷ 0022 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0041 ÷ 0027 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0041 × 0308 ÷ 0027 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0041 ÷ 231A ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0041 × 0308 ÷ 231A ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0041 ÷ 0020 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0041 × 0308 ÷ 0020 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0041 × 00AD ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0041 × 0308 × 00AD ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0041 × 0300 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0041 × 0308 × 0300 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0041 × 200D ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0041 × 0308 × 200D ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0041 × 0061 × 2060 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [5.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0041 × 0308 × 0061 × 2060 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [5.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0041 × 0061 ÷ 003A ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [5.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0041 × 0308 × 0061 ÷ 003A ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [5.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0041 × 0061 ÷ 0027 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [5.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0041 × 0308 × 0061 ÷ 0027 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [5.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0041 × 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [5.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0041 × 0308 × 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [5.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0041 × 0061 ÷ 002C ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [5.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0041 × 0308 × 0061 ÷ 002C ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [5.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0041 × 0031 ÷ 003A ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [9.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0041 × 0308 × 0031 ÷ 003A ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [9.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0041 × 0031 ÷ 0027 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [9.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0041 × 0308 × 0031 ÷ 0027 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [9.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0041 × 0031 ÷ 002C ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [9.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0041 × 0308 × 0031 ÷ 002C ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [9.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0041 × 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [9.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0041 × 0308 × 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [9.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 003A ÷ 0001 ÷ # ÷ [0.2] COLON (MidLetter) ÷ [999.0] (Other) ÷ [0.3] +÷ 003A × 0308 ÷ 0001 ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 003A ÷ 000D ÷ # ÷ [0.2] COLON (MidLetter) ÷ [3.2] (CR) ÷ [0.3] +÷ 003A × 0308 ÷ 000D ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 003A ÷ 000A ÷ # ÷ [0.2] COLON (MidLetter) ÷ [3.2] (LF) ÷ [0.3] +÷ 003A × 0308 ÷ 000A ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 003A ÷ 000B ÷ # ÷ [0.2] COLON (MidLetter) ÷ [3.2] (Newline) ÷ [0.3] +÷ 003A × 0308 ÷ 000B ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 003A ÷ 3031 ÷ # ÷ [0.2] COLON (MidLetter) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 003A × 0308 ÷ 3031 ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 003A ÷ 0041 ÷ # ÷ [0.2] COLON (MidLetter) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 003A × 0308 ÷ 0041 ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 003A ÷ 003A ÷ # ÷ [0.2] COLON (MidLetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 003A × 0308 ÷ 003A ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 003A ÷ 002C ÷ # ÷ [0.2] COLON (MidLetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 003A × 0308 ÷ 002C ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 003A ÷ 002E ÷ # ÷ [0.2] COLON (MidLetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 003A × 0308 ÷ 002E ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 003A ÷ 0030 ÷ # ÷ [0.2] COLON (MidLetter) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 003A × 0308 ÷ 0030 ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 003A ÷ 005F ÷ # ÷ [0.2] COLON (MidLetter) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 003A × 0308 ÷ 005F ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 003A ÷ 1F1E6 ÷ # ÷ [0.2] COLON (MidLetter) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 003A × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 003A ÷ 05D0 ÷ # ÷ [0.2] COLON (MidLetter) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 003A × 0308 ÷ 05D0 ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 003A ÷ 0022 ÷ # ÷ [0.2] COLON (MidLetter) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 003A × 0308 ÷ 0022 ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 003A ÷ 0027 ÷ # ÷ [0.2] COLON (MidLetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 003A × 0308 ÷ 0027 ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 003A ÷ 231A ÷ # ÷ [0.2] COLON (MidLetter) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 003A × 0308 ÷ 231A ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 003A ÷ 0020 ÷ # ÷ [0.2] COLON (MidLetter) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 003A × 0308 ÷ 0020 ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 003A × 00AD ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 003A × 0308 × 00AD ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 003A × 0300 ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 003A × 0308 × 0300 ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 003A × 200D ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 003A × 0308 × 200D ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 003A ÷ 0061 × 2060 ÷ # ÷ [0.2] COLON (MidLetter) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 003A × 0308 ÷ 0061 × 2060 ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 003A ÷ 0061 ÷ 003A ÷ # ÷ [0.2] COLON (MidLetter) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 003A × 0308 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 003A ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] COLON (MidLetter) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 003A × 0308 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 003A ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] COLON (MidLetter) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 003A × 0308 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 003A ÷ 0061 ÷ 002C ÷ # ÷ [0.2] COLON (MidLetter) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 003A × 0308 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 003A ÷ 0031 ÷ 003A ÷ # ÷ [0.2] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 003A × 0308 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 003A ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 003A × 0308 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 003A ÷ 0031 ÷ 002C ÷ # ÷ [0.2] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 003A × 0308 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 003A ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 003A × 0308 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 002C ÷ 0001 ÷ # ÷ [0.2] COMMA (MidNum) ÷ [999.0] (Other) ÷ [0.3] +÷ 002C × 0308 ÷ 0001 ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 002C ÷ 000D ÷ # ÷ [0.2] COMMA (MidNum) ÷ [3.2] (CR) ÷ [0.3] +÷ 002C × 0308 ÷ 000D ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 002C ÷ 000A ÷ # ÷ [0.2] COMMA (MidNum) ÷ [3.2] (LF) ÷ [0.3] +÷ 002C × 0308 ÷ 000A ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 002C ÷ 000B ÷ # ÷ [0.2] COMMA (MidNum) ÷ [3.2] (Newline) ÷ [0.3] +÷ 002C × 0308 ÷ 000B ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 002C ÷ 3031 ÷ # ÷ [0.2] COMMA (MidNum) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 002C × 0308 ÷ 3031 ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 002C ÷ 0041 ÷ # ÷ [0.2] COMMA (MidNum) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 002C × 0308 ÷ 0041 ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 002C ÷ 003A ÷ # ÷ [0.2] COMMA (MidNum) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 002C × 0308 ÷ 003A ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 002C ÷ 002C ÷ # ÷ [0.2] COMMA (MidNum) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 002C × 0308 ÷ 002C ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 002C ÷ 002E ÷ # ÷ [0.2] COMMA (MidNum) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 002C × 0308 ÷ 002E ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 002C ÷ 0030 ÷ # ÷ [0.2] COMMA (MidNum) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 002C × 0308 ÷ 0030 ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 002C ÷ 005F ÷ # ÷ [0.2] COMMA (MidNum) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 002C × 0308 ÷ 005F ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 002C ÷ 1F1E6 ÷ # ÷ [0.2] COMMA (MidNum) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 002C × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 002C ÷ 05D0 ÷ # ÷ [0.2] COMMA (MidNum) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 002C × 0308 ÷ 05D0 ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 002C ÷ 0022 ÷ # ÷ [0.2] COMMA (MidNum) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 002C × 0308 ÷ 0022 ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 002C ÷ 0027 ÷ # ÷ [0.2] COMMA (MidNum) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 002C × 0308 ÷ 0027 ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 002C ÷ 231A ÷ # ÷ [0.2] COMMA (MidNum) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 002C × 0308 ÷ 231A ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 002C ÷ 0020 ÷ # ÷ [0.2] COMMA (MidNum) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 002C × 0308 ÷ 0020 ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 002C × 00AD ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 002C × 0308 × 00AD ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 002C × 0300 ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 002C × 0308 × 0300 ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 002C × 200D ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 002C × 0308 × 200D ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 002C ÷ 0061 × 2060 ÷ # ÷ [0.2] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 002C × 0308 ÷ 0061 × 2060 ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 002C ÷ 0061 ÷ 003A ÷ # ÷ [0.2] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 002C × 0308 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 002C ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 002C × 0308 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 002C ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 002C × 0308 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 002C ÷ 0061 ÷ 002C ÷ # ÷ [0.2] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 002C × 0308 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 002C ÷ 0031 ÷ 003A ÷ # ÷ [0.2] COMMA (MidNum) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 002C × 0308 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 002C ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] COMMA (MidNum) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 002C × 0308 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 002C ÷ 0031 ÷ 002C ÷ # ÷ [0.2] COMMA (MidNum) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 002C × 0308 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 002C ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] COMMA (MidNum) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 002C × 0308 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 002E ÷ 0001 ÷ # ÷ [0.2] FULL STOP (MidNumLet) ÷ [999.0] (Other) ÷ [0.3] +÷ 002E × 0308 ÷ 0001 ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 002E ÷ 000D ÷ # ÷ [0.2] FULL STOP (MidNumLet) ÷ [3.2] (CR) ÷ [0.3] +÷ 002E × 0308 ÷ 000D ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 002E ÷ 000A ÷ # ÷ [0.2] FULL STOP (MidNumLet) ÷ [3.2] (LF) ÷ [0.3] +÷ 002E × 0308 ÷ 000A ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 002E ÷ 000B ÷ # ÷ [0.2] FULL STOP (MidNumLet) ÷ [3.2] (Newline) ÷ [0.3] +÷ 002E × 0308 ÷ 000B ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 002E ÷ 3031 ÷ # ÷ [0.2] FULL STOP (MidNumLet) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 002E × 0308 ÷ 3031 ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 002E ÷ 0041 ÷ # ÷ [0.2] FULL STOP (MidNumLet) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 002E × 0308 ÷ 0041 ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 002E ÷ 003A ÷ # ÷ [0.2] FULL STOP (MidNumLet) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 002E × 0308 ÷ 003A ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 002E ÷ 002C ÷ # ÷ [0.2] FULL STOP (MidNumLet) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 002E × 0308 ÷ 002C ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 002E ÷ 002E ÷ # ÷ [0.2] FULL STOP (MidNumLet) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 002E × 0308 ÷ 002E ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 002E ÷ 0030 ÷ # ÷ [0.2] FULL STOP (MidNumLet) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 002E × 0308 ÷ 0030 ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 002E ÷ 005F ÷ # ÷ [0.2] FULL STOP (MidNumLet) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 002E × 0308 ÷ 005F ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 002E ÷ 1F1E6 ÷ # ÷ [0.2] FULL STOP (MidNumLet) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 002E × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 002E ÷ 05D0 ÷ # ÷ [0.2] FULL STOP (MidNumLet) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 002E × 0308 ÷ 05D0 ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 002E ÷ 0022 ÷ # ÷ [0.2] FULL STOP (MidNumLet) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 002E × 0308 ÷ 0022 ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 002E ÷ 0027 ÷ # ÷ [0.2] FULL STOP (MidNumLet) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 002E × 0308 ÷ 0027 ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 002E ÷ 231A ÷ # ÷ [0.2] FULL STOP (MidNumLet) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 002E × 0308 ÷ 231A ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 002E ÷ 0020 ÷ # ÷ [0.2] FULL STOP (MidNumLet) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 002E × 0308 ÷ 0020 ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 002E × 00AD ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 002E × 0308 × 00AD ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 002E × 0300 ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 002E × 0308 × 0300 ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 002E × 200D ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 002E × 0308 × 200D ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 002E ÷ 0061 × 2060 ÷ # ÷ [0.2] FULL STOP (MidNumLet) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 002E × 0308 ÷ 0061 × 2060 ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 002E ÷ 0061 ÷ 003A ÷ # ÷ [0.2] FULL STOP (MidNumLet) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 002E × 0308 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 002E ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] FULL STOP (MidNumLet) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 002E × 0308 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 002E ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] FULL STOP (MidNumLet) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 002E × 0308 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 002E ÷ 0061 ÷ 002C ÷ # ÷ [0.2] FULL STOP (MidNumLet) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 002E × 0308 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 002E ÷ 0031 ÷ 003A ÷ # ÷ [0.2] FULL STOP (MidNumLet) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 002E × 0308 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 002E ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] FULL STOP (MidNumLet) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 002E × 0308 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 002E ÷ 0031 ÷ 002C ÷ # ÷ [0.2] FULL STOP (MidNumLet) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 002E × 0308 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 002E ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] FULL STOP (MidNumLet) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 002E × 0308 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] FULL STOP (MidNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0030 ÷ 0001 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) ÷ [999.0] (Other) ÷ [0.3] +÷ 0030 × 0308 ÷ 0001 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 0030 ÷ 000D ÷ # ÷ [0.2] DIGIT ZERO (Numeric) ÷ [3.2] (CR) ÷ [0.3] +÷ 0030 × 0308 ÷ 000D ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 0030 ÷ 000A ÷ # ÷ [0.2] DIGIT ZERO (Numeric) ÷ [3.2] (LF) ÷ [0.3] +÷ 0030 × 0308 ÷ 000A ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 0030 ÷ 000B ÷ # ÷ [0.2] DIGIT ZERO (Numeric) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0030 × 0308 ÷ 000B ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0030 ÷ 3031 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0030 × 0308 ÷ 3031 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0030 × 0041 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [10.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0030 × 0308 × 0041 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING DIAERESIS (Extend_FE) × [10.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0030 ÷ 003A ÷ # ÷ [0.2] DIGIT ZERO (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0030 × 0308 ÷ 003A ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0030 ÷ 002C ÷ # ÷ [0.2] DIGIT ZERO (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0030 × 0308 ÷ 002C ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0030 ÷ 002E ÷ # ÷ [0.2] DIGIT ZERO (Numeric) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0030 × 0308 ÷ 002E ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0030 × 0030 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [8.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0030 × 0308 × 0030 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING DIAERESIS (Extend_FE) × [8.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0030 × 005F ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [13.1] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0030 × 0308 × 005F ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING DIAERESIS (Extend_FE) × [13.1] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0030 ÷ 1F1E6 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0030 × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0030 × 05D0 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [10.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0030 × 0308 × 05D0 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING DIAERESIS (Extend_FE) × [10.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0030 ÷ 0022 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0030 × 0308 ÷ 0022 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0030 ÷ 0027 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0030 × 0308 ÷ 0027 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0030 ÷ 231A ÷ # ÷ [0.2] DIGIT ZERO (Numeric) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0030 × 0308 ÷ 231A ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0030 ÷ 0020 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0030 × 0308 ÷ 0020 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0030 × 00AD ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0030 × 0308 × 00AD ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0030 × 0300 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0030 × 0308 × 0300 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0030 × 200D ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0030 × 0308 × 200D ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0030 × 0061 × 2060 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [10.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0030 × 0308 × 0061 × 2060 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING DIAERESIS (Extend_FE) × [10.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0030 × 0061 ÷ 003A ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [10.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0030 × 0308 × 0061 ÷ 003A ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING DIAERESIS (Extend_FE) × [10.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0030 × 0061 ÷ 0027 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [10.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0030 × 0308 × 0061 ÷ 0027 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING DIAERESIS (Extend_FE) × [10.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0030 × 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [10.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0030 × 0308 × 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING DIAERESIS (Extend_FE) × [10.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0030 × 0061 ÷ 002C ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [10.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0030 × 0308 × 0061 ÷ 002C ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING DIAERESIS (Extend_FE) × [10.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0030 × 0031 ÷ 003A ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [8.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0030 × 0308 × 0031 ÷ 003A ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING DIAERESIS (Extend_FE) × [8.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0030 × 0031 ÷ 0027 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [8.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0030 × 0308 × 0031 ÷ 0027 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING DIAERESIS (Extend_FE) × [8.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0030 × 0031 ÷ 002C ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [8.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0030 × 0308 × 0031 ÷ 002C ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING DIAERESIS (Extend_FE) × [8.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0030 × 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [8.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0030 × 0308 × 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [4.0] COMBINING DIAERESIS (Extend_FE) × [8.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 005F ÷ 0001 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) ÷ [999.0] (Other) ÷ [0.3] +÷ 005F × 0308 ÷ 0001 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 005F ÷ 000D ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) ÷ [3.2] (CR) ÷ [0.3] +÷ 005F × 0308 ÷ 000D ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 005F ÷ 000A ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) ÷ [3.2] (LF) ÷ [0.3] +÷ 005F × 0308 ÷ 000A ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 005F ÷ 000B ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) ÷ [3.2] (Newline) ÷ [0.3] +÷ 005F × 0308 ÷ 000B ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 005F × 3031 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [13.2] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 005F × 0308 × 3031 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) × [13.2] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 005F × 0041 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [13.2] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 005F × 0308 × 0041 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) × [13.2] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 005F ÷ 003A ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 005F × 0308 ÷ 003A ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 005F ÷ 002C ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 005F × 0308 ÷ 002C ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 005F ÷ 002E ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 005F × 0308 ÷ 002E ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 005F × 0030 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [13.2] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 005F × 0308 × 0030 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) × [13.2] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 005F × 005F ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [13.1] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 005F × 0308 × 005F ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) × [13.1] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 005F ÷ 1F1E6 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 005F × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 005F × 05D0 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [13.2] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 005F × 0308 × 05D0 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) × [13.2] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 005F ÷ 0022 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 005F × 0308 ÷ 0022 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 005F ÷ 0027 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 005F × 0308 ÷ 0027 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 005F ÷ 231A ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 005F × 0308 ÷ 231A ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 005F ÷ 0020 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 005F × 0308 ÷ 0020 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 005F × 00AD ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 005F × 0308 × 00AD ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 005F × 0300 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 005F × 0308 × 0300 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 005F × 200D ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 005F × 0308 × 200D ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 005F × 0061 × 2060 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 005F × 0308 × 0061 × 2060 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) × [13.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 005F × 0061 ÷ 003A ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 005F × 0308 × 0061 ÷ 003A ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 005F × 0061 ÷ 0027 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 005F × 0308 × 0061 ÷ 0027 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 005F × 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 005F × 0308 × 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 005F × 0061 ÷ 002C ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 005F × 0308 × 0061 ÷ 002C ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 005F × 0031 ÷ 003A ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 005F × 0308 × 0031 ÷ 003A ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 005F × 0031 ÷ 0027 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 005F × 0308 × 0031 ÷ 0027 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 005F × 0031 ÷ 002C ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 005F × 0308 × 0031 ÷ 002C ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 005F × 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 005F × 0308 × 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] LOW LINE (ExtendNumLet) × [4.0] COMBINING DIAERESIS (Extend_FE) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 1F1E6 ÷ 0001 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] (Other) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 0001 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 1F1E6 ÷ 000D ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [3.2] (CR) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 000D ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 1F1E6 ÷ 000A ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [3.2] (LF) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 000A ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 1F1E6 ÷ 000B ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [3.2] (Newline) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 000B ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 1F1E6 ÷ 3031 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 3031 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 1F1E6 ÷ 0041 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 0041 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 1F1E6 ÷ 003A ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 003A ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 1F1E6 ÷ 002C ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 002C ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 1F1E6 ÷ 002E ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 002E ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 1F1E6 ÷ 0030 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 0030 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 1F1E6 ÷ 005F ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 005F ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 1F1E6 × 1F1E6 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [15.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 1F1E6 × 0308 × 1F1E6 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING DIAERESIS (Extend_FE) × [15.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 1F1E6 ÷ 05D0 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 05D0 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 1F1E6 ÷ 0022 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 0022 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 1F1E6 ÷ 0027 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 0027 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 1F1E6 ÷ 231A ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 231A ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 1F1E6 ÷ 0020 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 0020 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 1F1E6 × 00AD ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 1F1E6 × 0308 × 00AD ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 1F1E6 × 0300 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 1F1E6 × 0308 × 0300 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 1F1E6 × 200D ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 1F1E6 × 0308 × 200D ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 1F1E6 ÷ 0061 × 2060 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 0061 × 2060 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 1F1E6 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 1F1E6 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 1F1E6 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 1F1E6 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 1F1E6 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 1F1E6 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 1F1E6 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 1F1E6 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 05D0 ÷ 0001 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [999.0] (Other) ÷ [0.3] +÷ 05D0 × 0308 ÷ 0001 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 05D0 ÷ 000D ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [3.2] (CR) ÷ [0.3] +÷ 05D0 × 0308 ÷ 000D ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 05D0 ÷ 000A ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [3.2] (LF) ÷ [0.3] +÷ 05D0 × 0308 ÷ 000A ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 05D0 ÷ 000B ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [3.2] (Newline) ÷ [0.3] +÷ 05D0 × 0308 ÷ 000B ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 05D0 ÷ 3031 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 05D0 × 0308 ÷ 3031 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 05D0 × 0041 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [5.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 05D0 × 0308 × 0041 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [5.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 05D0 ÷ 003A ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 05D0 × 0308 ÷ 003A ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 05D0 ÷ 002C ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 05D0 × 0308 ÷ 002C ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 05D0 ÷ 002E ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 05D0 × 0308 ÷ 002E ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 05D0 × 0030 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [9.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 05D0 × 0308 × 0030 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [9.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 05D0 × 005F ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [13.1] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 05D0 × 0308 × 005F ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [13.1] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 05D0 ÷ 1F1E6 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 05D0 × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 05D0 × 05D0 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [5.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 05D0 × 0308 × 05D0 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [5.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 05D0 ÷ 0022 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 05D0 × 0308 ÷ 0022 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 05D0 × 0027 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [7.1] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 05D0 × 0308 × 0027 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [7.1] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 05D0 ÷ 231A ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 05D0 × 0308 ÷ 231A ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 05D0 ÷ 0020 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 05D0 × 0308 ÷ 0020 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 05D0 × 00AD ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 05D0 × 0308 × 00AD ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 05D0 × 0300 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 05D0 × 0308 × 0300 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 05D0 × 200D ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 05D0 × 0308 × 200D ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 05D0 × 0061 × 2060 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [5.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 05D0 × 0308 × 0061 × 2060 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [5.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 05D0 × 0061 ÷ 003A ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [5.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 05D0 × 0308 × 0061 ÷ 003A ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [5.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 05D0 × 0061 ÷ 0027 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [5.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 05D0 × 0308 × 0061 ÷ 0027 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [5.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 05D0 × 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [5.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 05D0 × 0308 × 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [5.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 05D0 × 0061 ÷ 002C ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [5.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 05D0 × 0308 × 0061 ÷ 002C ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [5.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 05D0 × 0031 ÷ 003A ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [9.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 05D0 × 0308 × 0031 ÷ 003A ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [9.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 05D0 × 0031 ÷ 0027 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [9.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 05D0 × 0308 × 0031 ÷ 0027 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [9.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 05D0 × 0031 ÷ 002C ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [9.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 05D0 × 0308 × 0031 ÷ 002C ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [9.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 05D0 × 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [9.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 05D0 × 0308 × 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [9.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0022 ÷ 0001 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) ÷ [999.0] (Other) ÷ [0.3] +÷ 0022 × 0308 ÷ 0001 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 0022 ÷ 000D ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) ÷ [3.2] (CR) ÷ [0.3] +÷ 0022 × 0308 ÷ 000D ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 0022 ÷ 000A ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) ÷ [3.2] (LF) ÷ [0.3] +÷ 0022 × 0308 ÷ 000A ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 0022 ÷ 000B ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0022 × 0308 ÷ 000B ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0022 ÷ 3031 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0022 × 0308 ÷ 3031 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0022 ÷ 0041 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0022 × 0308 ÷ 0041 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0022 ÷ 003A ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0022 × 0308 ÷ 003A ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0022 ÷ 002C ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0022 × 0308 ÷ 002C ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0022 ÷ 002E ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0022 × 0308 ÷ 002E ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0022 ÷ 0030 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0022 × 0308 ÷ 0030 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0022 ÷ 005F ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0022 × 0308 ÷ 005F ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0022 ÷ 1F1E6 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0022 × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0022 ÷ 05D0 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0022 × 0308 ÷ 05D0 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0022 ÷ 0022 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0022 × 0308 ÷ 0022 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0022 ÷ 0027 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0022 × 0308 ÷ 0027 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0022 ÷ 231A ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0022 × 0308 ÷ 231A ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0022 ÷ 0020 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0022 × 0308 ÷ 0020 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0022 × 00AD ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0022 × 0308 × 00AD ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0022 × 0300 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0022 × 0308 × 0300 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0022 × 200D ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0022 × 0308 × 200D ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0022 ÷ 0061 × 2060 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0022 × 0308 ÷ 0061 × 2060 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0022 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0022 × 0308 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0022 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0022 × 0308 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0022 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0022 × 0308 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0022 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0022 × 0308 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0022 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0022 × 0308 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0022 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0022 × 0308 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0022 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0022 × 0308 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0022 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0022 × 0308 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] QUOTATION MARK (Double_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0027 ÷ 0001 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) ÷ [999.0] (Other) ÷ [0.3] +÷ 0027 × 0308 ÷ 0001 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 0027 ÷ 000D ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) ÷ [3.2] (CR) ÷ [0.3] +÷ 0027 × 0308 ÷ 000D ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 0027 ÷ 000A ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) ÷ [3.2] (LF) ÷ [0.3] +÷ 0027 × 0308 ÷ 000A ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 0027 ÷ 000B ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0027 × 0308 ÷ 000B ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0027 ÷ 3031 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0027 × 0308 ÷ 3031 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0027 ÷ 0041 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0027 × 0308 ÷ 0041 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0027 ÷ 003A ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0027 × 0308 ÷ 003A ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0027 ÷ 002C ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0027 × 0308 ÷ 002C ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0027 ÷ 002E ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0027 × 0308 ÷ 002E ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0027 ÷ 0030 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0027 × 0308 ÷ 0030 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0027 ÷ 005F ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0027 × 0308 ÷ 005F ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0027 ÷ 1F1E6 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0027 × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0027 ÷ 05D0 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0027 × 0308 ÷ 05D0 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0027 ÷ 0022 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0027 × 0308 ÷ 0022 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0027 ÷ 0027 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0027 × 0308 ÷ 0027 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0027 ÷ 231A ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0027 × 0308 ÷ 231A ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0027 ÷ 0020 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0027 × 0308 ÷ 0020 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0027 × 00AD ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0027 × 0308 × 00AD ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0027 × 0300 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0027 × 0308 × 0300 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0027 × 200D ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0027 × 0308 × 200D ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0027 ÷ 0061 × 2060 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0027 × 0308 ÷ 0061 × 2060 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0027 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0027 × 0308 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0027 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0027 × 0308 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0027 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0027 × 0308 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0027 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0027 × 0308 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0027 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0027 × 0308 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0027 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0027 × 0308 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0027 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0027 × 0308 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0027 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0027 × 0308 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 231A ÷ 0001 ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] (Other) ÷ [0.3] +÷ 231A × 0308 ÷ 0001 ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 231A ÷ 000D ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [3.2] (CR) ÷ [0.3] +÷ 231A × 0308 ÷ 000D ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 231A ÷ 000A ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [3.2] (LF) ÷ [0.3] +÷ 231A × 0308 ÷ 000A ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 231A ÷ 000B ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [3.2] (Newline) ÷ [0.3] +÷ 231A × 0308 ÷ 000B ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 231A ÷ 3031 ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 231A × 0308 ÷ 3031 ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 231A ÷ 0041 ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 231A × 0308 ÷ 0041 ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 231A ÷ 003A ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 231A × 0308 ÷ 003A ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 231A ÷ 002C ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 231A × 0308 ÷ 002C ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 231A ÷ 002E ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 231A × 0308 ÷ 002E ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 231A ÷ 0030 ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 231A × 0308 ÷ 0030 ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 231A ÷ 005F ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 231A × 0308 ÷ 005F ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 231A ÷ 1F1E6 ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 231A × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 231A ÷ 05D0 ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 231A × 0308 ÷ 05D0 ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 231A ÷ 0022 ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 231A × 0308 ÷ 0022 ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 231A ÷ 0027 ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 231A × 0308 ÷ 0027 ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 231A ÷ 231A ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 231A × 0308 ÷ 231A ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 231A ÷ 0020 ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 231A × 0308 ÷ 0020 ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 231A × 00AD ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 231A × 0308 × 00AD ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 231A × 0300 ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 231A × 0308 × 0300 ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 231A × 200D ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 231A × 0308 × 200D ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 231A ÷ 0061 × 2060 ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 231A × 0308 ÷ 0061 × 2060 ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 231A ÷ 0061 ÷ 003A ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 231A × 0308 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 231A ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 231A × 0308 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 231A ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 231A × 0308 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 231A ÷ 0061 ÷ 002C ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 231A × 0308 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 231A ÷ 0031 ÷ 003A ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 231A × 0308 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 231A ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 231A × 0308 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 231A ÷ 0031 ÷ 002C ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 231A × 0308 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 231A ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 231A × 0308 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] WATCH (ExtPict) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0020 ÷ 0001 ÷ # ÷ [0.2] SPACE (WSegSpace) ÷ [999.0] (Other) ÷ [0.3] +÷ 0020 × 0308 ÷ 0001 ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 0020 ÷ 000D ÷ # ÷ [0.2] SPACE (WSegSpace) ÷ [3.2] (CR) ÷ [0.3] +÷ 0020 × 0308 ÷ 000D ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 0020 ÷ 000A ÷ # ÷ [0.2] SPACE (WSegSpace) ÷ [3.2] (LF) ÷ [0.3] +÷ 0020 × 0308 ÷ 000A ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 0020 ÷ 000B ÷ # ÷ [0.2] SPACE (WSegSpace) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0020 × 0308 ÷ 000B ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0020 ÷ 3031 ÷ # ÷ [0.2] SPACE (WSegSpace) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0020 × 0308 ÷ 3031 ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0020 ÷ 0041 ÷ # ÷ [0.2] SPACE (WSegSpace) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0020 × 0308 ÷ 0041 ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0020 ÷ 003A ÷ # ÷ [0.2] SPACE (WSegSpace) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0020 × 0308 ÷ 003A ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0020 ÷ 002C ÷ # ÷ [0.2] SPACE (WSegSpace) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0020 × 0308 ÷ 002C ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0020 ÷ 002E ÷ # ÷ [0.2] SPACE (WSegSpace) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0020 × 0308 ÷ 002E ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0020 ÷ 0030 ÷ # ÷ [0.2] SPACE (WSegSpace) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0020 × 0308 ÷ 0030 ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0020 ÷ 005F ÷ # ÷ [0.2] SPACE (WSegSpace) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0020 × 0308 ÷ 005F ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0020 ÷ 1F1E6 ÷ # ÷ [0.2] SPACE (WSegSpace) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0020 × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0020 ÷ 05D0 ÷ # ÷ [0.2] SPACE (WSegSpace) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0020 × 0308 ÷ 05D0 ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0020 ÷ 0022 ÷ # ÷ [0.2] SPACE (WSegSpace) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0020 × 0308 ÷ 0022 ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0020 ÷ 0027 ÷ # ÷ [0.2] SPACE (WSegSpace) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0020 × 0308 ÷ 0027 ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0020 ÷ 231A ÷ # ÷ [0.2] SPACE (WSegSpace) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0020 × 0308 ÷ 231A ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0020 × 0020 ÷ # ÷ [0.2] SPACE (WSegSpace) × [3.4] SPACE (WSegSpace) ÷ [0.3] +÷ 0020 × 0308 ÷ 0020 ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0020 × 00AD ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0020 × 0308 × 00AD ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0020 × 0300 ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0020 × 0308 × 0300 ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0020 × 200D ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0020 × 0308 × 200D ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0020 ÷ 0061 × 2060 ÷ # ÷ [0.2] SPACE (WSegSpace) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0020 × 0308 ÷ 0061 × 2060 ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0020 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] SPACE (WSegSpace) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0020 × 0308 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0020 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] SPACE (WSegSpace) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0020 × 0308 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0020 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] SPACE (WSegSpace) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0020 × 0308 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0020 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] SPACE (WSegSpace) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0020 × 0308 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0020 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] SPACE (WSegSpace) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0020 × 0308 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0020 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] SPACE (WSegSpace) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0020 × 0308 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0020 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] SPACE (WSegSpace) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0020 × 0308 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0020 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] SPACE (WSegSpace) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0020 × 0308 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 00AD ÷ 0001 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 00AD × 0308 ÷ 0001 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 00AD ÷ 000D ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 00AD × 0308 ÷ 000D ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 00AD ÷ 000A ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 00AD × 0308 ÷ 000A ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 00AD ÷ 000B ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 00AD × 0308 ÷ 000B ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 00AD ÷ 3031 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 00AD × 0308 ÷ 3031 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 00AD ÷ 0041 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 00AD × 0308 ÷ 0041 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 00AD ÷ 003A ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 00AD × 0308 ÷ 003A ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 00AD ÷ 002C ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 00AD × 0308 ÷ 002C ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 00AD ÷ 002E ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 00AD × 0308 ÷ 002E ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 00AD ÷ 0030 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 00AD × 0308 ÷ 0030 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 00AD ÷ 005F ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 00AD × 0308 ÷ 005F ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 00AD ÷ 1F1E6 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 00AD × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 00AD ÷ 05D0 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 00AD × 0308 ÷ 05D0 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 00AD ÷ 0022 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 00AD × 0308 ÷ 0022 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 00AD ÷ 0027 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 00AD × 0308 ÷ 0027 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 00AD ÷ 231A ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 00AD × 0308 ÷ 231A ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 00AD ÷ 0020 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 00AD × 0308 ÷ 0020 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 00AD × 00AD ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 00AD × 0308 × 00AD ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 00AD × 0300 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 00AD × 0308 × 0300 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 00AD × 200D ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 00AD × 0308 × 200D ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 00AD ÷ 0061 × 2060 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 00AD × 0308 ÷ 0061 × 2060 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 00AD ÷ 0061 ÷ 003A ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 00AD × 0308 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 00AD ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 00AD × 0308 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 00AD ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 00AD × 0308 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 00AD ÷ 0061 ÷ 002C ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 00AD × 0308 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 00AD ÷ 0031 ÷ 003A ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 00AD × 0308 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 00AD ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 00AD × 0308 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 00AD ÷ 0031 ÷ 002C ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 00AD × 0308 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 00AD ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 00AD × 0308 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] SOFT HYPHEN (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0300 ÷ 0001 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 0300 × 0308 ÷ 0001 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 0300 ÷ 000D ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 0300 × 0308 ÷ 000D ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 0300 ÷ 000A ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 0300 × 0308 ÷ 000A ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 0300 ÷ 000B ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0300 × 0308 ÷ 000B ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0300 ÷ 3031 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0300 × 0308 ÷ 3031 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0300 ÷ 0041 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0300 × 0308 ÷ 0041 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0300 ÷ 003A ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0300 × 0308 ÷ 003A ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0300 ÷ 002C ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0300 × 0308 ÷ 002C ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0300 ÷ 002E ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0300 × 0308 ÷ 002E ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0300 ÷ 0030 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0300 × 0308 ÷ 0030 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0300 ÷ 005F ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0300 × 0308 ÷ 005F ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0300 ÷ 1F1E6 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0300 × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0300 ÷ 05D0 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0300 × 0308 ÷ 05D0 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0300 ÷ 0022 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0300 × 0308 ÷ 0022 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0300 ÷ 0027 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0300 × 0308 ÷ 0027 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0300 ÷ 231A ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0300 × 0308 ÷ 231A ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0300 ÷ 0020 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0300 × 0308 ÷ 0020 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0300 × 00AD ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0300 × 0308 × 00AD ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0300 × 0300 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0300 × 0308 × 0300 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0300 × 200D ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0300 × 0308 × 200D ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0300 ÷ 0061 × 2060 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0300 × 0308 ÷ 0061 × 2060 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0300 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0300 × 0308 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0300 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0300 × 0308 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0300 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0300 × 0308 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0300 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0300 × 0308 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0300 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0300 × 0308 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0300 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0300 × 0308 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0300 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0300 × 0308 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0300 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0300 × 0308 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 200D ÷ 0001 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 200D × 0308 ÷ 0001 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 200D ÷ 000D ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 200D × 0308 ÷ 000D ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 200D ÷ 000A ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 200D × 0308 ÷ 000A ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 200D ÷ 000B ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 200D × 0308 ÷ 000B ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 200D ÷ 3031 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 200D × 0308 ÷ 3031 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 200D ÷ 0041 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 200D × 0308 ÷ 0041 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 200D ÷ 003A ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 200D × 0308 ÷ 003A ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 200D ÷ 002C ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 200D × 0308 ÷ 002C ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 200D ÷ 002E ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 200D × 0308 ÷ 002E ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 200D ÷ 0030 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 200D × 0308 ÷ 0030 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 200D ÷ 005F ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 200D × 0308 ÷ 005F ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 200D ÷ 1F1E6 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 200D × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 200D ÷ 05D0 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 200D × 0308 ÷ 05D0 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 200D ÷ 0022 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 200D × 0308 ÷ 0022 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 200D ÷ 0027 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 200D × 0308 ÷ 0027 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 200D × 231A ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [3.3] WATCH (ExtPict) ÷ [0.3] +÷ 200D × 0308 ÷ 231A ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 200D ÷ 0020 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 200D × 0308 ÷ 0020 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 200D × 00AD ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 200D × 0308 × 00AD ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 200D × 0300 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 200D × 0308 × 0300 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 200D × 200D ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 200D × 0308 × 200D ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 200D ÷ 0061 × 2060 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 200D × 0308 ÷ 0061 × 2060 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 200D ÷ 0061 ÷ 003A ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 200D × 0308 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 200D ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 200D × 0308 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 200D ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 200D × 0308 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 200D ÷ 0061 ÷ 002C ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 200D × 0308 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 200D ÷ 0031 ÷ 003A ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 200D × 0308 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 200D ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 200D × 0308 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 200D ÷ 0031 ÷ 002C ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 200D × 0308 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 200D ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 200D × 0308 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 × 2060 ÷ 0001 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 0061 × 2060 × 0308 ÷ 0001 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 0061 × 2060 ÷ 000D ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 0061 × 2060 × 0308 ÷ 000D ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 0061 × 2060 ÷ 000A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 0061 × 2060 × 0308 ÷ 000A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 0061 × 2060 ÷ 000B ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0061 × 2060 × 0308 ÷ 000B ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0061 × 2060 ÷ 3031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0061 × 2060 × 0308 ÷ 3031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0061 × 2060 × 0041 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [5.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0061 × 2060 × 0308 × 0041 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [5.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0061 × 2060 ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 × 2060 × 0308 ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 × 2060 ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 × 2060 × 0308 ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 × 2060 ÷ 002E ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0061 × 2060 × 0308 ÷ 002E ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0061 × 2060 × 0030 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [9.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0061 × 2060 × 0308 × 0030 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [9.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0061 × 2060 × 005F ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [13.1] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0061 × 2060 × 0308 × 005F ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [13.1] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0061 × 2060 ÷ 1F1E6 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0061 × 2060 × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0061 × 2060 × 05D0 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [5.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0061 × 2060 × 0308 × 05D0 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [5.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0061 × 2060 ÷ 0022 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0061 × 2060 × 0308 ÷ 0022 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0061 × 2060 ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 × 2060 × 0308 ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 × 2060 ÷ 231A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0061 × 2060 × 0308 ÷ 231A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0061 × 2060 ÷ 0020 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0061 × 2060 × 0308 ÷ 0020 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0061 × 2060 × 00AD ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0061 × 2060 × 0308 × 00AD ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0061 × 2060 × 0300 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0061 × 2060 × 0308 × 0300 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0061 × 2060 × 200D ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0061 × 2060 × 0308 × 200D ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0061 × 2060 × 0061 × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [5.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 × 2060 × 0308 × 0061 × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [5.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 × 2060 × 0061 ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [5.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 × 2060 × 0308 × 0061 ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [5.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 × 2060 × 0061 ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [5.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 × 2060 × 0308 × 0061 ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [5.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 × 2060 × 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [5.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 × 2060 × 0308 × 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [5.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 × 2060 × 0061 ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [5.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 × 2060 × 0308 × 0061 ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [5.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 × 2060 × 0031 ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [9.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 × 2060 × 0308 × 0031 ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [9.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 × 2060 × 0031 ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [9.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 × 2060 × 0308 × 0031 ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [9.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 × 2060 × 0031 ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [9.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 × 2060 × 0308 × 0031 ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [9.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 × 2060 × 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [9.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 × 2060 × 0308 × 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [9.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 ÷ 003A ÷ 0001 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] (Other) ÷ [0.3] +÷ 0061 ÷ 003A × 0308 ÷ 0001 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 0061 ÷ 003A ÷ 000D ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [3.2] (CR) ÷ [0.3] +÷ 0061 ÷ 003A × 0308 ÷ 000D ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 0061 ÷ 003A ÷ 000A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [3.2] (LF) ÷ [0.3] +÷ 0061 ÷ 003A × 0308 ÷ 000A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 0061 ÷ 003A ÷ 000B ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0061 ÷ 003A × 0308 ÷ 000B ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0061 ÷ 003A ÷ 3031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0061 ÷ 003A × 0308 ÷ 3031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0061 × 003A × 0041 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] COLON (MidLetter) × [7.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0061 × 003A × 0308 × 0041 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [7.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0061 ÷ 003A ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 ÷ 003A × 0308 ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 ÷ 003A ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 ÷ 003A × 0308 ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 ÷ 003A ÷ 002E ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0061 ÷ 003A × 0308 ÷ 002E ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0061 ÷ 003A ÷ 0030 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0061 ÷ 003A × 0308 ÷ 0030 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0061 ÷ 003A ÷ 005F ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0061 ÷ 003A × 0308 ÷ 005F ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0061 ÷ 003A ÷ 1F1E6 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0061 ÷ 003A × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0061 × 003A × 05D0 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] COLON (MidLetter) × [7.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0061 × 003A × 0308 × 05D0 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [7.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0061 ÷ 003A ÷ 0022 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0061 ÷ 003A × 0308 ÷ 0022 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0061 ÷ 003A ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 ÷ 003A × 0308 ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 ÷ 003A ÷ 231A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0061 ÷ 003A × 0308 ÷ 231A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0061 ÷ 003A ÷ 0020 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0061 ÷ 003A × 0308 ÷ 0020 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0061 ÷ 003A × 00AD ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0061 ÷ 003A × 0308 × 00AD ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0061 ÷ 003A × 0300 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0061 ÷ 003A × 0308 × 0300 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0061 ÷ 003A × 200D ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0061 ÷ 003A × 0308 × 200D ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0061 × 003A × 0061 × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] COLON (MidLetter) × [7.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 × 003A × 0308 × 0061 × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [7.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 × 003A × 0061 ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] COLON (MidLetter) × [7.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 × 003A × 0308 × 0061 ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [7.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 × 003A × 0061 ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] COLON (MidLetter) × [7.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 × 003A × 0308 × 0061 ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [7.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 × 003A × 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] COLON (MidLetter) × [7.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 × 003A × 0308 × 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [7.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 × 003A × 0061 ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] COLON (MidLetter) × [7.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 × 003A × 0308 × 0061 ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [7.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 ÷ 003A ÷ 0031 ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 ÷ 003A × 0308 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 ÷ 003A ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 ÷ 003A × 0308 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 ÷ 003A ÷ 0031 ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 ÷ 003A × 0308 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 ÷ 003A ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 ÷ 003A × 0308 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 ÷ 0027 ÷ 0001 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] (Other) ÷ [0.3] +÷ 0061 ÷ 0027 × 0308 ÷ 0001 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 0061 ÷ 0027 ÷ 000D ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [3.2] (CR) ÷ [0.3] +÷ 0061 ÷ 0027 × 0308 ÷ 000D ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 0061 ÷ 0027 ÷ 000A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [3.2] (LF) ÷ [0.3] +÷ 0061 ÷ 0027 × 0308 ÷ 000A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 0061 ÷ 0027 ÷ 000B ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0061 ÷ 0027 × 0308 ÷ 000B ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0061 ÷ 0027 ÷ 3031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0061 ÷ 0027 × 0308 ÷ 3031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0061 × 0027 × 0041 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] APOSTROPHE (Single_Quote) × [7.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0061 × 0027 × 0308 × 0041 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) × [7.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0061 ÷ 0027 ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 ÷ 0027 × 0308 ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 ÷ 0027 ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 ÷ 0027 × 0308 ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 ÷ 0027 ÷ 002E ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0061 ÷ 0027 × 0308 ÷ 002E ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0061 ÷ 0027 ÷ 0030 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0061 ÷ 0027 × 0308 ÷ 0030 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0061 ÷ 0027 ÷ 005F ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0061 ÷ 0027 × 0308 ÷ 005F ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0061 ÷ 0027 ÷ 1F1E6 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0061 ÷ 0027 × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0061 × 0027 × 05D0 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] APOSTROPHE (Single_Quote) × [7.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0061 × 0027 × 0308 × 05D0 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) × [7.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0061 ÷ 0027 ÷ 0022 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0061 ÷ 0027 × 0308 ÷ 0022 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0061 ÷ 0027 ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 ÷ 0027 × 0308 ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 ÷ 0027 ÷ 231A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0061 ÷ 0027 × 0308 ÷ 231A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0061 ÷ 0027 ÷ 0020 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0061 ÷ 0027 × 0308 ÷ 0020 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0061 ÷ 0027 × 00AD ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0061 ÷ 0027 × 0308 × 00AD ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0061 ÷ 0027 × 0300 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0061 ÷ 0027 × 0308 × 0300 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0061 ÷ 0027 × 200D ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0061 ÷ 0027 × 0308 × 200D ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0061 × 0027 × 0061 × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] APOSTROPHE (Single_Quote) × [7.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 × 0027 × 0308 × 0061 × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) × [7.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 × 0027 × 0061 ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] APOSTROPHE (Single_Quote) × [7.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 × 0027 × 0308 × 0061 ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) × [7.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 × 0027 × 0061 ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] APOSTROPHE (Single_Quote) × [7.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 × 0027 × 0308 × 0061 ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) × [7.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 × 0027 × 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] APOSTROPHE (Single_Quote) × [7.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 × 0027 × 0308 × 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) × [7.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 × 0027 × 0061 ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] APOSTROPHE (Single_Quote) × [7.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 × 0027 × 0308 × 0061 ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) × [7.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 ÷ 0027 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 ÷ 0027 × 0308 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 ÷ 0027 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 ÷ 0027 × 0308 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 ÷ 0027 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 ÷ 0027 × 0308 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 ÷ 0027 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 ÷ 0027 × 0308 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 ÷ 0001 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 × 0308 ÷ 0001 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 ÷ 000D ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 × 0308 ÷ 000D ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 ÷ 000A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 × 0308 ÷ 000A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 ÷ 000B ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 × 0308 ÷ 000B ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 ÷ 3031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 × 0308 ÷ 3031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0061 × 0027 × 2060 × 0041 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [7.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0061 × 0027 × 2060 × 0308 × 0041 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [7.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 × 0308 ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 × 0308 ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 ÷ 002E ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 × 0308 ÷ 002E ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 ÷ 0030 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 × 0308 ÷ 0030 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 ÷ 005F ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 × 0308 ÷ 005F ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 ÷ 1F1E6 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0061 × 0027 × 2060 × 05D0 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [7.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0061 × 0027 × 2060 × 0308 × 05D0 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [7.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 ÷ 0022 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 × 0308 ÷ 0022 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 × 0308 ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 ÷ 231A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 × 0308 ÷ 231A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 ÷ 0020 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 × 0308 ÷ 0020 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 × 00AD ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 × 0308 × 00AD ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 × 0300 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 × 0308 × 0300 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 × 200D ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 × 0308 × 200D ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0061 × 0027 × 2060 × 0061 × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [7.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 × 0027 × 2060 × 0308 × 0061 × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [7.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 × 0027 × 2060 × 0061 ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [7.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 × 0027 × 2060 × 0308 × 0061 ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [7.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 × 0027 × 2060 × 0061 ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [7.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 × 0027 × 2060 × 0308 × 0061 ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [7.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 × 0027 × 2060 × 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [7.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 × 0027 × 2060 × 0308 × 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [7.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 × 0027 × 2060 × 0061 ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [7.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 × 0027 × 2060 × 0308 × 0061 ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [6.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [7.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 × 0308 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 × 0308 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 × 0308 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 ÷ 0027 × 2060 × 0308 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 0001 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] (Other) ÷ [0.3] +÷ 0061 ÷ 002C × 0308 ÷ 0001 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 000D ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [3.2] (CR) ÷ [0.3] +÷ 0061 ÷ 002C × 0308 ÷ 000D ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 000A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [3.2] (LF) ÷ [0.3] +÷ 0061 ÷ 002C × 0308 ÷ 000A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 000B ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0061 ÷ 002C × 0308 ÷ 000B ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 3031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0061 ÷ 002C × 0308 ÷ 3031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 0041 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0061 ÷ 002C × 0308 ÷ 0041 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 ÷ 002C × 0308 ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 ÷ 002C × 0308 ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 002E ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0061 ÷ 002C × 0308 ÷ 002E ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 0030 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0061 ÷ 002C × 0308 ÷ 0030 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 005F ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0061 ÷ 002C × 0308 ÷ 005F ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 1F1E6 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0061 ÷ 002C × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 05D0 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0061 ÷ 002C × 0308 ÷ 05D0 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 0022 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0061 ÷ 002C × 0308 ÷ 0022 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 ÷ 002C × 0308 ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 231A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0061 ÷ 002C × 0308 ÷ 231A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 0020 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0061 ÷ 002C × 0308 ÷ 0020 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0061 ÷ 002C × 00AD ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0061 ÷ 002C × 0308 × 00AD ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0061 ÷ 002C × 0300 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0061 ÷ 002C × 0308 × 0300 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0061 ÷ 002C × 200D ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0061 ÷ 002C × 0308 × 200D ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 0061 × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 ÷ 002C × 0308 ÷ 0061 × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 0061 ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 ÷ 002C × 0308 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 ÷ 002C × 0308 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 ÷ 002C × 0308 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 0061 ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 ÷ 002C × 0308 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 0031 ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 ÷ 002C × 0308 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 ÷ 002C × 0308 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 0031 ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 ÷ 002C × 0308 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0061 ÷ 002C × 0308 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 0001 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] (Other) ÷ [0.3] +÷ 0031 ÷ 003A × 0308 ÷ 0001 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 000D ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [3.2] (CR) ÷ [0.3] +÷ 0031 ÷ 003A × 0308 ÷ 000D ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 000A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [3.2] (LF) ÷ [0.3] +÷ 0031 ÷ 003A × 0308 ÷ 000A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 000B ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0031 ÷ 003A × 0308 ÷ 000B ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 3031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0031 ÷ 003A × 0308 ÷ 3031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 0041 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0031 ÷ 003A × 0308 ÷ 0041 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 003A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0031 ÷ 003A × 0308 ÷ 003A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 002C ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0031 ÷ 003A × 0308 ÷ 002C ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 002E ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0031 ÷ 003A × 0308 ÷ 002E ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 0030 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0031 ÷ 003A × 0308 ÷ 0030 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 005F ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0031 ÷ 003A × 0308 ÷ 005F ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 1F1E6 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0031 ÷ 003A × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 05D0 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0031 ÷ 003A × 0308 ÷ 05D0 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 0022 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0031 ÷ 003A × 0308 ÷ 0022 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 0027 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0031 ÷ 003A × 0308 ÷ 0027 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 231A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0031 ÷ 003A × 0308 ÷ 231A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 0020 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0031 ÷ 003A × 0308 ÷ 0020 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0031 ÷ 003A × 00AD ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0031 ÷ 003A × 0308 × 00AD ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0031 ÷ 003A × 0300 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0031 ÷ 003A × 0308 × 0300 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0031 ÷ 003A × 200D ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0031 ÷ 003A × 0308 × 200D ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 0061 × 2060 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0031 ÷ 003A × 0308 ÷ 0061 × 2060 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 0061 ÷ 003A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0031 ÷ 003A × 0308 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0031 ÷ 003A × 0308 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0031 ÷ 003A × 0308 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 0061 ÷ 002C ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0031 ÷ 003A × 0308 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 0031 ÷ 003A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0031 ÷ 003A × 0308 ÷ 0031 ÷ 003A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0031 ÷ 003A × 0308 ÷ 0031 ÷ 0027 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 0031 ÷ 002C ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0031 ÷ 003A × 0308 ÷ 0031 ÷ 002C ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0031 ÷ 003A × 0308 ÷ 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0031 ÷ 0027 ÷ 0001 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] (Other) ÷ [0.3] +÷ 0031 ÷ 0027 × 0308 ÷ 0001 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 0031 ÷ 0027 ÷ 000D ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [3.2] (CR) ÷ [0.3] +÷ 0031 ÷ 0027 × 0308 ÷ 000D ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 0031 ÷ 0027 ÷ 000A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [3.2] (LF) ÷ [0.3] +÷ 0031 ÷ 0027 × 0308 ÷ 000A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 0031 ÷ 0027 ÷ 000B ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0031 ÷ 0027 × 0308 ÷ 000B ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0031 ÷ 0027 ÷ 3031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0031 ÷ 0027 × 0308 ÷ 3031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0031 ÷ 0027 ÷ 0041 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0031 ÷ 0027 × 0308 ÷ 0041 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0031 ÷ 0027 ÷ 003A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0031 ÷ 0027 × 0308 ÷ 003A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0031 ÷ 0027 ÷ 002C ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0031 ÷ 0027 × 0308 ÷ 002C ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0031 ÷ 0027 ÷ 002E ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0031 ÷ 0027 × 0308 ÷ 002E ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0031 × 0027 × 0030 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] APOSTROPHE (Single_Quote) × [11.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0031 × 0027 × 0308 × 0030 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) × [11.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0031 ÷ 0027 ÷ 005F ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0031 ÷ 0027 × 0308 ÷ 005F ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0031 ÷ 0027 ÷ 1F1E6 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0031 ÷ 0027 × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0031 ÷ 0027 ÷ 05D0 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0031 ÷ 0027 × 0308 ÷ 05D0 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0031 ÷ 0027 ÷ 0022 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0031 ÷ 0027 × 0308 ÷ 0022 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0031 ÷ 0027 ÷ 0027 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0031 ÷ 0027 × 0308 ÷ 0027 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0031 ÷ 0027 ÷ 231A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0031 ÷ 0027 × 0308 ÷ 231A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0031 ÷ 0027 ÷ 0020 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0031 ÷ 0027 × 0308 ÷ 0020 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0031 ÷ 0027 × 00AD ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0031 ÷ 0027 × 0308 × 00AD ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0031 ÷ 0027 × 0300 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0031 ÷ 0027 × 0308 × 0300 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0031 ÷ 0027 × 200D ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0031 ÷ 0027 × 0308 × 200D ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0031 ÷ 0027 ÷ 0061 × 2060 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0031 ÷ 0027 × 0308 ÷ 0061 × 2060 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0031 ÷ 0027 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0031 ÷ 0027 × 0308 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0031 ÷ 0027 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0031 ÷ 0027 × 0308 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0031 ÷ 0027 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0031 ÷ 0027 × 0308 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0031 ÷ 0027 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0031 ÷ 0027 × 0308 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0031 × 0027 × 0031 ÷ 003A ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] APOSTROPHE (Single_Quote) × [11.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0031 × 0027 × 0308 × 0031 ÷ 003A ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) × [11.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0031 × 0027 × 0031 ÷ 0027 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] APOSTROPHE (Single_Quote) × [11.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0031 × 0027 × 0308 × 0031 ÷ 0027 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) × [11.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0031 × 0027 × 0031 ÷ 002C ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] APOSTROPHE (Single_Quote) × [11.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0031 × 0027 × 0308 × 0031 ÷ 002C ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) × [11.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0031 × 0027 × 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] APOSTROPHE (Single_Quote) × [11.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0031 × 0027 × 0308 × 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] APOSTROPHE (Single_Quote) × [4.0] COMBINING DIAERESIS (Extend_FE) × [11.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0031 ÷ 002C ÷ 0001 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] (Other) ÷ [0.3] +÷ 0031 ÷ 002C × 0308 ÷ 0001 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 0031 ÷ 002C ÷ 000D ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [3.2] (CR) ÷ [0.3] +÷ 0031 ÷ 002C × 0308 ÷ 000D ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 0031 ÷ 002C ÷ 000A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [3.2] (LF) ÷ [0.3] +÷ 0031 ÷ 002C × 0308 ÷ 000A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 0031 ÷ 002C ÷ 000B ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0031 ÷ 002C × 0308 ÷ 000B ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0031 ÷ 002C ÷ 3031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0031 ÷ 002C × 0308 ÷ 3031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0031 ÷ 002C ÷ 0041 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0031 ÷ 002C × 0308 ÷ 0041 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0031 ÷ 002C ÷ 003A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0031 ÷ 002C × 0308 ÷ 003A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0031 ÷ 002C ÷ 002C ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0031 ÷ 002C × 0308 ÷ 002C ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0031 ÷ 002C ÷ 002E ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0031 ÷ 002C × 0308 ÷ 002E ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0031 × 002C × 0030 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] COMMA (MidNum) × [11.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0031 × 002C × 0308 × 0030 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) × [11.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0031 ÷ 002C ÷ 005F ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0031 ÷ 002C × 0308 ÷ 005F ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0031 ÷ 002C ÷ 1F1E6 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0031 ÷ 002C × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0031 ÷ 002C ÷ 05D0 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0031 ÷ 002C × 0308 ÷ 05D0 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0031 ÷ 002C ÷ 0022 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0031 ÷ 002C × 0308 ÷ 0022 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0031 ÷ 002C ÷ 0027 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0031 ÷ 002C × 0308 ÷ 0027 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0031 ÷ 002C ÷ 231A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0031 ÷ 002C × 0308 ÷ 231A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0031 ÷ 002C ÷ 0020 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0031 ÷ 002C × 0308 ÷ 0020 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0031 ÷ 002C × 00AD ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0031 ÷ 002C × 0308 × 00AD ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0031 ÷ 002C × 0300 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0031 ÷ 002C × 0308 × 0300 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0031 ÷ 002C × 200D ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0031 ÷ 002C × 0308 × 200D ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0031 ÷ 002C ÷ 0061 × 2060 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0031 ÷ 002C × 0308 ÷ 0061 × 2060 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0031 ÷ 002C ÷ 0061 ÷ 003A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0031 ÷ 002C × 0308 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0031 ÷ 002C ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0031 ÷ 002C × 0308 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0031 ÷ 002C ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0031 ÷ 002C × 0308 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0031 ÷ 002C ÷ 0061 ÷ 002C ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0031 ÷ 002C × 0308 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0031 × 002C × 0031 ÷ 003A ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] COMMA (MidNum) × [11.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0031 × 002C × 0308 × 0031 ÷ 003A ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) × [11.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0031 × 002C × 0031 ÷ 0027 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] COMMA (MidNum) × [11.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0031 × 002C × 0308 × 0031 ÷ 0027 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) × [11.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0031 × 002C × 0031 ÷ 002C ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] COMMA (MidNum) × [11.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0031 × 002C × 0308 × 0031 ÷ 002C ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) × [11.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0031 × 002C × 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] COMMA (MidNum) × [11.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0031 × 002C × 0308 × 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] COMMA (MidNum) × [4.0] COMBINING DIAERESIS (Extend_FE) × [11.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 ÷ 0001 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 × 0308 ÷ 0001 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] (Other) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 ÷ 000D ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 × 0308 ÷ 000D ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (CR) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 ÷ 000A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 × 0308 ÷ 000A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (LF) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 ÷ 000B ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 × 0308 ÷ 000B ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [3.2] (Newline) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 ÷ 3031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 × 0308 ÷ 3031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 ÷ 0041 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 × 0308 ÷ 0041 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 ÷ 003A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 × 0308 ÷ 003A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 ÷ 002C ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 × 0308 ÷ 002C ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 ÷ 002E ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 × 0308 ÷ 002E ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] FULL STOP (MidNumLet) ÷ [0.3] +÷ 0031 × 002E × 2060 × 0030 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [11.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0031 × 002E × 2060 × 0308 × 0030 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [11.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 ÷ 005F ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 × 0308 ÷ 005F ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 ÷ 1F1E6 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 ÷ 05D0 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 × 0308 ÷ 05D0 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 ÷ 0022 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 × 0308 ÷ 0022 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] QUOTATION MARK (Double_Quote) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 ÷ 0027 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 × 0308 ÷ 0027 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 ÷ 231A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 × 0308 ÷ 231A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 ÷ 0020 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 × 0308 ÷ 0020 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 × 00AD ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 × 0308 × 00AD ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] SOFT HYPHEN (Format_FE) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 × 0300 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 × 0308 × 0300 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] COMBINING GRAVE ACCENT (Extend_FE) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 × 200D ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 × 0308 × 200D ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 ÷ 0061 × 2060 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 × 0308 ÷ 0061 × 2060 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 × 0308 ÷ 0061 ÷ 003A ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 × 0308 ÷ 0061 ÷ 0027 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 × 0308 ÷ 0061 ÷ 0027 × 2060 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] APOSTROPHE (Single_Quote) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0031 ÷ 002E × 2060 × 0308 ÷ 0061 ÷ 002C ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0031 × 002E × 2060 × 0031 ÷ 003A ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [11.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0031 × 002E × 2060 × 0308 × 0031 ÷ 003A ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [11.0] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [0.3] +÷ 0031 × 002E × 2060 × 0031 ÷ 0027 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [11.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0031 × 002E × 2060 × 0308 × 0031 ÷ 0027 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [11.0] DIGIT ONE (Numeric) ÷ [999.0] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 0031 × 002E × 2060 × 0031 ÷ 002C ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [11.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0031 × 002E × 2060 × 0308 × 0031 ÷ 002C ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [11.0] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [0.3] +÷ 0031 × 002E × 2060 × 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [11.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 0031 × 002E × 2060 × 0308 × 0031 ÷ 002E × 2060 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [12.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [11.0] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) × [4.0] WORD JOINER (Format_FE) ÷ [0.3] +÷ 000D × 000A ÷ 0061 ÷ 000A ÷ 0308 ÷ # ÷ [0.2] (CR) × [3.0] (LF) ÷ [3.1] LATIN SMALL LETTER A (ALetter) ÷ [3.2] (LF) ÷ [3.1] COMBINING DIAERESIS (Extend_FE) ÷ [0.3] +÷ 0061 × 0308 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) ÷ [0.3] +÷ 0020 × 200D ÷ 0646 ÷ # ÷ [0.2] SPACE (WSegSpace) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [999.0] ARABIC LETTER NOON (ALetter) ÷ [0.3] +÷ 0646 × 200D ÷ 0020 ÷ # ÷ [0.2] ARABIC LETTER NOON (ALetter) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [999.0] SPACE (WSegSpace) ÷ [0.3] +÷ 0041 × 0041 × 0041 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [5.0] LATIN CAPITAL LETTER A (ALetter) × [5.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0041 × 003A × 0041 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [6.0] COLON (MidLetter) × [7.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0041 ÷ 003A ÷ 003A ÷ 0041 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 05D0 × 0027 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [7.1] APOSTROPHE (Single_Quote) ÷ [0.3] +÷ 05D0 × 0022 × 05D0 ÷ # ÷ [0.2] HEBREW LETTER ALEF (Hebrew_Letter) × [7.2] QUOTATION MARK (Double_Quote) × [7.3] HEBREW LETTER ALEF (Hebrew_Letter) ÷ [0.3] +÷ 0041 × 0030 × 0030 × 0041 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [9.0] DIGIT ZERO (Numeric) × [8.0] DIGIT ZERO (Numeric) × [10.0] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 0030 × 002C × 0030 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) × [12.0] COMMA (MidNum) × [11.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 0030 ÷ 002C ÷ 002C ÷ 0030 ÷ # ÷ [0.2] DIGIT ZERO (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] COMMA (MidNum) ÷ [999.0] DIGIT ZERO (Numeric) ÷ [0.3] +÷ 3031 × 3031 ÷ # ÷ [0.2] VERTICAL KANA REPEAT MARK (Katakana) × [13.0] VERTICAL KANA REPEAT MARK (Katakana) ÷ [0.3] +÷ 0041 × 005F × 0030 × 005F × 3031 × 005F ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ZERO (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] VERTICAL KANA REPEAT MARK (Katakana) × [13.1] LOW LINE (ExtendNumLet) ÷ [0.3] +÷ 0041 × 005F × 005F × 0041 ÷ # ÷ [0.2] LATIN CAPITAL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN CAPITAL LETTER A (ALetter) ÷ [0.3] +÷ 1F1E6 × 1F1E7 ÷ 1F1E8 ÷ 0062 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [15.0] REGIONAL INDICATOR SYMBOL LETTER B (RI) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER C (RI) ÷ [999.0] LATIN SMALL LETTER B (ALetter) ÷ [0.3] +÷ 0061 ÷ 1F1E6 × 1F1E7 ÷ 1F1E8 ÷ 0062 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [16.0] REGIONAL INDICATOR SYMBOL LETTER B (RI) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER C (RI) ÷ [999.0] LATIN SMALL LETTER B (ALetter) ÷ [0.3] +÷ 0061 ÷ 1F1E6 × 1F1E7 × 200D ÷ 1F1E8 ÷ 0062 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [16.0] REGIONAL INDICATOR SYMBOL LETTER B (RI) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER C (RI) ÷ [999.0] LATIN SMALL LETTER B (ALetter) ÷ [0.3] +÷ 0061 ÷ 1F1E6 × 200D × 1F1E7 ÷ 1F1E8 ÷ 0062 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) × [16.0] REGIONAL INDICATOR SYMBOL LETTER B (RI) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER C (RI) ÷ [999.0] LATIN SMALL LETTER B (ALetter) ÷ [0.3] +÷ 0061 ÷ 1F1E6 × 1F1E7 ÷ 1F1E8 × 1F1E9 ÷ 0062 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [16.0] REGIONAL INDICATOR SYMBOL LETTER B (RI) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER C (RI) × [16.0] REGIONAL INDICATOR SYMBOL LETTER D (RI) ÷ [999.0] LATIN SMALL LETTER B (ALetter) ÷ [0.3] +÷ 1F476 × 1F3FF ÷ 1F476 ÷ # ÷ [0.2] BABY (ExtPict) × [4.0] EMOJI MODIFIER FITZPATRICK TYPE-6 (Extend_FE) ÷ [999.0] BABY (ExtPict) ÷ [0.3] +÷ 1F6D1 × 200D × 1F6D1 ÷ # ÷ [0.2] OCTAGONAL SIGN (ExtPict) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) × [3.3] OCTAGONAL SIGN (ExtPict) ÷ [0.3] +÷ 0061 × 200D × 1F6D1 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) × [3.3] OCTAGONAL SIGN (ExtPict) ÷ [0.3] +÷ 2701 × 200D × 2701 ÷ # ÷ [0.2] UPPER BLADE SCISSORS (Other) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) × [3.3] UPPER BLADE SCISSORS (Other) ÷ [0.3] +÷ 0061 × 200D × 2701 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) × [3.3] UPPER BLADE SCISSORS (Other) ÷ [0.3] +÷ 1F476 × 1F3FF × 0308 × 200D × 1F476 × 1F3FF ÷ # ÷ [0.2] BABY (ExtPict) × [4.0] EMOJI MODIFIER FITZPATRICK TYPE-6 (Extend_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) × [3.3] BABY (ExtPict) × [4.0] EMOJI MODIFIER FITZPATRICK TYPE-6 (Extend_FE) ÷ [0.3] +÷ 1F6D1 × 1F3FF ÷ # ÷ [0.2] OCTAGONAL SIGN (ExtPict) × [4.0] EMOJI MODIFIER FITZPATRICK TYPE-6 (Extend_FE) ÷ [0.3] +÷ 200D × 1F6D1 × 1F3FF ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [3.3] OCTAGONAL SIGN (ExtPict) × [4.0] EMOJI MODIFIER FITZPATRICK TYPE-6 (Extend_FE) ÷ [0.3] +÷ 200D × 1F6D1 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [3.3] OCTAGONAL SIGN (ExtPict) ÷ [0.3] +÷ 200D × 1F6D1 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_FE) × [3.3] OCTAGONAL SIGN (ExtPict) ÷ [0.3] +÷ 1F6D1 ÷ 1F6D1 ÷ # ÷ [0.2] OCTAGONAL SIGN (ExtPict) ÷ [999.0] OCTAGONAL SIGN (ExtPict) ÷ [0.3] +÷ 0061 × 0308 × 200D × 0308 × 0062 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [4.0] COMBINING DIAERESIS (Extend_FE) × [4.0] ZERO WIDTH JOINER (ZWJ_FE) × [4.0] COMBINING DIAERESIS (Extend_FE) × [5.0] LATIN SMALL LETTER B (ALetter) ÷ [0.3] +÷ 0061 ÷ 0020 × 0020 ÷ 0062 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] SPACE (WSegSpace) × [3.4] SPACE (WSegSpace) ÷ [999.0] LATIN SMALL LETTER B (ALetter) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 003A ÷ 0031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0031 × 005F × 0031 ÷ 003A ÷ 003A ÷ 0031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0031 × 005F × 0061 ÷ 003A ÷ 003A ÷ 0031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 003A ÷ 0061 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0031 × 005F × 0031 ÷ 003A ÷ 003A ÷ 0061 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0031 × 005F × 0061 ÷ 003A ÷ 003A ÷ 0061 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 002E ÷ 0031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0031 × 005F × 0031 ÷ 003A ÷ 002E ÷ 0031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0031 × 005F × 0061 ÷ 003A ÷ 002E ÷ 0031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 002E ÷ 0061 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0031 × 005F × 0031 ÷ 003A ÷ 002E ÷ 0061 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0031 × 005F × 0061 ÷ 003A ÷ 002E ÷ 0061 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 002C ÷ 0031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0031 × 005F × 0031 ÷ 003A ÷ 002C ÷ 0031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0031 × 005F × 0061 ÷ 003A ÷ 002C ÷ 0031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0031 ÷ 003A ÷ 002C ÷ 0061 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0031 × 005F × 0031 ÷ 003A ÷ 002C ÷ 0061 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0031 × 005F × 0061 ÷ 003A ÷ 002C ÷ 0061 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0031 ÷ 002E ÷ 003A ÷ 0031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0031 × 005F × 0031 ÷ 002E ÷ 003A ÷ 0031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0031 × 005F × 0061 ÷ 002E ÷ 003A ÷ 0031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0031 ÷ 002E ÷ 003A ÷ 0061 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] COLON (MidLetter) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0031 × 005F × 0031 ÷ 002E ÷ 003A ÷ 0061 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] COLON (MidLetter) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0031 × 005F × 0061 ÷ 002E ÷ 003A ÷ 0061 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] COLON (MidLetter) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0031 ÷ 002E ÷ 002E ÷ 0031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0031 × 005F × 0031 ÷ 002E ÷ 002E ÷ 0031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0031 × 005F × 0061 ÷ 002E ÷ 002E ÷ 0031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0031 ÷ 002E ÷ 002E ÷ 0061 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0031 × 005F × 0031 ÷ 002E ÷ 002E ÷ 0061 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0031 × 005F × 0061 ÷ 002E ÷ 002E ÷ 0061 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0031 ÷ 002E ÷ 002C ÷ 0031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] COMMA (MidNum) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0031 × 005F × 0031 ÷ 002E ÷ 002C ÷ 0031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] COMMA (MidNum) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0031 × 005F × 0061 ÷ 002E ÷ 002C ÷ 0031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] COMMA (MidNum) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0031 ÷ 002E ÷ 002C ÷ 0061 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0031 × 005F × 0031 ÷ 002E ÷ 002C ÷ 0061 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0031 × 005F × 0061 ÷ 002E ÷ 002C ÷ 0061 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0031 ÷ 002C ÷ 003A ÷ 0031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0031 × 005F × 0031 ÷ 002C ÷ 003A ÷ 0031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0031 × 005F × 0061 ÷ 002C ÷ 003A ÷ 0031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0031 ÷ 002C ÷ 003A ÷ 0061 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] COLON (MidLetter) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0031 × 005F × 0031 ÷ 002C ÷ 003A ÷ 0061 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] COLON (MidLetter) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0031 × 005F × 0061 ÷ 002C ÷ 003A ÷ 0061 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] COLON (MidLetter) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0031 ÷ 002C ÷ 002E ÷ 0031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0031 × 005F × 0031 ÷ 002C ÷ 002E ÷ 0031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0031 × 005F × 0061 ÷ 002C ÷ 002E ÷ 0031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0031 ÷ 002C ÷ 002E ÷ 0061 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0031 × 005F × 0031 ÷ 002C ÷ 002E ÷ 0061 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0031 × 005F × 0061 ÷ 002C ÷ 002E ÷ 0061 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0031 ÷ 002C ÷ 002C ÷ 0031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] COMMA (MidNum) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0031 × 005F × 0031 ÷ 002C ÷ 002C ÷ 0031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] COMMA (MidNum) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0031 × 005F × 0061 ÷ 002C ÷ 002C ÷ 0031 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] COMMA (MidNum) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0031 ÷ 002C ÷ 002C ÷ 0061 ÷ # ÷ [0.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0031 × 005F × 0031 ÷ 002C ÷ 002C ÷ 0061 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0031 × 005F × 0061 ÷ 002C ÷ 002C ÷ 0061 ÷ # ÷ [0.2] DIGIT ONE (Numeric) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0061 ÷ 003A ÷ 003A ÷ 0031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0061 × 005F × 0031 ÷ 003A ÷ 003A ÷ 0031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0061 × 005F × 0061 ÷ 003A ÷ 003A ÷ 0031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0061 ÷ 003A ÷ 003A ÷ 0061 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0061 × 005F × 0031 ÷ 003A ÷ 003A ÷ 0061 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0061 × 005F × 0061 ÷ 003A ÷ 003A ÷ 0061 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0061 ÷ 003A ÷ 002E ÷ 0031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0061 × 005F × 0031 ÷ 003A ÷ 002E ÷ 0031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0061 × 005F × 0061 ÷ 003A ÷ 002E ÷ 0031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0061 ÷ 003A ÷ 002E ÷ 0061 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0061 × 005F × 0031 ÷ 003A ÷ 002E ÷ 0061 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0061 × 005F × 0061 ÷ 003A ÷ 002E ÷ 0061 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0061 ÷ 003A ÷ 002C ÷ 0031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0061 × 005F × 0031 ÷ 003A ÷ 002C ÷ 0031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0061 × 005F × 0061 ÷ 003A ÷ 002C ÷ 0031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0061 ÷ 003A ÷ 002C ÷ 0061 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0061 × 005F × 0031 ÷ 003A ÷ 002C ÷ 0061 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] COLON (MidLetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0061 × 005F × 0061 ÷ 003A ÷ 002C ÷ 0061 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COLON (MidLetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0061 ÷ 002E ÷ 003A ÷ 0031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0061 × 005F × 0031 ÷ 002E ÷ 003A ÷ 0031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0061 × 005F × 0061 ÷ 002E ÷ 003A ÷ 0031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0061 ÷ 002E ÷ 003A ÷ 0061 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] COLON (MidLetter) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0061 × 005F × 0031 ÷ 002E ÷ 003A ÷ 0061 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] COLON (MidLetter) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0061 × 005F × 0061 ÷ 002E ÷ 003A ÷ 0061 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] COLON (MidLetter) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0061 ÷ 002E ÷ 002E ÷ 0031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0061 × 005F × 0031 ÷ 002E ÷ 002E ÷ 0031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0061 × 005F × 0061 ÷ 002E ÷ 002E ÷ 0031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0061 ÷ 002E ÷ 002E ÷ 0061 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0061 × 005F × 0031 ÷ 002E ÷ 002E ÷ 0061 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0061 × 005F × 0061 ÷ 002E ÷ 002E ÷ 0061 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0061 ÷ 002E ÷ 002C ÷ 0031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] COMMA (MidNum) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0061 × 005F × 0031 ÷ 002E ÷ 002C ÷ 0031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] COMMA (MidNum) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0061 × 005F × 0061 ÷ 002E ÷ 002C ÷ 0031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] COMMA (MidNum) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0061 ÷ 002E ÷ 002C ÷ 0061 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0061 × 005F × 0031 ÷ 002E ÷ 002C ÷ 0061 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0061 × 005F × 0061 ÷ 002E ÷ 002C ÷ 0061 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 003A ÷ 0031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0061 × 005F × 0031 ÷ 002C ÷ 003A ÷ 0031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0061 × 005F × 0061 ÷ 002C ÷ 003A ÷ 0031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] COLON (MidLetter) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 003A ÷ 0061 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] COLON (MidLetter) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0061 × 005F × 0031 ÷ 002C ÷ 003A ÷ 0061 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] COLON (MidLetter) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0061 × 005F × 0061 ÷ 002C ÷ 003A ÷ 0061 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] COLON (MidLetter) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 002E ÷ 0031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0061 × 005F × 0031 ÷ 002C ÷ 002E ÷ 0031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0061 × 005F × 0061 ÷ 002C ÷ 002E ÷ 0031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 002E ÷ 0061 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0061 × 005F × 0031 ÷ 002C ÷ 002E ÷ 0061 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0061 × 005F × 0061 ÷ 002C ÷ 002E ÷ 0061 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] FULL STOP (MidNumLet) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 002C ÷ 0031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] COMMA (MidNum) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0061 × 005F × 0031 ÷ 002C ÷ 002C ÷ 0031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] COMMA (MidNum) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0061 × 005F × 0061 ÷ 002C ÷ 002C ÷ 0031 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] COMMA (MidNum) ÷ [999.0] DIGIT ONE (Numeric) ÷ [0.3] +÷ 0061 ÷ 002C ÷ 002C ÷ 0061 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0061 × 005F × 0031 ÷ 002C ÷ 002C ÷ 0061 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] DIGIT ONE (Numeric) ÷ [999.0] COMMA (MidNum) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +÷ 0061 × 005F × 0061 ÷ 002C ÷ 002C ÷ 0061 ÷ # ÷ [0.2] LATIN SMALL LETTER A (ALetter) × [13.1] LOW LINE (ExtendNumLet) × [13.2] LATIN SMALL LETTER A (ALetter) ÷ [999.0] COMMA (MidNum) ÷ [999.0] COMMA (MidNum) ÷ [999.0] LATIN SMALL LETTER A (ALetter) ÷ [0.3] +# +# Lines: 1823 +# +# EOF diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/grapheme_break_fwd.bigendian.dfa b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/grapheme_break_fwd.bigendian.dfa new file mode 100644 index 0000000000000000000000000000000000000000..0efaaf290fa3ed7d1979d69686f0651fda048972 GIT binary patch literal 10589 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 literal 0 HcmV?d00001 diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/grapheme_break_fwd.littleendian.dfa b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/grapheme_break_fwd.littleendian.dfa new file mode 100644 index 0000000000000000000000000000000000000000..eb240256c3d597ed0b1fcd07cad945514b0c15bf GIT binary patch literal 10589 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 literal 0 HcmV?d00001 diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/grapheme_break_fwd.rs b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/grapheme_break_fwd.rs new file mode 100644 index 0000000..317ba96 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/grapheme_break_fwd.rs @@ -0,0 +1,41 @@ +// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY: +// +// ucd-generate dfa --name GRAPHEME_BREAK_FWD --sparse --minimize --anchored --state-size 2 src/unicode/fsm/ [snip (arg too long)] +// +// ucd-generate 0.2.8 is available on crates.io. + +#[cfg(target_endian = "big")] +lazy_static! { + pub static ref GRAPHEME_BREAK_FWD: ::regex_automata::SparseDFA<&'static [u8], u16> = { + #[repr(C)] + struct Aligned { + _align: [u8; 0], + bytes: B, + } + + static ALIGNED: &'static Aligned<[u8]> = &Aligned { + _align: [], + bytes: *include_bytes!("grapheme_break_fwd.bigendian.dfa"), + }; + + unsafe { ::regex_automata::SparseDFA::from_bytes(&ALIGNED.bytes) } + }; +} + +#[cfg(target_endian = "little")] +lazy_static! { + pub static ref GRAPHEME_BREAK_FWD: ::regex_automata::SparseDFA<&'static [u8], u16> = { + #[repr(C)] + struct Aligned { + _align: [u8; 0], + bytes: B, + } + + static ALIGNED: &'static Aligned<[u8]> = &Aligned { + _align: [], + bytes: *include_bytes!("grapheme_break_fwd.littleendian.dfa"), + }; + + unsafe { ::regex_automata::SparseDFA::from_bytes(&ALIGNED.bytes) } + }; +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/grapheme_break_rev.bigendian.dfa b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/grapheme_break_rev.bigendian.dfa new file mode 100644 index 0000000000000000000000000000000000000000..d42cd3652733d482d95f0e60f36518d55de3be6a GIT binary patch literal 53905 zcmd6Q3!IhJb?*U*F~m?~DWyt{HHKJ=)DFYM7(FkJrazRLZ3ZJ}HDb9#L0+)tnPnVz3L|8u>5>4MK+_{+V2rO&VS z{k4lO?)U4LeBsjHxa^CUf2seMulUU?e`~;11AqJK-zgbXI=JjB*L?NbuU+@`A-{Y5 zH*Wa78-M?sfAFn8yy=gI{_)L!^6fvp<lH2H}qfAG`~r~IgD z>eJ6W`{QZPO@F?+rnatrM#IcmFU+3PICtKQP4k-(u}L@c)o>3WZ-8H}3m_V&bGHo_y+uKb$h(raAhlk}QSug1!j z$`#aax6gg9Fs#ta_AY(b)y2dCWP5oMLQe8~VfNg4i(1g@nzfGSymwwa z_r#7LPj4?CbnQ^M&f`;)8(;F5xtZi60bKuNtX3m<~GIQO`_L&1`T}!Wq znFC+w^}<8+bK(mh%s!W1ed#rRcE{|~vpeQg%z10h@i}ib-cGMA^x8M~*16?#$97#m zV~!;B^NmX%Wya$ldu)Q`{NxWT>#0va{S27@c-pk*!2bE_>Kc(i{frq6K?ZXg8|Oj} zFE%yJhb$H>T(}7GSiEG(QpjZaiWMtUaw*((&9z_c`_-e@F8kV;>u&t|xnF-{$dccE z>iR3M-}{YOH{APsCBL`j#@lcF@b?#f^Nv3__YYdXHRcbmyQ$AjYyW8E(0)UA{qa*b z-|#0r{-o{O5B+J$E$82I=+EZeI_A&6bzA@2KKP4W!`A*~{q5ua>b5%u{B_Se3wNIS znN*S&9(C%<|{NmcvklGP=9TN@WmS>9H%dQdyP#+9rty#cR5?QIvn)>zuQ zap>TorL8-@Ie6%f(XUnv9=dHvX=_=ZvhuRY;q~(QuTCo~-`f6_E6OI5kKWb&+VCn| zV?0Kz7&eTEWHl$2+jXs_S?&7iPj@r3lGO{F!7H0pX}>}3um7U7m09&2JalmXjTg0* z0;NQ?7`WZAptu2Xq<3+GF#@snVjg%56 zJ42Z5B_Td4Ugsq$>*843I$%$+Uu+!n+9~o2=O;Pk&)PZ&Z@FqZpxyFDQl^>-6b2NLt=OYVH^wdb8nhov zS8?ZJ-n{OW>k;Fej2&v4>m^dNeU_C&#@VO~zm-Ca3@qfD`FOLep%`AWhgYuOyiU+= zdtWRTGPY>dBDTDd^d`iq7TRMZ_d*0-@vu!WGH$;RueY@f|x zwQY;e?1+$o8!U^h>zb|A5jR?eh<>20d_6I{D|2-v845Vr`6k32S;gxNu6~@uL8AMh zcF_t@8_Xu=luag^ie?`lDbt<|J*WY0qu-n2pquAoDZAoS4Zy z>STP!n%!d7mAQKI{ATPuVeZV2?JQ%g<^(h5q_AFqg}{fAu}bWLq$zfi_lh-iV(;nL z(-~%&^NZs~uHaSL8 zt?nB3!Z2?w15@6JTstt3d@E@);Ly4BIU{HvZF4SU+lv3STL!gn>s{6-%>b6ueh6_S z-*Vhq$3{sY$Nr31yXU#w@#<&-U)mI#yP(7qwbqMdeT?5cpH z;ngYm>n>X{7G0BnA~Grmtl7W=R+Psf?Y&v(nL&t>*zU%@5*TR2QTs{GRI&ZEuG0Al zJ7b8HjD5}M_DkcOz5OQjT$Mbpnj6Y!-w1iy)@nii+7?((*>3EHxtt;13k!CijXIe% z%$*0B%id*(mbtjMoQ`qJIvKMmtX^{kS}8MfcrEt#U@@H{FY^{-k;@8M^Wrd*c72tc zsey&f!eq(S)_MXPqlI0>WwPvFa2(?O3*l5Y`L!+ZWMn)=bTYUL%#wORRF#ODx38SZ zYt85^4Ow2u={9z}HqP0XV-zz&Luf%7nH5)6+%IPA!_b+DmRTIgRJ_dH- znqk<*39H$(<}l;N{A~PVhFjlP&8@y=^{gz0SuDHGF=ogt<$7A|bFj#mp}n@2#Zj&f z2ZrV~rlT9lZgIz;5p%8`g;7DLTXgO!4zT4~z* z?A1`wVV4-LdISt#p*)JNkH*&-h~c1i@Y`AeFD%`Ks3}$|{E}8$grUu*tfig}J6S=8 z=n{NT;^zKW*Q)+XPPgs|>_mT*ad>909<|H{H@sRAGfPF7#I;`1UEVyG%`7Xr#MkO$ z{|nr31>5ji-d2p)rYgSPOMAegv%oBEmtvEN*pfHTrF~8<9jB^=-ZfCu6ev{TTu7?E9gZrzd2RCGB8rEI@ zN|UhtO81nmzi~!vahA&N-gLf_4Z8N{y=Vp%OHXL~m0p7e3YjPOY580m8@>NP;8wz_uqVVS-Iu@ z@{ZD0@$Z+HN%u2E=jomr=O*74# zsqGpk%+$&20ZFb|v3q|>Rm`+xHF%cZpqkY=I-l#N!+|TjHRhUW$sZ5XV8>n3>B2{a z=@RF+%2a2oe5Pu_U@AII^UTp{dfj?9It@&5zBSBBnHp7|YP((MxpAvl@1_;Rvp?rt zq)%|A9Fu3E>^aDvlGM{klb^u#He}GrIVf0e(r(in<5gXlb@zjzo-(94m*Onzt|@4e ztd*isuvuFB(44c0t}4SjH(q4<$sRK1*c^7E!*Fu>%(>~AqGZg?W!Tbc8Ft36beiyM zyN3ATG)(!%+KpT38s16DnxQ@Dj{Zj3qi31g?~@Y`f#sQL&oWdSg>}Ypm9pbS!veFm zT4I)~HO~sCdPHkOt=^a!G2(Mc(QXl~0KUevMqrb)$oQOjzEvtOyDz5v;+%+2S*c}~ zoVNLp;mEcM>y&d4$PhfwYl!EEgZuM|Wv4wp=K;+*?-LDz@mFpO*)U}WsLD|9i|zBH zGL=&}dSW>>QcR z;)~?;>kl41MpY}LFByG#y97Cm;q zR@$+&W8EHqS1iEl)^j~Tg-v21hO3eNfqy^hTX;m*GCza-z=4CQcCbf!!A@*{2goMf zh|(Y1ZNef0Djk#i5gizdqj6nttO2%hk%rSjj1hJejV+9T}}oyqC7N zVH_#2tL7}d6TZPZ{kXgbQ6|QyQIzXs~;;KA%Rvnc> zzNRL>T1Za`qh1L6Z`d)$X+)_OLRF2N$a0k?*z-@FM`3-W_gGQyCTDAsHD75)@w!H4 zVqD!waN`;%-g*4V!zEP}1MffF+E}vpC%Xm>sCfAP!}#65@cZzjIV?Gy7&; zOHA|2(v@WA{ASeRbjs!@^HfV<^OMVrj;1?yjt%Lj+-b(B93}}CBg)qe9C2#I8!ct61L!CD2zbClM)l6~5m*&lRydue*(z#Z zEuS-rXTI(+gNf8WIxVEM(K4JootbPnNj!+pOW!6Qy<4WJm#^$&z1%YhC&QBrK4KN8 z=fW{8Xe7m>gRP397JPzuoElNSVe5!f!UHVGD_9$<74h@c11N5lg}BA~$gXb;^*UMB zmA596l>+LK-M)lpA)dW;8}@Y!O9b=w{@mn3uOSvN~pF zBC^+&T#L2dFS{>+pUlzuXWold6|eXFoW|1JDwvr@fh0G~G8B_ZUoki6jde!<;yv+8 zuq%Aot#2hRWb+A`Kt|TijDBu-*p{oAB-Il$;)}&>{V9)G0oH@VdNjgAk#8h zrsP{jL87b59k#Br*PZdsuXzP8)-}J_IdfRwCLBk1LJkgSEw(uVcYAbT4@jrC}aW^6m_YenwsuWub7 zmXCQ%?S!I7jOy~l-k6-<(3*WjM9A0TicV?-DT+ml41+%c8zT9-*=bblfxXv{Ok~hf zhmI@un&*VmtiYq$O()fvjErkDR~~_#u4t3Y%;#Z>t9%{Jmo)#MQhCYTzvL0fZS4i= z8Kr2AqeZB>BQmgz%1lOxa}vHTGay9`Ob$}=sh0Cw2P{HVpeTX(t4JwJiB=KQc{5$64Qc$c*-FJYaFY#rj3GDQq~9Mv1L%|cvA*KozB71aV_`C=6)K4bkw z<(q|dYemQMl4UIpDe~A1q(-)p=Wxc9tcIHW#F@yoOK4HS6)b_!!kflx-YvF}l&sh- z$u^BRR3;SnE-Tw2b&PrT5TmYmxMJ(#Au;Bc9u#X>Hw-pBs!TA8Wn>}`>(DfEozb!^ zqpRq-CS>K2r9CB9Bp8s?!2#KstawE7$^xHT7S6U)@@K0FrvjD9$5w$E=_7~Hx*j^i zku7xuUX)`XqdT?mDa7cwW&3$z5!&C(Au%df1L+#33^a|wJ_&d0gx%dX((8HI3* zHh?(bRiu#rs4~K7W?&x;(_VX4m6vI(_a9!`^Q9KdG-^F8Ys@rV#hYz0$@tw_1!G+Q zlob!zHn0K{yqIrH9>HiS1Es7J@@+XE5|-H}irv|0(=nzqyn4Mi*h3OC@*Zc;>Dk<6 z87kulHP-XGnm4mfHu6wyrk)vU6~%&OZ#9mNMd!&PxCcg-jEtXU-8x_u zsXOc%%TeuvIaIKVwXC?VqGLrL7e!L|*X~R*SUWEnOA6`AVm-ZHjDci>U9$8feyp*W z14WcP{An*uBj;EhY(2YjEJSR(!ipnHIE}8Sn%PI!j9yz7XWVP=P#^U&r}gc~n@9DQ zd34n&!M$c5Y-ZF%?5t;bwWNrVuD!Pk{-p_*od23aZ=pQLblm8y}0^A%V(vm zzmonV+F?#DM-j&?qg7XA>&G%;{iLsk=GPtuTRT%$h{_Q&t*rE#iadzzF2zhNudB?M zUASfyTVIyWbnTYrrfY<3FJfM+cZkNcvQl_ae&u-~euEdh$?D6pDn9pgsxR3)(^#$% zFY9W&wZ&*Z&0Uknu0@I$Dl21s**O*5unMKf?f5M}B6%b}Q?1!pF{*c>`suDh`h;q* zMz9O@LE)5KXI2^Wvw4Cr9IKj>%E~muES6p87{^1_VOHHCEHY;JF;-Ttx+QQ#-J$1b zuL#i@1kB2+#{|O((4xc?)gdB(R*pm*vlwb_8m!dTc%{AXj4CSwL#eD>(dYidE01W# z;WUU-7R+x|JG^kj1Vl||rOYpBr9~LpoI}@YV0bp{5*2!WT`y5{f9oTvJ*lho-1Lf# z=hb@J@)~(F<%bckPUFj&vC4`pU9PIMtWbNH&uZ~LV#Rx-qOZU!ZIfb;iMWzC$EE$P zSj>!>C3NPqU#_YYeQ8xC<^Z-u=!@rrMThvb58GmKc1zbG%Nliu`do&;>&1sx9A7*{`7YTl+N6_BN0;qd{va~`mf@DK zM3)u!r6VXsm`}K>5-hvQdikwctViCQW{vY6qbBNAVVsc2VE>6#RSIXEmZ&(7wam7h z)-gXtzPv!E_i~xjs+Qs~t~{l<)3v>& zw-;qkyMfr-&XvL^T2(3R7f-S5v$Vdfh4yo|J6oSH;*F&p}X1{ptL{gus}ixc6;hT$W|;pLA7alJnx$`wx5Gn7ufX zr+M=}n$vVq)|p;jNLS!ZeggTh&R=#nGd)8m_rhDcUR4RcC3}O8BfdFYIhqmImh<7! z^e@d@$g3o`^07NxziFnL_a|p+yS@o|R%cwpUYw~=Lsg|^djDbYtmyEXMH~m)lszlg zCAS5x@YV#^jL4m#)3aeJJ9J&Hltsl8m@aXCt4#5ke`PXN3kFlsX$H@1ou=2UAC0M2 zbjh<+GBv6^)ponib8%mZ$xC_=PdYD4ITz^@FUm1_7RsK3K8dPIJp)K{E>8VIhr_%U zaRn&SB&`u>&RKk~@M|fv{FvE9%&|G_KB210z_2rZBW@Ia3r`Y1IweAovo!q-RzMCPwus8*ELzPb<$Y;~clEljjB6=cLSs#eTsY5VilifGrBYDMXfYx6wU zP#0+aYGfZ*D>_7-Rx1i3Uh@^LR@8Qk$!I8`s39gN{S_9Xjm5LF@V40qUjL5jU{l`htRkx0x^UwF`XV}@)-CB8Opsn_i zwT13PORlZgi1nmOqI#)#4I|Edl&s!S?`qL;hcT)`$NgTVicxDA@oX@bZZzqjB;e{9Y{cibf&YXGk z@E7zxe*A<9+*>#L7ky5cJzGXQc#t&JZR*s@cG6P^^mOznJ~_ZKyQAYjel9-8?`S4W z)Dy^43gfEHP}LagP@h4WuRE^iK&Lw#sY5f}NG~M8apN9)?16sxoj%`P=(cw+WVL4xe!lPm zJ|St-U&oKfPm(VEJap)R%L>{$Jb80VdC0Jw@>LVAkA0@>nd8qk{&?t*Pfcrn?)K+SPH%et*5`j=&T+e| zzg*|bHNO6-jdUDJ^9^f!bfZbW6gCn z17eJXGMobSC|$jz$dvuBp&^0RJr$FmUzL(4kV2w0y+xumjgV;lXeZIP=-)5;mJ z2^q<+X0swDc@koW_d5DFk|?3o$`XC1ske5OY5Ez7$@<#%Z98{5jW<>|N64UaMn)rJ z^a1tv)Goun(6jq2iRdy{>tYd!hU*YP-IGLV##yj{?hTfb)y|zNEgCsS!$@j2*X?2i z<7*EQ4zacj$&hTm;A4ZE4WD$Dh9|p5^)}5$ChH*&#Q=>}H;cYh7Q~$~kSt*J17K&t z+F|Kz?NW(kPF`}&t*cn23Y&%q1=){(o@%(3&sc)(7$nfl3A}1H)IAJ~t{+A(M#Oe6 zKIrVFwpYynhf3{5CF1I%>O?o;REVGn+VK^pDjgadQ6b2N(O~TQZ<18T*Lc~$*Hk`u z4>Z*r5m-)NboQc%5Vf^xt9E9jCzg;%C&b_&qbxkmdIeK`Pu3T7#**QG8Ij^CToR%2 zIA+W+Nam-X%Ben7x6a9AI{oV;!rHk8GJ(D1j(lksMkcSxlL1?aN+54^_Ge~&vhKVj z`@(PJA)veTbV(0yzDZFo6GPpF#CtR53DQA8L9ru+!p0Ake;xc~W>h1W@RrCP-h8vZ zui&8B!RP_r3=}oz*7r9ka;zbmSrN??O|3^`cB&UF==_Pu?b}2`991?*bPHC(pMF5- z1`s}y5=S?U{lJ*QiBH&ve%)yfGgiO}sl_r=-*Nk`iic#BLZgx*n-zUIT?Oy;z9J`W zUd?8}8TkX^{|@}D?d3-oPnF1?J-W+Z%;9>8F+&s3qfra&1@nAvMa(cUNkTKYfh2| zocw8Sl{l#~@Tc)|#)sYIk51C3acOj!+2gTE2Q;!;I*lw*%FnAo`TSAhcs1nJHGkVfyY2-~5QKFG03kupZwQ@B2OddV$(f)pjih+Emq;6Tj zz*1rBhK?{|?IF>amxDtRp^4(lWK&m0c@VJZyf@#-BGL}^zCmy}|8hPC)))!?MK~Ih zC=lH^!UcIi4-o>&1S|&LyUN1xChG*_n@AgQV4cNC>PqWoab`xg?QA2doe*?Yl_BFFRpE)nA|rlp}HyLO&(RhwoVc%k0qL?AS0l0@yuAPu^Wq|b(PoE zo;`KMGyNqnNv27t2niw%>`UcTTkSl(zt9$E+GAW{j@ehTmG zsHd}^la%VNWGQVHJ<>{p_BPVk+!`RnAn`7nQ3MV8$efRA-#()|i9TLZ&>c|8+7;FX zRC$=l>w{hKT8!mokQtfHp5w9Q$!pJ^fUR~mOD%yfSXa#@W)4Z|Q)46{40&P>LYKjM zbi7X-s)LMAW}-V0v|2ZsB=vzsMjFLV0L4?aG=nUbo%$uD7wQdYCmRt2duNpE2aI~Z zEk@VYhI}YS$C1NIPqTiWVMwQ<<7F;Wgm?Og*1h1oA!M>{Z`kWMK4tGv#u&3>ETO!? z#Wvb&ue+5zBZ)FX8sn6<0jc05Er+`=C{mSUs4n8GAU+;@SuT)>BGCl-q(> z#v*A>!o0+p1YI9+^L9$6unj@W(ZMTHA<(6)*kk zeVp}AGs*^;U31Z9TSBl?l5Lh`%^p!ITJPImd)&)*L-i6^0%KL2xb7k|KkbfSAD-qq zLRxpBV9oKW*x%Kw0#d@s-V`K?eR)K1gV1@DMYx2pCJ_QDdAy<{v zaKe|ozZ-=4atuLLCkXRflz-BEn9_ z^ste)$T|>vX(vrN5K4*_bTy`T9t+lhu@yRjV4mdWEG3gio~09uq{U#L!t+oTh{$Z) zz^<>iVCUdKr~?bcJ>_r*Bks*V)pF?D!QKn@o*R_4PEMiMr;?>@C!qm3oxEnP#m<;( zuV?fr+)326H`R`1J7UzzGRxwldu{-=#FrR*jjT-~>!F<6Tsw@PRg;ZduI%@6QiuIR z>iCy^mA#RyruHVXn$5L$)JArn_EmRXpYJ4SQ2WRdNjqWlB<~Pcl5)l>A;#*gBa$*( zIMy%7GbMs&%2#F^L8zAdEBl16LTQ>m0Cb;4|gqfKgf7pJ z=%q6?c0Q30RZYd*m&T@g50+}z-U*yFoMZ4c`xqzfM#e~S+Jo2PhiWdVIZ4ty&DILU zIBVf%KZ9EGVTYQol?vum^zu@Ta2v_u3Zc&}YO2JyAlI4}LL^d!Z(;w`*ehWIHi}ww z)r!`aB4NgyoT+7%sq(c?DWV6ns)W7n?Oj=$c@Ic!fUjk?x9{D{9)$?7M4}aIUXaRq zh$AZ_rCq;OJl19K18A* zL$Oq34M0elCH?;a;XD@+it$0$gibSJZ=>f-or-+1=H8k+Ywjy_n=zy2&O$f({l3CE zGDEq)bmvyu=H5bgd=Gysa1VzL;XR!Zr?Y(YlUma!`2Cz2GY%X$dbH+Fmd80&Rp^!4 z;+xd!;6eNatqvaat?2Uu2l#V3U5US9Ec%4LL%+Gc<=sIVh2GJLOpM*pf%iZEIsNP* zyr_TrR?U6%3H4&e{*?axXFt;xz+G3zvLH!RRn-v7Lx+wY#VV)J?chQBNn;C2?O%A; z+(+M~5z#;6^hgf~zitQk+f%0k5BjO9a?+y{r5LB7fqFtO-K)G@A#uou(RZ(}cgWm0 zgoCAs-lk1+{j#KlGkwk)Bm{zn{^t6)m$cg*r}7`T3?ojP=CF`XmHo77go?k<<2W5b z8qg~B-9ylk^cbJW&h?Y{8xSH|00$)a-g}})Xk4rUeQ8gH?ywj69P;#RdPtTU^aXq@ zH{wI%pCf-4ZNfgG8~U8i=|UFJjEqdbb$jnUd`7aTHM7W3^~d9R{Q;GHn@1w9U^-(4 zKG!jWWga--WO@!{>OUu|cQS?qL@R2|j9RRS#_1szq%z0IV5PqoSO)A*jFA3LlEpY^ zS!M0JTU{M#u!nqRY?7_ObEe;%#lt4j_YW_AYB}7=Mt6-fpIp)=Pbc@!G1&2olB$2X zykxaJVJ3Cr{AhgY{Iy0rpD&zVetip0FPHV{^z?E+y1K^edpSeQcb0gDuTxjU-e%6k zH5=X$ZCTDSmR2^jlHa|1ZvEWZb35ivq<^2DJ3adO6n}zG=~cPY{-pEGpQ7V46KBkj zbM5r~r|4|6`*hNz88dLAeeT4{&2yikPy6AV58BfVJ6ZNcpT$#&rqysIt?b-3QLe)K zH%nW2{jz>Np~J`<<{oAwc?eG>5h{)uGvs7_j1HgT?7VzRsLug1oU;esLcj1laK7UI z1G!JfbDY15*ENy_G&SMckDNhX!`HJ}b{*Vr8mW8&Hk+A?ktj~^Pn?MF6)qY#PP8~_ zlAHs7hR=Uj^NuI7x)&*5qO5~*C3&{^I?6X$LR;qUOlZ%Km>dtk7tWD8sN?iMjmr`c znb4Va{tYz+^q0E|7k^*Y)r65&NpyXmv%0A=r^|ef)3MkGkmtuxj!E(mOX^G-No<8* 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 Vtwx-_g<&M3+nLU3ZKVO({x{W4)oK6$ literal 0 HcmV?d00001 diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/grapheme_break_rev.rs b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/grapheme_break_rev.rs new file mode 100644 index 0000000..db6b6ee --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/grapheme_break_rev.rs @@ -0,0 +1,41 @@ +// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY: +// +// ucd-generate dfa --name GRAPHEME_BREAK_REV --reverse --longest --sparse --minimize --anchored --state-size 2 src/unicode/fsm/ [snip (arg too long)] +// +// ucd-generate 0.2.8 is available on crates.io. + +#[cfg(target_endian = "big")] +lazy_static! { + pub static ref GRAPHEME_BREAK_REV: ::regex_automata::SparseDFA<&'static [u8], u16> = { + #[repr(C)] + struct Aligned { + _align: [u8; 0], + bytes: B, + } + + static ALIGNED: &'static Aligned<[u8]> = &Aligned { + _align: [], + bytes: *include_bytes!("grapheme_break_rev.bigendian.dfa"), + }; + + unsafe { ::regex_automata::SparseDFA::from_bytes(&ALIGNED.bytes) } + }; +} + +#[cfg(target_endian = "little")] +lazy_static! { + pub static ref GRAPHEME_BREAK_REV: ::regex_automata::SparseDFA<&'static [u8], u16> = { + #[repr(C)] + struct Aligned { + _align: [u8; 0], + bytes: B, + } + + static ALIGNED: &'static Aligned<[u8]> = &Aligned { + _align: [], + bytes: *include_bytes!("grapheme_break_rev.littleendian.dfa"), + }; + + unsafe { ::regex_automata::SparseDFA::from_bytes(&ALIGNED.bytes) } + }; +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/mod.rs b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/mod.rs new file mode 100644 index 0000000..ae6c499 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/mod.rs @@ -0,0 +1,8 @@ +pub mod grapheme_break_fwd; +pub mod grapheme_break_rev; +pub mod regional_indicator_rev; +pub mod sentence_break_fwd; +pub mod simple_word_fwd; +pub mod whitespace_anchored_fwd; +pub mod whitespace_anchored_rev; +pub mod word_break_fwd; diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/regional_indicator_rev.bigendian.dfa b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/regional_indicator_rev.bigendian.dfa new file mode 100644 index 0000000000000000000000000000000000000000..1a3357f714d45e1cab013e2d861509c889f1c053 GIT binary patch literal 366 zcmXRaEiTb5N=;9#&`m5Y$pMenwnHeBJ7fQ21X-+6T&=eyRcEHR6 e2CO&%8;O9O0~KKLxHLjc1;J!sfQFS2Pz(TV><#+> literal 0 HcmV?d00001 diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/regional_indicator_rev.littleendian.dfa b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/regional_indicator_rev.littleendian.dfa new file mode 100644 index 0000000000000000000000000000000000000000..e437aae3ad775a5b2aeb507e618100b7d9fa8e90 GIT binary patch literal 366 zcmXRaEiTb5N=;9#&`m5Y$ = { + #[repr(C)] + struct Aligned { + _align: [u8; 0], + bytes: B, + } + + static ALIGNED: &'static Aligned<[u8]> = &Aligned { + _align: [], + bytes: *include_bytes!("regional_indicator_rev.bigendian.dfa"), + }; + + unsafe { ::regex_automata::DenseDFA::from_bytes(&ALIGNED.bytes) } + }; +} + +#[cfg(target_endian = "little")] +lazy_static! { + pub static ref REGIONAL_INDICATOR_REV: ::regex_automata::DenseDFA<&'static [u8], u8> = { + #[repr(C)] + struct Aligned { + _align: [u8; 0], + bytes: B, + } + + static ALIGNED: &'static Aligned<[u8]> = &Aligned { + _align: [], + bytes: *include_bytes!("regional_indicator_rev.littleendian.dfa"), + }; + + unsafe { ::regex_automata::DenseDFA::from_bytes(&ALIGNED.bytes) } + }; +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/sentence_break_fwd.bigendian.dfa b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/sentence_break_fwd.bigendian.dfa new file mode 100644 index 0000000000000000000000000000000000000000..a1813d7c8eb16fa90117a11ad656dfd44206af45 GIT binary patch literal 149903 zcmeFadze+ll{Q}cobKi-qM|XzD54@7MI>kl5+n|yV+=9GASxmfG{g|cF^=PB3^_mp z-A&WoH1}&a&~j~{xyW5Y2r+~>#t@^9<75;WVi;lwI>zw%ncw?Xt+h|>efH^Y5H)}N z&hxBion5tR)vEh#t*VFr<@=9Z@$h}$zVERs?){fX{^@)7K639B-+$=dhrfT{6(jDy z*L?6d6PN;%GVUk1-6r>W?!zWXr3(s+TC{A{x=q_t+MU||wA0V%aOPQ`I{VY-eCFKG zo_Bu73p!nR(Z!uF>2m31pS%2uu2*)us{7}ATz$jS@W+cyW@KKPD1?;3LV(0hj6JN#QC?z{inBfs;&cSn8i!GC(_ zpCA7IBmeT~zdrVV9{<4;KOFs|%$Tv`ipNiwSW;RxseE!pW!04Gsne#KIRx^4T@JASd+t}y|9anVUij^cFTMQlul&cW|M|QBdhPZ7ZyfmVgTH_C4~PEe@E_m$(~&

qHEVH`&@Tj-@aeI^R8j{KK_Fr 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 OOP4n!IA_%IjQW3rxyyL~ literal 0 HcmV?d00001 diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/sentence_break_fwd.littleendian.dfa b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/sentence_break_fwd.littleendian.dfa new file mode 100644 index 0000000000000000000000000000000000000000..2763583be9f39d9a1d26833be1cd3f80327df2be GIT binary patch literal 149903 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 Ch|75Z literal 0 HcmV?d00001 diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/sentence_break_fwd.rs b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/sentence_break_fwd.rs new file mode 100644 index 0000000..46ecfcf --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/sentence_break_fwd.rs @@ -0,0 +1,41 @@ +// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY: +// +// ucd-generate dfa --name SENTENCE_BREAK_FWD --minimize --sparse --anchored --state-size 4 src/unicode/fsm/ [snip (arg too long)] +// +// ucd-generate 0.2.8 is available on crates.io. + +#[cfg(target_endian = "big")] +lazy_static! { + pub static ref SENTENCE_BREAK_FWD: ::regex_automata::SparseDFA<&'static [u8], u32> = { + #[repr(C)] + struct Aligned { + _align: [u8; 0], + bytes: B, + } + + static ALIGNED: &'static Aligned<[u8]> = &Aligned { + _align: [], + bytes: *include_bytes!("sentence_break_fwd.bigendian.dfa"), + }; + + unsafe { ::regex_automata::SparseDFA::from_bytes(&ALIGNED.bytes) } + }; +} + +#[cfg(target_endian = "little")] +lazy_static! { + pub static ref SENTENCE_BREAK_FWD: ::regex_automata::SparseDFA<&'static [u8], u32> = { + #[repr(C)] + struct Aligned { + _align: [u8; 0], + bytes: B, + } + + static ALIGNED: &'static Aligned<[u8]> = &Aligned { + _align: [], + bytes: *include_bytes!("sentence_break_fwd.littleendian.dfa"), + }; + + unsafe { ::regex_automata::SparseDFA::from_bytes(&ALIGNED.bytes) } + }; +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/simple_word_fwd.bigendian.dfa b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/simple_word_fwd.bigendian.dfa new file mode 100644 index 0000000000000000000000000000000000000000..adc64c1924752de395a16a54ae598d531f1a9d79 GIT binary patch literal 8975 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 W4*;v89?Q)GwugI^NsZf}_WlE$g}2)P literal 0 HcmV?d00001 diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/simple_word_fwd.littleendian.dfa b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/simple_word_fwd.littleendian.dfa new file mode 100644 index 0000000000000000000000000000000000000000..dd4838619473786134afa9ae694b2eac90bebad6 GIT binary patch literal 8975 zcmb7K3wRXO6`riSkc8b3lFd7WU@cNAO08O?l&YoFQcEeNEk&zB0WH;P15&C~HzDtY z?B)S^07(cTB%6dR0TSL=q?96JiWpHbq9RqRXq8$zwc7umJ9lhAB2hQS7+*Z(NwT zb4>deX1l`f7&0_GB66716*WA1L`AT^eRJ}+rhNOBTW|Z$)bCFF-tFI?{)0PyIO9h%e?03avw!-t zpU?Tl+&l03<=yw(J8%B47A#zJ-~GQ{{F?_J{Ov;z|1M+6(nps4e)%6BeQd=aAAiD= znYA)ICpRy@ps=WTRf*SET2@}MdQD|jbuc-kH#BT)+|;zWxy9ew*1n}9u(fmB z_8nc_J9q8gvv=SA15f_x;8TbGeE2U%{(AK3W6vCaw&!mro;&$`?+d41eCg%Wuk^io z=C#+~IQ!VH4^->09^1``zJx(PQ=y5-in zciw%^J@?)_@6pGeIC$`>rw$!``sriGo_Xf@@n=c*#BX$hYzgRVdbo% zDoU6NkK7)Xfx8D+N!Yru&afk4ABTn8R3+Xv**48K+jh5YxlOh0y&}dw**@Jq(>@n} zd+dGov-T;DMu*?A(=k->wD|q4+js2f+O>Q4oÖ#l&kva+hHyL;z>pd4X}2XB!I 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 = { + #[repr(C)] + struct Aligned { + _align: [u8; 0], + bytes: B, + } + + static ALIGNED: &'static Aligned<[u8]> = &Aligned { + _align: [], + bytes: *include_bytes!("simple_word_fwd.bigendian.dfa"), + }; + + unsafe { ::regex_automata::SparseDFA::from_bytes(&ALIGNED.bytes) } + }; +} + +#[cfg(target_endian = "little")] +lazy_static! { + pub static ref SIMPLE_WORD_FWD: ::regex_automata::SparseDFA<&'static [u8], u16> = { + #[repr(C)] + struct Aligned { + _align: [u8; 0], + bytes: B, + } + + static ALIGNED: &'static Aligned<[u8]> = &Aligned { + _align: [], + bytes: *include_bytes!("simple_word_fwd.littleendian.dfa"), + }; + + unsafe { ::regex_automata::SparseDFA::from_bytes(&ALIGNED.bytes) } + }; +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/whitespace_anchored_fwd.bigendian.dfa b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/whitespace_anchored_fwd.bigendian.dfa new file mode 100644 index 0000000000000000000000000000000000000000..bcfc4e9a15d370165a346e47d19a64c7668aa2b3 GIT binary patch literal 572 zcmXRaEiTb5N=;9#&`m5Y$pMenwnHeC!1WI#3X(=epz`zIsOc;Qf zg|>i|jh&sHgA)X}Pysg&5b*NxLx6yQAP5KvV*n9Ryg*D`LJ|*v`yZ1b#efJMsH`7D wM$;Sypg1lWs5*!=h9ZdUHcYD+F1*4b2o}Po8lo15@jyu_5P&JdstiRC0G?SMU;qFB literal 0 HcmV?d00001 diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/whitespace_anchored_fwd.littleendian.dfa b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/whitespace_anchored_fwd.littleendian.dfa new file mode 100644 index 0000000000000000000000000000000000000000..d534a464a506577560bbfc69c245b8afcd6ee24e GIT binary patch literal 572 zcmXRaEiTb5N=;9#&`m5Y$#$a0WTjv1PBNSf`E`P1`rX&3&g}FB=G>a|1lX-3>bmr$B@x9 uhXE*#O9pBRL>fa8M0OjdRSXwiVG#riVN(rJi^F)Jq!b9i6k%0{A_xGW#~xq+ literal 0 HcmV?d00001 diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/whitespace_anchored_fwd.rs b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/whitespace_anchored_fwd.rs new file mode 100644 index 0000000..ea68582 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/whitespace_anchored_fwd.rs @@ -0,0 +1,41 @@ +// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY: +// +// ucd-generate dfa --name WHITESPACE_ANCHORED_FWD --anchored --classes --premultiply --minimize --state-size 1 src/unicode/fsm/ \s+ +// +// ucd-generate 0.2.8 is available on crates.io. + +#[cfg(target_endian = "big")] +lazy_static! { + pub static ref WHITESPACE_ANCHORED_FWD: ::regex_automata::DenseDFA<&'static [u8], u8> = { + #[repr(C)] + struct Aligned { + _align: [u8; 0], + bytes: B, + } + + static ALIGNED: &'static Aligned<[u8]> = &Aligned { + _align: [], + bytes: *include_bytes!("whitespace_anchored_fwd.bigendian.dfa"), + }; + + unsafe { ::regex_automata::DenseDFA::from_bytes(&ALIGNED.bytes) } + }; +} + +#[cfg(target_endian = "little")] +lazy_static! { + pub static ref WHITESPACE_ANCHORED_FWD: ::regex_automata::DenseDFA<&'static [u8], u8> = { + #[repr(C)] + struct Aligned { + _align: [u8; 0], + bytes: B, + } + + static ALIGNED: &'static Aligned<[u8]> = &Aligned { + _align: [], + bytes: *include_bytes!("whitespace_anchored_fwd.littleendian.dfa"), + }; + + unsafe { ::regex_automata::DenseDFA::from_bytes(&ALIGNED.bytes) } + }; +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/whitespace_anchored_rev.bigendian.dfa b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/whitespace_anchored_rev.bigendian.dfa new file mode 100644 index 0000000000000000000000000000000000000000..bb217f17a0f04cb8547dc29414a4b936931fa275 GIT binary patch literal 598 zcmXRaEiTb5N=;9#&`m5Y$pMenwnHV4dMsq{?j8K|^fe{3lFaR?P zZ2>DAJ3BiECkSw%0&X54;N|0o0099(5D*f^03xDzfta|2Bpv|wKPCedZb0v|vH+#n z*cn)W5DIY1fD~|oRdGSpB2yg5927R13?f<>7|^6pv>|hl^&pFb*|;ScaY=#10jj1J ANB{r; literal 0 HcmV?d00001 diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/whitespace_anchored_rev.littleendian.dfa b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/whitespace_anchored_rev.littleendian.dfa new file mode 100644 index 0000000000000000000000000000000000000000..a7cb5a78a7416271dea570ea04061c98167e5693 GIT binary patch literal 598 zcmXRaEiTb5N=;9#&`m5Y$fKqJi x3@kth1-NBE3OK>4xS(p0DGp=~3L8xZId;&bP_!X)ko6#ogW0$x8F5L0!~v@f7Dxa9 literal 0 HcmV?d00001 diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/whitespace_anchored_rev.rs b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/whitespace_anchored_rev.rs new file mode 100644 index 0000000..72b444e --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/whitespace_anchored_rev.rs @@ -0,0 +1,41 @@ +// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY: +// +// ucd-generate dfa --name WHITESPACE_ANCHORED_REV --reverse --anchored --classes --minimize --state-size 1 src/unicode/fsm/ \s+ +// +// ucd-generate 0.2.8 is available on crates.io. + +#[cfg(target_endian = "big")] +lazy_static! { + pub static ref WHITESPACE_ANCHORED_REV: ::regex_automata::DenseDFA<&'static [u8], u8> = { + #[repr(C)] + struct Aligned { + _align: [u8; 0], + bytes: B, + } + + static ALIGNED: &'static Aligned<[u8]> = &Aligned { + _align: [], + bytes: *include_bytes!("whitespace_anchored_rev.bigendian.dfa"), + }; + + unsafe { ::regex_automata::DenseDFA::from_bytes(&ALIGNED.bytes) } + }; +} + +#[cfg(target_endian = "little")] +lazy_static! { + pub static ref WHITESPACE_ANCHORED_REV: ::regex_automata::DenseDFA<&'static [u8], u8> = { + #[repr(C)] + struct Aligned { + _align: [u8; 0], + bytes: B, + } + + static ALIGNED: &'static Aligned<[u8]> = &Aligned { + _align: [], + bytes: *include_bytes!("whitespace_anchored_rev.littleendian.dfa"), + }; + + unsafe { ::regex_automata::DenseDFA::from_bytes(&ALIGNED.bytes) } + }; +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/word_break_fwd.bigendian.dfa b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/word_break_fwd.bigendian.dfa new file mode 100644 index 0000000000000000000000000000000000000000..1e75db68a4e2747fd6cbc59048a510535e485b6b GIT binary patch literal 229739 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 a>C96$X!`9Bqh)jh_h2!P(lSEl(*Fl4euJX` literal 0 HcmV?d00001 diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/word_break_fwd.littleendian.dfa b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/fsm/word_break_fwd.littleendian.dfa new file mode 100644 index 0000000000000000000000000000000000000000..e3093a3f0c850396bbcbb3c59e39b89951c8bf91 GIT binary patch literal 229739 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�fe`^=W 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≪eWaY)wWT1a!>Be&! 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 = { + #[repr(C)] + struct Aligned { + _align: [u8; 0], + bytes: B, + } + + static ALIGNED: &'static Aligned<[u8]> = &Aligned { + _align: [], + bytes: *include_bytes!("word_break_fwd.bigendian.dfa"), + }; + + unsafe { ::regex_automata::SparseDFA::from_bytes(&ALIGNED.bytes) } + }; +} + +#[cfg(target_endian = "little")] +lazy_static! { + pub static ref WORD_BREAK_FWD: ::regex_automata::SparseDFA<&'static [u8], u32> = { + #[repr(C)] + struct Aligned { + _align: [u8; 0], + bytes: B, + } + + static ALIGNED: &'static Aligned<[u8]> = &Aligned { + _align: [], + bytes: *include_bytes!("word_break_fwd.littleendian.dfa"), + }; + + unsafe { ::regex_automata::SparseDFA::from_bytes(&ALIGNED.bytes) } + }; +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/grapheme.rs b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/grapheme.rs new file mode 100644 index 0000000..e40a0de --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/grapheme.rs @@ -0,0 +1,355 @@ +use regex_automata::DFA; + +use ext_slice::ByteSlice; +use unicode::fsm::grapheme_break_fwd::GRAPHEME_BREAK_FWD; +use unicode::fsm::grapheme_break_rev::GRAPHEME_BREAK_REV; +use unicode::fsm::regional_indicator_rev::REGIONAL_INDICATOR_REV; +use utf8; + +/// An iterator over grapheme clusters in a byte string. +/// +/// This iterator is typically constructed by +/// [`ByteSlice::graphemes`](trait.ByteSlice.html#method.graphemes). +/// +/// Unicode defines a grapheme cluster as an *approximation* to a single user +/// visible character. A grapheme cluster, or just "grapheme," is made up of +/// one or more codepoints. For end user oriented tasks, one should generally +/// prefer using graphemes instead of [`Chars`](struct.Chars.html), which +/// always yields one codepoint at a time. +/// +/// Since graphemes are made up of one or more codepoints, this iterator yields +/// `&str` elements. When invalid UTF-8 is encountered, replacement codepoints +/// are [substituted](index.html#handling-of-invalid-utf-8). +/// +/// This iterator can be used in reverse. When reversed, exactly the same +/// set of grapheme clusters are yielded, but in reverse order. +/// +/// This iterator only yields *extended* grapheme clusters, in accordance with +/// [UAX #29](https://www.unicode.org/reports/tr29/tr29-33.html#Grapheme_Cluster_Boundaries). +#[derive(Clone, Debug)] +pub struct Graphemes<'a> { + bs: &'a [u8], +} + +impl<'a> Graphemes<'a> { + pub(crate) fn new(bs: &'a [u8]) -> Graphemes<'a> { + Graphemes { bs } + } + + /// View the underlying data as a subslice of the original data. + /// + /// The slice returned has the same lifetime as the original slice, and so + /// the iterator can continue to be used while this exists. + /// + /// # Examples + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let mut it = b"abc".graphemes(); + /// + /// assert_eq!(b"abc", it.as_bytes()); + /// it.next(); + /// assert_eq!(b"bc", it.as_bytes()); + /// it.next(); + /// it.next(); + /// assert_eq!(b"", it.as_bytes()); + /// ``` + #[inline] + pub fn as_bytes(&self) -> &'a [u8] { + self.bs + } +} + +impl<'a> Iterator for Graphemes<'a> { + type Item = &'a str; + + #[inline] + fn next(&mut self) -> Option<&'a str> { + let (grapheme, size) = decode_grapheme(self.bs); + if size == 0 { + return None; + } + self.bs = &self.bs[size..]; + Some(grapheme) + } +} + +impl<'a> DoubleEndedIterator for Graphemes<'a> { + #[inline] + fn next_back(&mut self) -> Option<&'a str> { + let (grapheme, size) = decode_last_grapheme(self.bs); + if size == 0 { + return None; + } + self.bs = &self.bs[..self.bs.len() - size]; + Some(grapheme) + } +} + +/// An iterator over grapheme clusters in a byte string and their byte index +/// positions. +/// +/// This iterator is typically constructed by +/// [`ByteSlice::grapheme_indices`](trait.ByteSlice.html#method.grapheme_indices). +/// +/// Unicode defines a grapheme cluster as an *approximation* to a single user +/// visible character. A grapheme cluster, or just "grapheme," is made up of +/// one or more codepoints. For end user oriented tasks, one should generally +/// prefer using graphemes instead of [`Chars`](struct.Chars.html), which +/// always yields one codepoint at a time. +/// +/// Since graphemes are made up of one or more codepoints, this iterator +/// yields `&str` elements (along with their start and end byte offsets). +/// When invalid UTF-8 is encountered, replacement codepoints are +/// [substituted](index.html#handling-of-invalid-utf-8). Because of this, the +/// indices yielded by this iterator may not correspond to the length of the +/// grapheme cluster yielded with those indices. For example, when this +/// iterator encounters `\xFF` in the byte string, then it will yield a pair +/// of indices ranging over a single byte, but will provide an `&str` +/// equivalent to `"\u{FFFD}"`, which is three bytes in length. However, when +/// given only valid UTF-8, then all indices are in exact correspondence with +/// their paired grapheme cluster. +/// +/// This iterator can be used in reverse. When reversed, exactly the same +/// set of grapheme clusters are yielded, but in reverse order. +/// +/// This iterator only yields *extended* grapheme clusters, in accordance with +/// [UAX #29](https://www.unicode.org/reports/tr29/tr29-33.html#Grapheme_Cluster_Boundaries). +#[derive(Clone, Debug)] +pub struct GraphemeIndices<'a> { + bs: &'a [u8], + forward_index: usize, + reverse_index: usize, +} + +impl<'a> GraphemeIndices<'a> { + pub(crate) fn new(bs: &'a [u8]) -> GraphemeIndices<'a> { + GraphemeIndices { bs: bs, forward_index: 0, reverse_index: bs.len() } + } + + /// View the underlying data as a subslice of the original data. + /// + /// The slice returned has the same lifetime as the original slice, and so + /// the iterator can continue to be used while this exists. + /// + /// # Examples + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let mut it = b"abc".grapheme_indices(); + /// + /// assert_eq!(b"abc", it.as_bytes()); + /// it.next(); + /// assert_eq!(b"bc", it.as_bytes()); + /// it.next(); + /// it.next(); + /// assert_eq!(b"", it.as_bytes()); + /// ``` + #[inline] + pub fn as_bytes(&self) -> &'a [u8] { + self.bs + } +} + +impl<'a> Iterator for GraphemeIndices<'a> { + type Item = (usize, usize, &'a str); + + #[inline] + fn next(&mut self) -> Option<(usize, usize, &'a str)> { + let index = self.forward_index; + let (grapheme, size) = decode_grapheme(self.bs); + if size == 0 { + return None; + } + self.bs = &self.bs[size..]; + self.forward_index += size; + Some((index, index + size, grapheme)) + } +} + +impl<'a> DoubleEndedIterator for GraphemeIndices<'a> { + #[inline] + fn next_back(&mut self) -> Option<(usize, usize, &'a str)> { + let (grapheme, size) = decode_last_grapheme(self.bs); + if size == 0 { + return None; + } + self.bs = &self.bs[..self.bs.len() - size]; + self.reverse_index -= size; + Some((self.reverse_index, self.reverse_index + size, grapheme)) + } +} + +/// Decode a grapheme from the given byte string. +/// +/// This returns the resulting grapheme (which may be a Unicode replacement +/// codepoint if invalid UTF-8 was found), along with the number of bytes +/// decoded in the byte string. The number of bytes decoded may not be the +/// same as the length of grapheme in the case where invalid UTF-8 is found. +pub fn decode_grapheme(bs: &[u8]) -> (&str, usize) { + if bs.is_empty() { + ("", 0) + } else if let Some(end) = GRAPHEME_BREAK_FWD.find(bs) { + // Safe because a match can only occur for valid UTF-8. + let grapheme = unsafe { bs[..end].to_str_unchecked() }; + (grapheme, grapheme.len()) + } else { + const INVALID: &'static str = "\u{FFFD}"; + // No match on non-empty bytes implies we found invalid UTF-8. + let (_, size) = utf8::decode_lossy(bs); + (INVALID, size) + } +} + +fn decode_last_grapheme(bs: &[u8]) -> (&str, usize) { + if bs.is_empty() { + ("", 0) + } else if let Some(mut start) = GRAPHEME_BREAK_REV.rfind(bs) { + start = adjust_rev_for_regional_indicator(bs, start); + // Safe because a match can only occur for valid UTF-8. + let grapheme = unsafe { bs[start..].to_str_unchecked() }; + (grapheme, grapheme.len()) + } else { + const INVALID: &'static str = "\u{FFFD}"; + // No match on non-empty bytes implies we found invalid UTF-8. + let (_, size) = utf8::decode_last_lossy(bs); + (INVALID, size) + } +} + +/// Return the correct offset for the next grapheme decoded at the end of the +/// given byte string, where `i` is the initial guess. In particular, +/// `&bs[i..]` represents the candidate grapheme. +/// +/// `i` is returned by this function in all cases except when `&bs[i..]` is +/// a pair of regional indicator codepoints. In that case, if an odd number of +/// additional regional indicator codepoints precedes `i`, then `i` is +/// adjusted such that it points to only a single regional indicator. +/// +/// This "fixing" is necessary to handle the requirement that a break cannot +/// occur between regional indicators where it would cause an odd number of +/// regional indicators to exist before the break from the *start* of the +/// string. A reverse regex cannot detect this case easily without look-around. +fn adjust_rev_for_regional_indicator(mut bs: &[u8], i: usize) -> usize { + // All regional indicators use a 4 byte encoding, and we only care about + // the case where we found a pair of regional indicators. + if bs.len() - i != 8 { + return i; + } + // Count all contiguous occurrences of regional indicators. If there's an + // even number of them, then we can accept the pair we found. Otherwise, + // we can only take one of them. + // + // FIXME: This is quadratic in the worst case, e.g., a string of just + // regional indicator codepoints. A fix probably requires refactoring this + // code a bit such that we don't rescan regional indicators. + let mut count = 0; + while let Some(start) = REGIONAL_INDICATOR_REV.rfind(bs) { + bs = &bs[..start]; + count += 1; + } + if count % 2 == 0 { + i + } else { + i + 4 + } +} + +#[cfg(test)] +mod tests { + use ucd_parse::GraphemeClusterBreakTest; + + use super::*; + use ext_slice::ByteSlice; + use tests::LOSSY_TESTS; + + #[test] + fn forward_ucd() { + for (i, test) in ucdtests().into_iter().enumerate() { + let given = test.grapheme_clusters.concat(); + let got: Vec = Graphemes::new(given.as_bytes()) + .map(|cluster| cluster.to_string()) + .collect(); + assert_eq!( + test.grapheme_clusters, + got, + "\ngrapheme forward break test {} failed:\n\ + given: {:?}\n\ + expected: {:?}\n\ + got: {:?}\n", + i, + uniescape(&given), + uniescape_vec(&test.grapheme_clusters), + uniescape_vec(&got), + ); + } + } + + #[test] + fn reverse_ucd() { + for (i, test) in ucdtests().into_iter().enumerate() { + let given = test.grapheme_clusters.concat(); + let mut got: Vec = Graphemes::new(given.as_bytes()) + .rev() + .map(|cluster| cluster.to_string()) + .collect(); + got.reverse(); + assert_eq!( + test.grapheme_clusters, + got, + "\n\ngrapheme reverse break test {} failed:\n\ + given: {:?}\n\ + expected: {:?}\n\ + got: {:?}\n", + i, + uniescape(&given), + uniescape_vec(&test.grapheme_clusters), + uniescape_vec(&got), + ); + } + } + + #[test] + fn forward_lossy() { + for &(expected, input) in LOSSY_TESTS { + let got = Graphemes::new(input.as_bytes()).collect::(); + assert_eq!(expected, got); + } + } + + #[test] + fn reverse_lossy() { + for &(expected, input) in LOSSY_TESTS { + let expected: String = expected.chars().rev().collect(); + let got = + Graphemes::new(input.as_bytes()).rev().collect::(); + assert_eq!(expected, got); + } + } + + fn uniescape(s: &str) -> String { + s.chars().flat_map(|c| c.escape_unicode()).collect::() + } + + fn uniescape_vec(strs: &[String]) -> Vec { + strs.iter().map(|s| uniescape(s)).collect() + } + + /// Return all of the UCD for grapheme breaks. + fn ucdtests() -> Vec { + const TESTDATA: &'static str = + include_str!("data/GraphemeBreakTest.txt"); + + let mut tests = vec![]; + for mut line in TESTDATA.lines() { + line = line.trim(); + if line.starts_with("#") || line.contains("surrogate") { + continue; + } + tests.push(line.parse().unwrap()); + } + tests + } +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/mod.rs b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/mod.rs new file mode 100644 index 0000000..60318f4 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/mod.rs @@ -0,0 +1,12 @@ +pub use self::grapheme::{decode_grapheme, GraphemeIndices, Graphemes}; +pub use self::sentence::{SentenceIndices, Sentences}; +pub use self::whitespace::{whitespace_len_fwd, whitespace_len_rev}; +pub use self::word::{ + WordIndices, Words, WordsWithBreakIndices, WordsWithBreaks, +}; + +mod fsm; +mod grapheme; +mod sentence; +mod whitespace; +mod word; diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/sentence.rs b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/sentence.rs new file mode 100644 index 0000000..01f5473 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/sentence.rs @@ -0,0 +1,220 @@ +use regex_automata::DFA; + +use ext_slice::ByteSlice; +use unicode::fsm::sentence_break_fwd::SENTENCE_BREAK_FWD; +use utf8; + +/// An iterator over sentences in a byte string. +/// +/// This iterator is typically constructed by +/// [`ByteSlice::sentences`](trait.ByteSlice.html#method.sentences). +/// +/// Sentences typically include their trailing punctuation and whitespace. +/// +/// Since sentences are made up of one or more codepoints, this iterator yields +/// `&str` elements. When invalid UTF-8 is encountered, replacement codepoints +/// are [substituted](index.html#handling-of-invalid-utf-8). +/// +/// This iterator yields words in accordance with the default sentence boundary +/// rules specified in +/// [UAX #29](https://www.unicode.org/reports/tr29/tr29-33.html#Sentence_Boundaries). +#[derive(Clone, Debug)] +pub struct Sentences<'a> { + bs: &'a [u8], +} + +impl<'a> Sentences<'a> { + pub(crate) fn new(bs: &'a [u8]) -> Sentences<'a> { + Sentences { bs } + } + + /// View the underlying data as a subslice of the original data. + /// + /// The slice returned has the same lifetime as the original slice, and so + /// the iterator can continue to be used while this exists. + /// + /// # Examples + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let mut it = b"I want this. Not that. Right now.".sentences(); + /// + /// assert_eq!(&b"I want this. Not that. Right now."[..], it.as_bytes()); + /// it.next(); + /// assert_eq!(b"Not that. Right now.", it.as_bytes()); + /// it.next(); + /// it.next(); + /// assert_eq!(b"", it.as_bytes()); + /// ``` + #[inline] + pub fn as_bytes(&self) -> &'a [u8] { + self.bs + } +} + +impl<'a> Iterator for Sentences<'a> { + type Item = &'a str; + + #[inline] + fn next(&mut self) -> Option<&'a str> { + let (sentence, size) = decode_sentence(self.bs); + if size == 0 { + return None; + } + self.bs = &self.bs[size..]; + Some(sentence) + } +} + +/// An iterator over sentences in a byte string, along with their byte offsets. +/// +/// This iterator is typically constructed by +/// [`ByteSlice::sentence_indices`](trait.ByteSlice.html#method.sentence_indices). +/// +/// Sentences typically include their trailing punctuation and whitespace. +/// +/// Since sentences are made up of one or more codepoints, this iterator +/// yields `&str` elements (along with their start and end byte offsets). +/// When invalid UTF-8 is encountered, replacement codepoints are +/// [substituted](index.html#handling-of-invalid-utf-8). Because of this, the +/// indices yielded by this iterator may not correspond to the length of the +/// sentence yielded with those indices. For example, when this iterator +/// encounters `\xFF` in the byte string, then it will yield a pair of indices +/// ranging over a single byte, but will provide an `&str` equivalent to +/// `"\u{FFFD}"`, which is three bytes in length. However, when given only +/// valid UTF-8, then all indices are in exact correspondence with their paired +/// word. +/// +/// This iterator yields words in accordance with the default sentence boundary +/// rules specified in +/// [UAX #29](https://www.unicode.org/reports/tr29/tr29-33.html#Sentence_Boundaries). +#[derive(Clone, Debug)] +pub struct SentenceIndices<'a> { + bs: &'a [u8], + forward_index: usize, +} + +impl<'a> SentenceIndices<'a> { + pub(crate) fn new(bs: &'a [u8]) -> SentenceIndices<'a> { + SentenceIndices { bs: bs, forward_index: 0 } + } + + /// View the underlying data as a subslice of the original data. + /// + /// The slice returned has the same lifetime as the original slice, and so + /// the iterator can continue to be used while this exists. + /// + /// # Examples + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let mut it = b"I want this. Not that. Right now.".sentence_indices(); + /// + /// assert_eq!(&b"I want this. Not that. Right now."[..], it.as_bytes()); + /// it.next(); + /// assert_eq!(b"Not that. Right now.", it.as_bytes()); + /// it.next(); + /// it.next(); + /// assert_eq!(b"", it.as_bytes()); + /// ``` + #[inline] + pub fn as_bytes(&self) -> &'a [u8] { + self.bs + } +} + +impl<'a> Iterator for SentenceIndices<'a> { + type Item = (usize, usize, &'a str); + + #[inline] + fn next(&mut self) -> Option<(usize, usize, &'a str)> { + let index = self.forward_index; + let (word, size) = decode_sentence(self.bs); + if size == 0 { + return None; + } + self.bs = &self.bs[size..]; + self.forward_index += size; + Some((index, index + size, word)) + } +} + +fn decode_sentence(bs: &[u8]) -> (&str, usize) { + if bs.is_empty() { + ("", 0) + } else if let Some(end) = SENTENCE_BREAK_FWD.find(bs) { + // Safe because a match can only occur for valid UTF-8. + let sentence = unsafe { bs[..end].to_str_unchecked() }; + (sentence, sentence.len()) + } else { + const INVALID: &'static str = "\u{FFFD}"; + // No match on non-empty bytes implies we found invalid UTF-8. + let (_, size) = utf8::decode_lossy(bs); + (INVALID, size) + } +} + +#[cfg(test)] +mod tests { + use ucd_parse::SentenceBreakTest; + + use ext_slice::ByteSlice; + + #[test] + fn forward_ucd() { + for (i, test) in ucdtests().into_iter().enumerate() { + let given = test.sentences.concat(); + let got = sentences(given.as_bytes()); + assert_eq!( + test.sentences, + got, + "\n\nsentence forward break test {} failed:\n\ + given: {:?}\n\ + expected: {:?}\n\ + got: {:?}\n", + i, + given, + strs_to_bstrs(&test.sentences), + strs_to_bstrs(&got), + ); + } + } + + // Some additional tests that don't seem to be covered by the UCD tests. + #[test] + fn forward_additional() { + assert_eq!(vec!["a.. ", "A"], sentences(b"a.. A")); + assert_eq!(vec!["a.. a"], sentences(b"a.. a")); + + assert_eq!(vec!["a... ", "A"], sentences(b"a... A")); + assert_eq!(vec!["a... a"], sentences(b"a... a")); + + assert_eq!(vec!["a...,..., a"], sentences(b"a...,..., a")); + } + + fn sentences(bytes: &[u8]) -> Vec<&str> { + bytes.sentences().collect() + } + + fn strs_to_bstrs>(strs: &[S]) -> Vec<&[u8]> { + strs.iter().map(|s| s.as_ref().as_bytes()).collect() + } + + /// Return all of the UCD for sentence breaks. + fn ucdtests() -> Vec { + const TESTDATA: &'static str = + include_str!("data/SentenceBreakTest.txt"); + + let mut tests = vec![]; + for mut line in TESTDATA.lines() { + line = line.trim(); + if line.starts_with("#") || line.contains("surrogate") { + continue; + } + tests.push(line.parse().unwrap()); + } + tests + } +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/whitespace.rs b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/whitespace.rs new file mode 100644 index 0000000..a8da144 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/whitespace.rs @@ -0,0 +1,14 @@ +use regex_automata::DFA; + +use unicode::fsm::whitespace_anchored_fwd::WHITESPACE_ANCHORED_FWD; +use unicode::fsm::whitespace_anchored_rev::WHITESPACE_ANCHORED_REV; + +/// Return the first position of a non-whitespace character. +pub fn whitespace_len_fwd(slice: &[u8]) -> usize { + WHITESPACE_ANCHORED_FWD.find(slice).unwrap_or(0) +} + +/// Return the last position of a non-whitespace character. +pub fn whitespace_len_rev(slice: &[u8]) -> usize { + WHITESPACE_ANCHORED_REV.rfind(slice).unwrap_or(slice.len()) +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/unicode/word.rs b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/word.rs new file mode 100644 index 0000000..1260e52 --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/unicode/word.rs @@ -0,0 +1,406 @@ +use regex_automata::DFA; + +use ext_slice::ByteSlice; +use unicode::fsm::simple_word_fwd::SIMPLE_WORD_FWD; +use unicode::fsm::word_break_fwd::WORD_BREAK_FWD; +use utf8; + +/// An iterator over words in a byte string. +/// +/// This iterator is typically constructed by +/// [`ByteSlice::words`](trait.ByteSlice.html#method.words). +/// +/// This is similar to the [`WordsWithBreaks`](struct.WordsWithBreaks.html) +/// iterator, except it only returns elements that contain a "word" character. +/// A word character is defined by UTS #18 (Annex C) to be the combination +/// of the `Alphabetic` and `Join_Control` properties, along with the +/// `Decimal_Number`, `Mark` and `Connector_Punctuation` general categories. +/// +/// Since words are made up of one or more codepoints, this iterator yields +/// `&str` elements. When invalid UTF-8 is encountered, replacement codepoints +/// are [substituted](index.html#handling-of-invalid-utf-8). +/// +/// This iterator yields words in accordance with the default word boundary +/// rules specified in +/// [UAX #29](https://www.unicode.org/reports/tr29/tr29-33.html#Word_Boundaries). +/// In particular, this may not be suitable for Japanese and Chinese scripts +/// that do not use spaces between words. +#[derive(Clone, Debug)] +pub struct Words<'a>(WordsWithBreaks<'a>); + +impl<'a> Words<'a> { + pub(crate) fn new(bs: &'a [u8]) -> Words<'a> { + Words(WordsWithBreaks::new(bs)) + } + + /// View the underlying data as a subslice of the original data. + /// + /// The slice returned has the same lifetime as the original slice, and so + /// the iterator can continue to be used while this exists. + /// + /// # Examples + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let mut it = b"foo bar baz".words(); + /// + /// assert_eq!(b"foo bar baz", it.as_bytes()); + /// it.next(); + /// it.next(); + /// assert_eq!(b" baz", it.as_bytes()); + /// it.next(); + /// assert_eq!(b"", it.as_bytes()); + /// ``` + #[inline] + pub fn as_bytes(&self) -> &'a [u8] { + self.0.as_bytes() + } +} + +impl<'a> Iterator for Words<'a> { + type Item = &'a str; + + #[inline] + fn next(&mut self) -> Option<&'a str> { + while let Some(word) = self.0.next() { + if SIMPLE_WORD_FWD.is_match(word.as_bytes()) { + return Some(word); + } + } + None + } +} + +/// An iterator over words in a byte string and their byte index positions. +/// +/// This iterator is typically constructed by +/// [`ByteSlice::word_indices`](trait.ByteSlice.html#method.word_indices). +/// +/// This is similar to the +/// [`WordsWithBreakIndices`](struct.WordsWithBreakIndices.html) iterator, +/// except it only returns elements that contain a "word" character. A +/// word character is defined by UTS #18 (Annex C) to be the combination +/// of the `Alphabetic` and `Join_Control` properties, along with the +/// `Decimal_Number`, `Mark` and `Connector_Punctuation` general categories. +/// +/// Since words are made up of one or more codepoints, this iterator +/// yields `&str` elements (along with their start and end byte offsets). +/// When invalid UTF-8 is encountered, replacement codepoints are +/// [substituted](index.html#handling-of-invalid-utf-8). Because of this, the +/// indices yielded by this iterator may not correspond to the length of the +/// word yielded with those indices. For example, when this iterator encounters +/// `\xFF` in the byte string, then it will yield a pair of indices ranging +/// over a single byte, but will provide an `&str` equivalent to `"\u{FFFD}"`, +/// which is three bytes in length. However, when given only valid UTF-8, then +/// all indices are in exact correspondence with their paired word. +/// +/// This iterator yields words in accordance with the default word boundary +/// rules specified in +/// [UAX #29](https://www.unicode.org/reports/tr29/tr29-33.html#Word_Boundaries). +/// In particular, this may not be suitable for Japanese and Chinese scripts +/// that do not use spaces between words. +#[derive(Clone, Debug)] +pub struct WordIndices<'a>(WordsWithBreakIndices<'a>); + +impl<'a> WordIndices<'a> { + pub(crate) fn new(bs: &'a [u8]) -> WordIndices<'a> { + WordIndices(WordsWithBreakIndices::new(bs)) + } + + /// View the underlying data as a subslice of the original data. + /// + /// The slice returned has the same lifetime as the original slice, and so + /// the iterator can continue to be used while this exists. + /// + /// # Examples + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let mut it = b"foo bar baz".word_indices(); + /// + /// assert_eq!(b"foo bar baz", it.as_bytes()); + /// it.next(); + /// it.next(); + /// assert_eq!(b" baz", it.as_bytes()); + /// it.next(); + /// it.next(); + /// assert_eq!(b"", it.as_bytes()); + /// ``` + #[inline] + pub fn as_bytes(&self) -> &'a [u8] { + self.0.as_bytes() + } +} + +impl<'a> Iterator for WordIndices<'a> { + type Item = (usize, usize, &'a str); + + #[inline] + fn next(&mut self) -> Option<(usize, usize, &'a str)> { + while let Some((start, end, word)) = self.0.next() { + if SIMPLE_WORD_FWD.is_match(word.as_bytes()) { + return Some((start, end, word)); + } + } + None + } +} + +/// An iterator over all word breaks in a byte string. +/// +/// This iterator is typically constructed by +/// [`ByteSlice::words_with_breaks`](trait.ByteSlice.html#method.words_with_breaks). +/// +/// This iterator yields not only all words, but the content that comes between +/// words. In particular, if all elements yielded by this iterator are +/// concatenated, then the result is the original string (subject to Unicode +/// replacement codepoint substitutions). +/// +/// Since words are made up of one or more codepoints, this iterator yields +/// `&str` elements. When invalid UTF-8 is encountered, replacement codepoints +/// are [substituted](index.html#handling-of-invalid-utf-8). +/// +/// This iterator yields words in accordance with the default word boundary +/// rules specified in +/// [UAX #29](https://www.unicode.org/reports/tr29/tr29-33.html#Word_Boundaries). +/// In particular, this may not be suitable for Japanese and Chinese scripts +/// that do not use spaces between words. +#[derive(Clone, Debug)] +pub struct WordsWithBreaks<'a> { + bs: &'a [u8], +} + +impl<'a> WordsWithBreaks<'a> { + pub(crate) fn new(bs: &'a [u8]) -> WordsWithBreaks<'a> { + WordsWithBreaks { bs } + } + + /// View the underlying data as a subslice of the original data. + /// + /// The slice returned has the same lifetime as the original slice, and so + /// the iterator can continue to be used while this exists. + /// + /// # Examples + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let mut it = b"foo bar baz".words_with_breaks(); + /// + /// assert_eq!(b"foo bar baz", it.as_bytes()); + /// it.next(); + /// assert_eq!(b" bar baz", it.as_bytes()); + /// it.next(); + /// it.next(); + /// assert_eq!(b" baz", it.as_bytes()); + /// it.next(); + /// it.next(); + /// assert_eq!(b"", it.as_bytes()); + /// ``` + #[inline] + pub fn as_bytes(&self) -> &'a [u8] { + self.bs + } +} + +impl<'a> Iterator for WordsWithBreaks<'a> { + type Item = &'a str; + + #[inline] + fn next(&mut self) -> Option<&'a str> { + let (word, size) = decode_word(self.bs); + if size == 0 { + return None; + } + self.bs = &self.bs[size..]; + Some(word) + } +} + +/// An iterator over all word breaks in a byte string, along with their byte +/// index positions. +/// +/// This iterator is typically constructed by +/// [`ByteSlice::words_with_break_indices`](trait.ByteSlice.html#method.words_with_break_indices). +/// +/// This iterator yields not only all words, but the content that comes between +/// words. In particular, if all elements yielded by this iterator are +/// concatenated, then the result is the original string (subject to Unicode +/// replacement codepoint substitutions). +/// +/// Since words are made up of one or more codepoints, this iterator +/// yields `&str` elements (along with their start and end byte offsets). +/// When invalid UTF-8 is encountered, replacement codepoints are +/// [substituted](index.html#handling-of-invalid-utf-8). Because of this, the +/// indices yielded by this iterator may not correspond to the length of the +/// word yielded with those indices. For example, when this iterator encounters +/// `\xFF` in the byte string, then it will yield a pair of indices ranging +/// over a single byte, but will provide an `&str` equivalent to `"\u{FFFD}"`, +/// which is three bytes in length. However, when given only valid UTF-8, then +/// all indices are in exact correspondence with their paired word. +/// +/// This iterator yields words in accordance with the default word boundary +/// rules specified in +/// [UAX #29](https://www.unicode.org/reports/tr29/tr29-33.html#Word_Boundaries). +/// In particular, this may not be suitable for Japanese and Chinese scripts +/// that do not use spaces between words. +#[derive(Clone, Debug)] +pub struct WordsWithBreakIndices<'a> { + bs: &'a [u8], + forward_index: usize, +} + +impl<'a> WordsWithBreakIndices<'a> { + pub(crate) fn new(bs: &'a [u8]) -> WordsWithBreakIndices<'a> { + WordsWithBreakIndices { bs: bs, forward_index: 0 } + } + + /// View the underlying data as a subslice of the original data. + /// + /// The slice returned has the same lifetime as the original slice, and so + /// the iterator can continue to be used while this exists. + /// + /// # Examples + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let mut it = b"foo bar baz".words_with_break_indices(); + /// + /// assert_eq!(b"foo bar baz", it.as_bytes()); + /// it.next(); + /// assert_eq!(b" bar baz", it.as_bytes()); + /// it.next(); + /// it.next(); + /// assert_eq!(b" baz", it.as_bytes()); + /// it.next(); + /// it.next(); + /// assert_eq!(b"", it.as_bytes()); + /// ``` + #[inline] + pub fn as_bytes(&self) -> &'a [u8] { + self.bs + } +} + +impl<'a> Iterator for WordsWithBreakIndices<'a> { + type Item = (usize, usize, &'a str); + + #[inline] + fn next(&mut self) -> Option<(usize, usize, &'a str)> { + let index = self.forward_index; + let (word, size) = decode_word(self.bs); + if size == 0 { + return None; + } + self.bs = &self.bs[size..]; + self.forward_index += size; + Some((index, index + size, word)) + } +} + +fn decode_word(bs: &[u8]) -> (&str, usize) { + if bs.is_empty() { + ("", 0) + } else if let Some(end) = WORD_BREAK_FWD.find(bs) { + // Safe because a match can only occur for valid UTF-8. + let word = unsafe { bs[..end].to_str_unchecked() }; + (word, word.len()) + } else { + const INVALID: &'static str = "\u{FFFD}"; + // No match on non-empty bytes implies we found invalid UTF-8. + let (_, size) = utf8::decode_lossy(bs); + (INVALID, size) + } +} + +#[cfg(test)] +mod tests { + use ucd_parse::WordBreakTest; + + use ext_slice::ByteSlice; + + #[test] + fn forward_ucd() { + for (i, test) in ucdtests().into_iter().enumerate() { + let given = test.words.concat(); + let got = words(given.as_bytes()); + assert_eq!( + test.words, + got, + "\n\nword forward break test {} failed:\n\ + given: {:?}\n\ + expected: {:?}\n\ + got: {:?}\n", + i, + given, + strs_to_bstrs(&test.words), + strs_to_bstrs(&got), + ); + } + } + + // Some additional tests that don't seem to be covered by the UCD tests. + // + // It's pretty amazing that the UCD tests miss these cases. I only found + // them by running this crate's segmenter and ICU's segmenter on the same + // text and comparing the output. + #[test] + fn forward_additional() { + assert_eq!(vec!["a", ".", " ", "Y"], words(b"a. Y")); + assert_eq!(vec!["r", ".", " ", "Yo"], words(b"r. Yo")); + assert_eq!( + vec!["whatsoever", ".", " ", "You", " ", "may"], + words(b"whatsoever. You may") + ); + assert_eq!( + vec!["21stcentury'syesterday"], + words(b"21stcentury'syesterday") + ); + + assert_eq!(vec!["Bonta_", "'", "s"], words(b"Bonta_'s")); + assert_eq!(vec!["_vhat's"], words(b"_vhat's")); + assert_eq!(vec!["__on'anima"], words(b"__on'anima")); + assert_eq!(vec!["123_", "'", "4"], words(b"123_'4")); + assert_eq!(vec!["_123'4"], words(b"_123'4")); + assert_eq!(vec!["__12'345"], words(b"__12'345")); + + assert_eq!( + vec!["tomorrowat4", ":", "00", ","], + words(b"tomorrowat4:00,") + ); + assert_eq!(vec!["RS1", "'", "s"], words(b"RS1's")); + assert_eq!(vec!["X38"], words(b"X38")); + + assert_eq!(vec!["4abc", ":", "00", ","], words(b"4abc:00,")); + assert_eq!(vec!["12S", "'", "1"], words(b"12S'1")); + assert_eq!(vec!["1XY"], words(b"1XY")); + + assert_eq!(vec!["\u{FEFF}", "Ты"], words("\u{FEFF}Ты".as_bytes())); + } + + fn words(bytes: &[u8]) -> Vec<&str> { + bytes.words_with_breaks().collect() + } + + fn strs_to_bstrs>(strs: &[S]) -> Vec<&[u8]> { + strs.iter().map(|s| s.as_ref().as_bytes()).collect() + } + + /// Return all of the UCD for word breaks. + fn ucdtests() -> Vec { + const TESTDATA: &'static str = include_str!("data/WordBreakTest.txt"); + + let mut tests = vec![]; + for mut line in TESTDATA.lines() { + line = line.trim(); + if line.starts_with("#") || line.contains("surrogate") { + continue; + } + tests.push(line.parse().unwrap()); + } + tests + } +} diff --git a/third_party/cargo/vendor/bstr-0.2.15/src/utf8.rs b/third_party/cargo/vendor/bstr-0.2.15/src/utf8.rs new file mode 100644 index 0000000..2d4035d --- /dev/null +++ b/third_party/cargo/vendor/bstr-0.2.15/src/utf8.rs @@ -0,0 +1,1370 @@ +use core::char; +use core::cmp; +use core::fmt; +use core::str; +#[cfg(feature = "std")] +use std::error; + +use ascii; +use bstr::BStr; +use ext_slice::ByteSlice; + +// The UTF-8 decoder provided here is based on the one presented here: +// https://bjoern.hoehrmann.de/utf-8/decoder/dfa/ +// +// We *could* have done UTF-8 decoding by using a DFA generated by `\p{any}` +// using regex-automata that is roughly the same size. The real benefit of +// Hoehrmann's formulation is that the byte class mapping below is manually +// tailored such that each byte's class doubles as a shift to mask out the +// bits necessary for constructing the leading bits of each codepoint value +// from the initial byte. +// +// There are some minor differences between this implementation and Hoehrmann's +// formulation. +// +// Firstly, we make REJECT have state ID 0, since it makes the state table +// itself a little easier to read and is consistent with the notion that 0 +// means "false" or "bad." +// +// Secondly, when doing bulk decoding, we add a SIMD accelerated ASCII fast +// path. +// +// Thirdly, we pre-multiply the state IDs to avoid a multiplication instruction +// in the core decoding loop. (Which is what regex-automata would do by +// default.) +// +// Fourthly, we split the byte class mapping and transition table into two +// arrays because it's clearer. +// +// It is unlikely that this is the fastest way to do UTF-8 decoding, however, +// it is fairly simple. + +const ACCEPT: usize = 12; +const REJECT: usize = 0; + +/// SAFETY: The decode below function relies on the correctness of these +/// equivalence classes. +#[cfg_attr(rustfmt, rustfmt::skip)] +const CLASSES: [u8; 256] = [ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, +]; + +/// SAFETY: The decode below function relies on the correctness of this state +/// machine. +#[cfg_attr(rustfmt, rustfmt::skip)] +const STATES_FORWARD: &'static [u8] = &[ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 12, 0, 24, 36, 60, 96, 84, 0, 0, 0, 48, 72, + 0, 12, 0, 0, 0, 0, 0, 12, 0, 12, 0, 0, + 0, 24, 0, 0, 0, 0, 0, 24, 0, 24, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, + 0, 24, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 36, 0, 36, 0, 0, + 0, 36, 0, 0, 0, 0, 0, 36, 0, 36, 0, 0, + 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +]; + +/// An iterator over Unicode scalar values in a byte string. +/// +/// When invalid UTF-8 byte sequences are found, they are substituted with the +/// Unicode replacement codepoint (`U+FFFD`) using the +/// ["maximal subpart" strategy](http://www.unicode.org/review/pr-121.html). +/// +/// This iterator is created by the +/// [`chars`](trait.ByteSlice.html#method.chars) method provided by the +/// [`ByteSlice`](trait.ByteSlice.html) extension trait for `&[u8]`. +#[derive(Clone, Debug)] +pub struct Chars<'a> { + bs: &'a [u8], +} + +impl<'a> Chars<'a> { + pub(crate) fn new(bs: &'a [u8]) -> Chars<'a> { + Chars { bs } + } + + /// View the underlying data as a subslice of the original data. + /// + /// The slice returned has the same lifetime as the original slice, and so + /// the iterator can continue to be used while this exists. + /// + /// # Examples + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let mut chars = b"abc".chars(); + /// + /// assert_eq!(b"abc", chars.as_bytes()); + /// chars.next(); + /// assert_eq!(b"bc", chars.as_bytes()); + /// chars.next(); + /// chars.next(); + /// assert_eq!(b"", chars.as_bytes()); + /// ``` + #[inline] + pub fn as_bytes(&self) -> &'a [u8] { + self.bs + } +} + +impl<'a> Iterator for Chars<'a> { + type Item = char; + + #[inline] + fn next(&mut self) -> Option { + let (ch, size) = decode_lossy(self.bs); + if size == 0 { + return None; + } + self.bs = &self.bs[size..]; + Some(ch) + } +} + +impl<'a> DoubleEndedIterator for Chars<'a> { + #[inline] + fn next_back(&mut self) -> Option { + let (ch, size) = decode_last_lossy(self.bs); + if size == 0 { + return None; + } + self.bs = &self.bs[..self.bs.len() - size]; + Some(ch) + } +} + +/// An iterator over Unicode scalar values in a byte string and their +/// byte index positions. +/// +/// When invalid UTF-8 byte sequences are found, they are substituted with the +/// Unicode replacement codepoint (`U+FFFD`) using the +/// ["maximal subpart" strategy](http://www.unicode.org/review/pr-121.html). +/// +/// Note that this is slightly different from the `CharIndices` iterator +/// provided by the standard library. Aside from working on possibly invalid +/// UTF-8, this iterator provides both the corresponding starting and ending +/// byte indices of each codepoint yielded. The ending position is necessary to +/// slice the original byte string when invalid UTF-8 bytes are converted into +/// a Unicode replacement codepoint, since a single replacement codepoint can +/// substitute anywhere from 1 to 3 invalid bytes (inclusive). +/// +/// This iterator is created by the +/// [`char_indices`](trait.ByteSlice.html#method.char_indices) method provided +/// by the [`ByteSlice`](trait.ByteSlice.html) extension trait for `&[u8]`. +#[derive(Clone, Debug)] +pub struct CharIndices<'a> { + bs: &'a [u8], + forward_index: usize, + reverse_index: usize, +} + +impl<'a> CharIndices<'a> { + pub(crate) fn new(bs: &'a [u8]) -> CharIndices<'a> { + CharIndices { bs: bs, forward_index: 0, reverse_index: bs.len() } + } + + /// View the underlying data as a subslice of the original data. + /// + /// The slice returned has the same lifetime as the original slice, and so + /// the iterator can continue to be used while this exists. + /// + /// # Examples + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let mut it = b"abc".char_indices(); + /// + /// assert_eq!(b"abc", it.as_bytes()); + /// it.next(); + /// assert_eq!(b"bc", it.as_bytes()); + /// it.next(); + /// it.next(); + /// assert_eq!(b"", it.as_bytes()); + /// ``` + #[inline] + pub fn as_bytes(&self) -> &'a [u8] { + self.bs + } +} + +impl<'a> Iterator for CharIndices<'a> { + type Item = (usize, usize, char); + + #[inline] + fn next(&mut self) -> Option<(usize, usize, char)> { + let index = self.forward_index; + let (ch, size) = decode_lossy(self.bs); + if size == 0 { + return None; + } + self.bs = &self.bs[size..]; + self.forward_index += size; + Some((index, index + size, ch)) + } +} + +impl<'a> DoubleEndedIterator for CharIndices<'a> { + #[inline] + fn next_back(&mut self) -> Option<(usize, usize, char)> { + let (ch, size) = decode_last_lossy(self.bs); + if size == 0 { + return None; + } + self.bs = &self.bs[..self.bs.len() - size]; + self.reverse_index -= size; + Some((self.reverse_index, self.reverse_index + size, ch)) + } +} + +impl<'a> ::core::iter::FusedIterator for CharIndices<'a> {} + +/// An iterator over chunks of valid UTF-8 in a byte slice. +/// +/// See [`utf8_chunks`](trait.ByteSlice.html#method.utf8_chunks). +#[derive(Clone, Debug)] +pub struct Utf8Chunks<'a> { + pub(super) bytes: &'a [u8], +} + +/// A chunk of valid UTF-8, possibly followed by invalid UTF-8 bytes. +/// +/// This is yielded by the +/// [`Utf8Chunks`](struct.Utf8Chunks.html) +/// iterator, which can be created via the +/// [`ByteSlice::utf8_chunks`](trait.ByteSlice.html#method.utf8_chunks) +/// method. +/// +/// The `'a` lifetime parameter corresponds to the lifetime of the bytes that +/// are being iterated over. +#[cfg_attr(test, derive(Debug, PartialEq))] +pub struct Utf8Chunk<'a> { + /// A valid UTF-8 piece, at the start, end, or between invalid UTF-8 bytes. + /// + /// This is empty between adjacent invalid UTF-8 byte sequences. + valid: &'a str, + /// A sequence of invalid UTF-8 bytes. + /// + /// Can only be empty in the last chunk. + /// + /// Should be replaced by a single unicode replacement character, if not + /// empty. + invalid: &'a BStr, + /// Indicates whether the invalid sequence could've been valid if there + /// were more bytes. + /// + /// Can only be true in the last chunk. + incomplete: bool, +} + +impl<'a> Utf8Chunk<'a> { + /// Returns the (possibly empty) valid UTF-8 bytes in this chunk. + /// + /// This may be empty if there are consecutive sequences of invalid UTF-8 + /// bytes. + #[inline] + pub fn valid(&self) -> &'a str { + self.valid + } + + /// Returns the (possibly empty) invalid UTF-8 bytes in this chunk that + /// immediately follow the valid UTF-8 bytes in this chunk. + /// + /// This is only empty when this chunk corresponds to the last chunk in + /// the original bytes. + /// + /// The maximum length of this slice is 3. That is, invalid UTF-8 byte + /// sequences greater than 1 always correspond to a valid _prefix_ of + /// a valid UTF-8 encoded codepoint. This corresponds to the "substitution + /// of maximal subparts" strategy that is described in more detail in the + /// docs for the + /// [`ByteSlice::to_str_lossy`](trait.ByteSlice.html#method.to_str_lossy) + /// method. + #[inline] + pub fn invalid(&self) -> &'a [u8] { + self.invalid.as_bytes() + } + + /// Returns whether the invalid sequence might still become valid if more + /// bytes are added. + /// + /// Returns true if the end of the input was reached unexpectedly, + /// without encountering an unexpected byte. + /// + /// This can only be the case for the last chunk. + #[inline] + pub fn incomplete(&self) -> bool { + self.incomplete + } +} + +impl<'a> Iterator for Utf8Chunks<'a> { + type Item = Utf8Chunk<'a>; + + #[inline] + fn next(&mut self) -> Option> { + if self.bytes.is_empty() { + return None; + } + match validate(self.bytes) { + Ok(()) => { + let valid = self.bytes; + self.bytes = &[]; + Some(Utf8Chunk { + // SAFETY: This is safe because of the guarantees provided + // by utf8::validate. + valid: unsafe { str::from_utf8_unchecked(valid) }, + invalid: [].as_bstr(), + incomplete: false, + }) + } + Err(e) => { + let (valid, rest) = self.bytes.split_at(e.valid_up_to()); + // SAFETY: This is safe because of the guarantees provided by + // utf8::validate. + let valid = unsafe { str::from_utf8_unchecked(valid) }; + let (invalid_len, incomplete) = match e.error_len() { + Some(n) => (n, false), + None => (rest.len(), true), + }; + let (invalid, rest) = rest.split_at(invalid_len); + self.bytes = rest; + Some(Utf8Chunk { + valid, + invalid: invalid.as_bstr(), + incomplete, + }) + } + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + if self.bytes.is_empty() { + (0, Some(0)) + } else { + (1, Some(self.bytes.len())) + } + } +} + +impl<'a> ::core::iter::FusedIterator for Utf8Chunks<'a> {} + +/// An error that occurs when UTF-8 decoding fails. +/// +/// This error occurs when attempting to convert a non-UTF-8 byte +/// string to a Rust string that must be valid UTF-8. For example, +/// [`to_str`](trait.ByteSlice.html#method.to_str) is one such method. +/// +/// # Example +/// +/// This example shows what happens when a given byte sequence is invalid, +/// but ends with a sequence that is a possible prefix of valid UTF-8. +/// +/// ``` +/// use bstr::{B, ByteSlice}; +/// +/// let s = B(b"foobar\xF1\x80\x80"); +/// let err = s.to_str().unwrap_err(); +/// assert_eq!(err.valid_up_to(), 6); +/// assert_eq!(err.error_len(), None); +/// ``` +/// +/// This example shows what happens when a given byte sequence contains +/// invalid UTF-8. +/// +/// ``` +/// use bstr::ByteSlice; +/// +/// let s = b"foobar\xF1\x80\x80quux"; +/// let err = s.to_str().unwrap_err(); +/// assert_eq!(err.valid_up_to(), 6); +/// // The error length reports the maximum number of bytes that correspond to +/// // a valid prefix of a UTF-8 encoded codepoint. +/// assert_eq!(err.error_len(), Some(3)); +/// +/// // In contrast to the above which contains a single invalid prefix, +/// // consider the case of multiple individal bytes that are never valid +/// // prefixes. Note how the value of error_len changes! +/// let s = b"foobar\xFF\xFFquux"; +/// let err = s.to_str().unwrap_err(); +/// assert_eq!(err.valid_up_to(), 6); +/// assert_eq!(err.error_len(), Some(1)); +/// +/// // The fact that it's an invalid prefix does not change error_len even +/// // when it immediately precedes the end of the string. +/// let s = b"foobar\xFF"; +/// let err = s.to_str().unwrap_err(); +/// assert_eq!(err.valid_up_to(), 6); +/// assert_eq!(err.error_len(), Some(1)); +/// ``` +#[derive(Debug, Eq, PartialEq)] +pub struct Utf8Error { + valid_up_to: usize, + error_len: Option, +} + +impl Utf8Error { + /// Returns the byte index of the position immediately following the last + /// valid UTF-8 byte. + /// + /// # Example + /// + /// This examples shows how `valid_up_to` can be used to retrieve a + /// possibly empty prefix that is guaranteed to be valid UTF-8: + /// + /// ``` + /// use bstr::ByteSlice; + /// + /// let s = b"foobar\xF1\x80\x80quux"; + /// let err = s.to_str().unwrap_err(); + /// + /// // This is guaranteed to never panic. + /// let string = s[..err.valid_up_to()].to_str().unwrap(); + /// assert_eq!(string, "foobar"); + /// ``` + #[inline] + pub fn valid_up_to(&self) -> usize { + self.valid_up_to + } + + /// Returns the total number of invalid UTF-8 bytes immediately following + /// the position returned by `valid_up_to`. This value is always at least + /// `1`, but can be up to `3` if bytes form a valid prefix of some UTF-8 + /// encoded codepoint. + /// + /// If the end of the original input was found before a valid UTF-8 encoded + /// codepoint could be completed, then this returns `None`. This is useful + /// when processing streams, where a `None` value signals that more input + /// might be needed. + #[inline] + pub fn error_len(&self) -> Option { + self.error_len + } +} + +#[cfg(feature = "std")] +impl error::Error for Utf8Error { + fn description(&self) -> &str { + "invalid UTF-8" + } +} + +impl fmt::Display for Utf8Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "invalid UTF-8 found at byte offset {}", self.valid_up_to) + } +} + +/// Returns OK if and only if the given slice is completely valid UTF-8. +/// +/// If the slice isn't valid UTF-8, then an error is returned that explains +/// the first location at which invalid UTF-8 was detected. +pub fn validate(slice: &[u8]) -> Result<(), Utf8Error> { + // The fast path for validating UTF-8. It steps through a UTF-8 automaton + // and uses a SIMD accelerated ASCII fast path on x86_64. If an error is + // detected, it backs up and runs the slower version of the UTF-8 automaton + // to determine correct error information. + fn fast(slice: &[u8]) -> Result<(), Utf8Error> { + let mut state = ACCEPT; + let mut i = 0; + + while i < slice.len() { + let b = slice[i]; + + // ASCII fast path. If we see two consecutive ASCII bytes, then try + // to validate as much ASCII as possible very quickly. + if state == ACCEPT + && b <= 0x7F + && slice.get(i + 1).map_or(false, |&b| b <= 0x7F) + { + i += ascii::first_non_ascii_byte(&slice[i..]); + continue; + } + + state = step(state, b); + if state == REJECT { + return Err(find_valid_up_to(slice, i)); + } + i += 1; + } + if state != ACCEPT { + Err(find_valid_up_to(slice, slice.len())) + } else { + Ok(()) + } + } + + // Given the first position at which a UTF-8 sequence was determined to be + // invalid, return an error that correctly reports the position at which + // the last complete UTF-8 sequence ends. + #[inline(never)] + fn find_valid_up_to(slice: &[u8], rejected_at: usize) -> Utf8Error { + // In order to find the last valid byte, we need to back up an amount + // that guarantees every preceding byte is part of a valid UTF-8 + // code unit sequence. To do this, we simply locate the last leading + // byte that occurs before rejected_at. + let mut backup = rejected_at.saturating_sub(1); + while backup > 0 && !is_leading_or_invalid_utf8_byte(slice[backup]) { + backup -= 1; + } + let upto = cmp::min(slice.len(), rejected_at.saturating_add(1)); + let mut err = slow(&slice[backup..upto]).unwrap_err(); + err.valid_up_to += backup; + err + } + + // Like top-level UTF-8 decoding, except it correctly reports a UTF-8 error + // when an invalid sequence is found. This is split out from validate so + // that the fast path doesn't need to keep track of the position of the + // last valid UTF-8 byte. In particular, tracking this requires checking + // for an ACCEPT state on each byte, which degrades throughput pretty + // badly. + fn slow(slice: &[u8]) -> Result<(), Utf8Error> { + let mut state = ACCEPT; + let mut valid_up_to = 0; + for (i, &b) in slice.iter().enumerate() { + state = step(state, b); + if state == ACCEPT { + valid_up_to = i + 1; + } else if state == REJECT { + // Our error length must always be at least 1. + let error_len = Some(cmp::max(1, i - valid_up_to)); + return Err(Utf8Error { valid_up_to, error_len }); + } + } + if state != ACCEPT { + Err(Utf8Error { valid_up_to, error_len: None }) + } else { + Ok(()) + } + } + + // Advance to the next state given the current state and current byte. + fn step(state: usize, b: u8) -> usize { + let class = CLASSES[b as usize]; + // SAFETY: This is safe because 'class' is always <=11 and 'state' is + // always <=96. Therefore, the maximal index is 96+11 = 107, where + // STATES_FORWARD.len() = 108 such that every index is guaranteed to be + // valid by construction of the state machine and the byte equivalence + // classes. + unsafe { + *STATES_FORWARD.get_unchecked(state + class as usize) as usize + } + } + + fast(slice) +} + +/// UTF-8 decode a single Unicode scalar value from the beginning of a slice. +/// +/// When successful, the corresponding Unicode scalar value is returned along +/// with the number of bytes it was encoded with. The number of bytes consumed +/// for a successful decode is always between 1 and 4, inclusive. +/// +/// When unsuccessful, `None` is returned along with the number of bytes that +/// make up a maximal prefix of a valid UTF-8 code unit sequence. In this case, +/// the number of bytes consumed is always between 0 and 3, inclusive, where +/// 0 is only returned when `slice` is empty. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use bstr::decode_utf8; +/// +/// // Decoding a valid codepoint. +/// let (ch, size) = decode_utf8(b"\xE2\x98\x83"); +/// assert_eq!(Some('☃'), ch); +/// assert_eq!(3, size); +/// +/// // Decoding an incomplete codepoint. +/// let (ch, size) = decode_utf8(b"\xE2\x98"); +/// assert_eq!(None, ch); +/// assert_eq!(2, size); +/// ``` +/// +/// This example shows how to iterate over all codepoints in UTF-8 encoded +/// bytes, while replacing invalid UTF-8 sequences with the replacement +/// codepoint: +/// +/// ``` +/// use bstr::{B, decode_utf8}; +/// +/// let mut bytes = B(b"\xE2\x98\x83\xFF\xF0\x9D\x9E\x83\xE2\x98\x61"); +/// let mut chars = vec![]; +/// while !bytes.is_empty() { +/// let (ch, size) = decode_utf8(bytes); +/// bytes = &bytes[size..]; +/// chars.push(ch.unwrap_or('\u{FFFD}')); +/// } +/// assert_eq!(vec!['☃', '\u{FFFD}', '𝞃', '\u{FFFD}', 'a'], chars); +/// ``` +#[inline] +pub fn decode>(slice: B) -> (Option, usize) { + let slice = slice.as_ref(); + match slice.get(0) { + None => return (None, 0), + Some(&b) if b <= 0x7F => return (Some(b as char), 1), + _ => {} + } + + let (mut state, mut cp, mut i) = (ACCEPT, 0, 0); + while i < slice.len() { + decode_step(&mut state, &mut cp, slice[i]); + i += 1; + + if state == ACCEPT { + // SAFETY: This is safe because `decode_step` guarantees that + // `cp` is a valid Unicode scalar value in an ACCEPT state. + let ch = unsafe { char::from_u32_unchecked(cp) }; + return (Some(ch), i); + } else if state == REJECT { + // At this point, we always want to advance at least one byte. + return (None, cmp::max(1, i.saturating_sub(1))); + } + } + (None, i) +} + +/// Lossily UTF-8 decode a single Unicode scalar value from the beginning of a +/// slice. +/// +/// When successful, the corresponding Unicode scalar value is returned along +/// with the number of bytes it was encoded with. The number of bytes consumed +/// for a successful decode is always between 1 and 4, inclusive. +/// +/// When unsuccessful, the Unicode replacement codepoint (`U+FFFD`) is returned +/// along with the number of bytes that make up a maximal prefix of a valid +/// UTF-8 code unit sequence. In this case, the number of bytes consumed is +/// always between 0 and 3, inclusive, where 0 is only returned when `slice` is +/// empty. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ```ignore +/// use bstr::decode_utf8_lossy; +/// +/// // Decoding a valid codepoint. +/// let (ch, size) = decode_utf8_lossy(b"\xE2\x98\x83"); +/// assert_eq!('☃', ch); +/// assert_eq!(3, size); +/// +/// // Decoding an incomplete codepoint. +/// let (ch, size) = decode_utf8_lossy(b"\xE2\x98"); +/// assert_eq!('\u{FFFD}', ch); +/// assert_eq!(2, size); +/// ``` +/// +/// This example shows how to iterate over all codepoints in UTF-8 encoded +/// bytes, while replacing invalid UTF-8 sequences with the replacement +/// codepoint: +/// +/// ```ignore +/// use bstr::{B, decode_utf8_lossy}; +/// +/// let mut bytes = B(b"\xE2\x98\x83\xFF\xF0\x9D\x9E\x83\xE2\x98\x61"); +/// let mut chars = vec![]; +/// while !bytes.is_empty() { +/// let (ch, size) = decode_utf8_lossy(bytes); +/// bytes = &bytes[size..]; +/// chars.push(ch); +/// } +/// assert_eq!(vec!['☃', '\u{FFFD}', '𝞃', '\u{FFFD}', 'a'], chars); +/// ``` +#[inline] +pub fn decode_lossy>(slice: B) -> (char, usize) { + match decode(slice) { + (Some(ch), size) => (ch, size), + (None, size) => ('\u{FFFD}', size), + } +} + +/// UTF-8 decode a single Unicode scalar value from the end of a slice. +/// +/// When successful, the corresponding Unicode scalar value is returned along +/// with the number of bytes it was encoded with. The number of bytes consumed +/// for a successful decode is always between 1 and 4, inclusive. +/// +/// When unsuccessful, `None` is returned along with the number of bytes that +/// make up a maximal prefix of a valid UTF-8 code unit sequence. In this case, +/// the number of bytes consumed is always between 0 and 3, inclusive, where +/// 0 is only returned when `slice` is empty. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use bstr::decode_last_utf8; +/// +/// // Decoding a valid codepoint. +/// let (ch, size) = decode_last_utf8(b"\xE2\x98\x83"); +/// assert_eq!(Some('☃'), ch); +/// assert_eq!(3, size); +/// +/// // Decoding an incomplete codepoint. +/// let (ch, size) = decode_last_utf8(b"\xE2\x98"); +/// assert_eq!(None, ch); +/// assert_eq!(2, size); +/// ``` +/// +/// This example shows how to iterate over all codepoints in UTF-8 encoded +/// bytes in reverse, while replacing invalid UTF-8 sequences with the +/// replacement codepoint: +/// +/// ``` +/// use bstr::{B, decode_last_utf8}; +/// +/// let mut bytes = B(b"\xE2\x98\x83\xFF\xF0\x9D\x9E\x83\xE2\x98\x61"); +/// let mut chars = vec![]; +/// while !bytes.is_empty() { +/// let (ch, size) = decode_last_utf8(bytes); +/// bytes = &bytes[..bytes.len()-size]; +/// chars.push(ch.unwrap_or('\u{FFFD}')); +/// } +/// assert_eq!(vec!['a', '\u{FFFD}', '𝞃', '\u{FFFD}', '☃'], chars); +/// ``` +#[inline] +pub fn decode_last>(slice: B) -> (Option, usize) { + // TODO: We could implement this by reversing the UTF-8 automaton, but for + // now, we do it the slow way by using the forward automaton. + + let slice = slice.as_ref(); + if slice.is_empty() { + return (None, 0); + } + let mut start = slice.len() - 1; + let limit = slice.len().saturating_sub(4); + while start > limit && !is_leading_or_invalid_utf8_byte(slice[start]) { + start -= 1; + } + let (ch, size) = decode(&slice[start..]); + // If we didn't consume all of the bytes, then that means there's at least + // one stray byte that never occurs in a valid code unit prefix, so we can + // advance by one byte. + if start + size != slice.len() { + (None, 1) + } else { + (ch, size) + } +} + +/// Lossily UTF-8 decode a single Unicode scalar value from the end of a slice. +/// +/// When successful, the corresponding Unicode scalar value is returned along +/// with the number of bytes it was encoded with. The number of bytes consumed +/// for a successful decode is always between 1 and 4, inclusive. +/// +/// When unsuccessful, the Unicode replacement codepoint (`U+FFFD`) is returned +/// along with the number of bytes that make up a maximal prefix of a valid +/// UTF-8 code unit sequence. In this case, the number of bytes consumed is +/// always between 0 and 3, inclusive, where 0 is only returned when `slice` is +/// empty. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ```ignore +/// use bstr::decode_last_utf8_lossy; +/// +/// // Decoding a valid codepoint. +/// let (ch, size) = decode_last_utf8_lossy(b"\xE2\x98\x83"); +/// assert_eq!('☃', ch); +/// assert_eq!(3, size); +/// +/// // Decoding an incomplete codepoint. +/// let (ch, size) = decode_last_utf8_lossy(b"\xE2\x98"); +/// assert_eq!('\u{FFFD}', ch); +/// assert_eq!(2, size); +/// ``` +/// +/// This example shows how to iterate over all codepoints in UTF-8 encoded +/// bytes in reverse, while replacing invalid UTF-8 sequences with the +/// replacement codepoint: +/// +/// ```ignore +/// use bstr::decode_last_utf8_lossy; +/// +/// let mut bytes = B(b"\xE2\x98\x83\xFF\xF0\x9D\x9E\x83\xE2\x98\x61"); +/// let mut chars = vec![]; +/// while !bytes.is_empty() { +/// let (ch, size) = decode_last_utf8_lossy(bytes); +/// bytes = &bytes[..bytes.len()-size]; +/// chars.push(ch); +/// } +/// assert_eq!(vec!['a', '\u{FFFD}', '𝞃', '\u{FFFD}', '☃'], chars); +/// ``` +#[inline] +pub fn decode_last_lossy>(slice: B) -> (char, usize) { + match decode_last(slice) { + (Some(ch), size) => (ch, size), + (None, size) => ('\u{FFFD}', size), + } +} + +/// SAFETY: The decode function relies on state being equal to ACCEPT only if +/// cp is a valid Unicode scalar value. +#[inline] +pub fn decode_step(state: &mut usize, cp: &mut u32, b: u8) { + let class = CLASSES[b as usize]; + if *state == ACCEPT { + *cp = (0xFF >> class) & (b as u32); + } else { + *cp = (b as u32 & 0b111111) | (*cp << 6); + } + *state = STATES_FORWARD[*state + class as usize] as usize; +} + +/// Returns true if and only if the given byte is either a valid leading UTF-8 +/// byte, or is otherwise an invalid byte that can never appear anywhere in a +/// valid UTF-8 sequence. +fn is_leading_or_invalid_utf8_byte(b: u8) -> bool { + // In the ASCII case, the most significant bit is never set. The leading + // byte of a 2/3/4-byte sequence always has the top two most significant + // bits set. For bytes that can never appear anywhere in valid UTF-8, this + // also returns true, since every such byte has its two most significant + // bits set: + // + // \xC0 :: 11000000 + // \xC1 :: 11000001 + // \xF5 :: 11110101 + // \xF6 :: 11110110 + // \xF7 :: 11110111 + // \xF8 :: 11111000 + // \xF9 :: 11111001 + // \xFA :: 11111010 + // \xFB :: 11111011 + // \xFC :: 11111100 + // \xFD :: 11111101 + // \xFE :: 11111110 + // \xFF :: 11111111 + (b & 0b1100_0000) != 0b1000_0000 +} + +#[cfg(test)] +mod tests { + use std::char; + + use ext_slice::{ByteSlice, B}; + use tests::LOSSY_TESTS; + use utf8::{self, Utf8Error}; + + fn utf8e(valid_up_to: usize) -> Utf8Error { + Utf8Error { valid_up_to, error_len: None } + } + + fn utf8e2(valid_up_to: usize, error_len: usize) -> Utf8Error { + Utf8Error { valid_up_to, error_len: Some(error_len) } + } + + #[test] + fn validate_all_codepoints() { + for i in 0..(0x10FFFF + 1) { + let cp = match char::from_u32(i) { + None => continue, + Some(cp) => cp, + }; + let mut buf = [0; 4]; + let s = cp.encode_utf8(&mut buf); + assert_eq!(Ok(()), utf8::validate(s.as_bytes())); + } + } + + #[test] + fn validate_multiple_codepoints() { + assert_eq!(Ok(()), utf8::validate(b"abc")); + assert_eq!(Ok(()), utf8::validate(b"a\xE2\x98\x83a")); + assert_eq!(Ok(()), utf8::validate(b"a\xF0\x9D\x9C\xB7a")); + assert_eq!(Ok(()), utf8::validate(b"\xE2\x98\x83\xF0\x9D\x9C\xB7",)); + assert_eq!( + Ok(()), + utf8::validate(b"a\xE2\x98\x83a\xF0\x9D\x9C\xB7a",) + ); + assert_eq!( + Ok(()), + utf8::validate(b"\xEF\xBF\xBD\xE2\x98\x83\xEF\xBF\xBD",) + ); + } + + #[test] + fn validate_errors() { + // single invalid byte + assert_eq!(Err(utf8e2(0, 1)), utf8::validate(b"\xFF")); + // single invalid byte after ASCII + assert_eq!(Err(utf8e2(1, 1)), utf8::validate(b"a\xFF")); + // single invalid byte after 2 byte sequence + assert_eq!(Err(utf8e2(2, 1)), utf8::validate(b"\xCE\xB2\xFF")); + // single invalid byte after 3 byte sequence + assert_eq!(Err(utf8e2(3, 1)), utf8::validate(b"\xE2\x98\x83\xFF")); + // single invalid byte after 4 byte sequence + assert_eq!(Err(utf8e2(4, 1)), utf8::validate(b"\xF0\x9D\x9D\xB1\xFF")); + + // An invalid 2-byte sequence with a valid 1-byte prefix. + assert_eq!(Err(utf8e2(0, 1)), utf8::validate(b"\xCE\xF0")); + // An invalid 3-byte sequence with a valid 2-byte prefix. + assert_eq!(Err(utf8e2(0, 2)), utf8::validate(b"\xE2\x98\xF0")); + // An invalid 4-byte sequence with a valid 3-byte prefix. + assert_eq!(Err(utf8e2(0, 3)), utf8::validate(b"\xF0\x9D\x9D\xF0")); + + // An overlong sequence. Should be \xE2\x82\xAC, but we encode the + // same codepoint value in 4 bytes. This not only tests that we reject + // overlong sequences, but that we get valid_up_to correct. + assert_eq!(Err(utf8e2(0, 1)), utf8::validate(b"\xF0\x82\x82\xAC")); + assert_eq!(Err(utf8e2(1, 1)), utf8::validate(b"a\xF0\x82\x82\xAC")); + assert_eq!( + Err(utf8e2(3, 1)), + utf8::validate(b"\xE2\x98\x83\xF0\x82\x82\xAC",) + ); + + // Check that encoding a surrogate codepoint using the UTF-8 scheme + // fails validation. + assert_eq!(Err(utf8e2(0, 1)), utf8::validate(b"\xED\xA0\x80")); + assert_eq!(Err(utf8e2(1, 1)), utf8::validate(b"a\xED\xA0\x80")); + assert_eq!( + Err(utf8e2(3, 1)), + utf8::validate(b"\xE2\x98\x83\xED\xA0\x80",) + ); + + // Check that an incomplete 2-byte sequence fails. + assert_eq!(Err(utf8e2(0, 1)), utf8::validate(b"\xCEa")); + assert_eq!(Err(utf8e2(1, 1)), utf8::validate(b"a\xCEa")); + assert_eq!( + Err(utf8e2(3, 1)), + utf8::validate(b"\xE2\x98\x83\xCE\xE2\x98\x83",) + ); + // Check that an incomplete 3-byte sequence fails. + assert_eq!(Err(utf8e2(0, 2)), utf8::validate(b"\xE2\x98a")); + assert_eq!(Err(utf8e2(1, 2)), utf8::validate(b"a\xE2\x98a")); + assert_eq!( + Err(utf8e2(3, 2)), + utf8::validate(b"\xE2\x98\x83\xE2\x98\xE2\x98\x83",) + ); + // Check that an incomplete 4-byte sequence fails. + assert_eq!(Err(utf8e2(0, 3)), utf8::validate(b"\xF0\x9D\x9Ca")); + assert_eq!(Err(utf8e2(1, 3)), utf8::validate(b"a\xF0\x9D\x9Ca")); + assert_eq!( + Err(utf8e2(4, 3)), + utf8::validate(b"\xF0\x9D\x9C\xB1\xF0\x9D\x9C\xE2\x98\x83",) + ); + assert_eq!( + Err(utf8e2(6, 3)), + utf8::validate(b"foobar\xF1\x80\x80quux",) + ); + + // Check that an incomplete (EOF) 2-byte sequence fails. + assert_eq!(Err(utf8e(0)), utf8::validate(b"\xCE")); + assert_eq!(Err(utf8e(1)), utf8::validate(b"a\xCE")); + assert_eq!(Err(utf8e(3)), utf8::validate(b"\xE2\x98\x83\xCE")); + // Check that an incomplete (EOF) 3-byte sequence fails. + assert_eq!(Err(utf8e(0)), utf8::validate(b"\xE2\x98")); + assert_eq!(Err(utf8e(1)), utf8::validate(b"a\xE2\x98")); + assert_eq!(Err(utf8e(3)), utf8::validate(b"\xE2\x98\x83\xE2\x98")); + // Check that an incomplete (EOF) 4-byte sequence fails. + assert_eq!(Err(utf8e(0)), utf8::validate(b"\xF0\x9D\x9C")); + assert_eq!(Err(utf8e(1)), utf8::validate(b"a\xF0\x9D\x9C")); + assert_eq!( + Err(utf8e(4)), + utf8::validate(b"\xF0\x9D\x9C\xB1\xF0\x9D\x9C",) + ); + + // Test that we errors correct even after long valid sequences. This + // checks that our "backup" logic for detecting errors is correct. + assert_eq!( + Err(utf8e2(8, 1)), + utf8::validate(b"\xe2\x98\x83\xce\xb2\xe3\x83\x84\xFF",) + ); + } + + #[test] + fn decode_valid() { + fn d(mut s: &str) -> Vec { + let mut chars = vec![]; + while !s.is_empty() { + let (ch, size) = utf8::decode(s.as_bytes()); + s = &s[size..]; + chars.push(ch.unwrap()); + } + chars + } + + assert_eq!(vec!['☃'], d("☃")); + assert_eq!(vec!['☃', '☃'], d("☃☃")); + assert_eq!(vec!['α', 'β', 'γ', 'δ', 'ε'], d("αβγδε")); + assert_eq!(vec!['☃', '⛄', '⛇'], d("☃⛄⛇")); + assert_eq!(vec!['𝗮', '𝗯', '𝗰', '𝗱', '𝗲'], d("𝗮𝗯𝗰𝗱𝗲")); + } + + #[test] + fn decode_invalid() { + let (ch, size) = utf8::decode(b""); + assert_eq!(None, ch); + assert_eq!(0, size); + + let (ch, size) = utf8::decode(b"\xFF"); + assert_eq!(None, ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode(b"\xCE\xF0"); + assert_eq!(None, ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode(b"\xE2\x98\xF0"); + assert_eq!(None, ch); + assert_eq!(2, size); + + let (ch, size) = utf8::decode(b"\xF0\x9D\x9D"); + assert_eq!(None, ch); + assert_eq!(3, size); + + let (ch, size) = utf8::decode(b"\xF0\x9D\x9D\xF0"); + assert_eq!(None, ch); + assert_eq!(3, size); + + let (ch, size) = utf8::decode(b"\xF0\x82\x82\xAC"); + assert_eq!(None, ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode(b"\xED\xA0\x80"); + assert_eq!(None, ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode(b"\xCEa"); + assert_eq!(None, ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode(b"\xE2\x98a"); + assert_eq!(None, ch); + assert_eq!(2, size); + + let (ch, size) = utf8::decode(b"\xF0\x9D\x9Ca"); + assert_eq!(None, ch); + assert_eq!(3, size); + } + + #[test] + fn decode_lossy() { + let (ch, size) = utf8::decode_lossy(b""); + assert_eq!('\u{FFFD}', ch); + assert_eq!(0, size); + + let (ch, size) = utf8::decode_lossy(b"\xFF"); + assert_eq!('\u{FFFD}', ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode_lossy(b"\xCE\xF0"); + assert_eq!('\u{FFFD}', ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode_lossy(b"\xE2\x98\xF0"); + assert_eq!('\u{FFFD}', ch); + assert_eq!(2, size); + + let (ch, size) = utf8::decode_lossy(b"\xF0\x9D\x9D\xF0"); + assert_eq!('\u{FFFD}', ch); + assert_eq!(3, size); + + let (ch, size) = utf8::decode_lossy(b"\xF0\x82\x82\xAC"); + assert_eq!('\u{FFFD}', ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode_lossy(b"\xED\xA0\x80"); + assert_eq!('\u{FFFD}', ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode_lossy(b"\xCEa"); + assert_eq!('\u{FFFD}', ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode_lossy(b"\xE2\x98a"); + assert_eq!('\u{FFFD}', ch); + assert_eq!(2, size); + + let (ch, size) = utf8::decode_lossy(b"\xF0\x9D\x9Ca"); + assert_eq!('\u{FFFD}', ch); + assert_eq!(3, size); + } + + #[test] + fn decode_last_valid() { + fn d(mut s: &str) -> Vec { + let mut chars = vec![]; + while !s.is_empty() { + let (ch, size) = utf8::decode_last(s.as_bytes()); + s = &s[..s.len() - size]; + chars.push(ch.unwrap()); + } + chars + } + + assert_eq!(vec!['☃'], d("☃")); + assert_eq!(vec!['☃', '☃'], d("☃☃")); + assert_eq!(vec!['ε', 'δ', 'γ', 'β', 'α'], d("αβγδε")); + assert_eq!(vec!['⛇', '⛄', '☃'], d("☃⛄⛇")); + assert_eq!(vec!['𝗲', '𝗱', '𝗰', '𝗯', '𝗮'], d("𝗮𝗯𝗰𝗱𝗲")); + } + + #[test] + fn decode_last_invalid() { + let (ch, size) = utf8::decode_last(b""); + assert_eq!(None, ch); + assert_eq!(0, size); + + let (ch, size) = utf8::decode_last(b"\xFF"); + assert_eq!(None, ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode_last(b"\xCE\xF0"); + assert_eq!(None, ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode_last(b"\xCE"); + assert_eq!(None, ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode_last(b"\xE2\x98\xF0"); + assert_eq!(None, ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode_last(b"\xE2\x98"); + assert_eq!(None, ch); + assert_eq!(2, size); + + let (ch, size) = utf8::decode_last(b"\xF0\x9D\x9D\xF0"); + assert_eq!(None, ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode_last(b"\xF0\x9D\x9D"); + assert_eq!(None, ch); + assert_eq!(3, size); + + let (ch, size) = utf8::decode_last(b"\xF0\x82\x82\xAC"); + assert_eq!(None, ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode_last(b"\xED\xA0\x80"); + assert_eq!(None, ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode_last(b"\xED\xA0"); + assert_eq!(None, ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode_last(b"\xED"); + assert_eq!(None, ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode_last(b"a\xCE"); + assert_eq!(None, ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode_last(b"a\xE2\x98"); + assert_eq!(None, ch); + assert_eq!(2, size); + + let (ch, size) = utf8::decode_last(b"a\xF0\x9D\x9C"); + assert_eq!(None, ch); + assert_eq!(3, size); + } + + #[test] + fn decode_last_lossy() { + let (ch, size) = utf8::decode_last_lossy(b""); + assert_eq!('\u{FFFD}', ch); + assert_eq!(0, size); + + let (ch, size) = utf8::decode_last_lossy(b"\xFF"); + assert_eq!('\u{FFFD}', ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode_last_lossy(b"\xCE\xF0"); + assert_eq!('\u{FFFD}', ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode_last_lossy(b"\xCE"); + assert_eq!('\u{FFFD}', ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode_last_lossy(b"\xE2\x98\xF0"); + assert_eq!('\u{FFFD}', ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode_last_lossy(b"\xE2\x98"); + assert_eq!('\u{FFFD}', ch); + assert_eq!(2, size); + + let (ch, size) = utf8::decode_last_lossy(b"\xF0\x9D\x9D\xF0"); + assert_eq!('\u{FFFD}', ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode_last_lossy(b"\xF0\x9D\x9D"); + assert_eq!('\u{FFFD}', ch); + assert_eq!(3, size); + + let (ch, size) = utf8::decode_last_lossy(b"\xF0\x82\x82\xAC"); + assert_eq!('\u{FFFD}', ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode_last_lossy(b"\xED\xA0\x80"); + assert_eq!('\u{FFFD}', ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode_last_lossy(b"\xED\xA0"); + assert_eq!('\u{FFFD}', ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode_last_lossy(b"\xED"); + assert_eq!('\u{FFFD}', ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode_last_lossy(b"a\xCE"); + assert_eq!('\u{FFFD}', ch); + assert_eq!(1, size); + + let (ch, size) = utf8::decode_last_lossy(b"a\xE2\x98"); + assert_eq!('\u{FFFD}', ch); + assert_eq!(2, size); + + let (ch, size) = utf8::decode_last_lossy(b"a\xF0\x9D\x9C"); + assert_eq!('\u{FFFD}', ch); + assert_eq!(3, size); + } + + #[test] + fn chars() { + for (i, &(expected, input)) in LOSSY_TESTS.iter().enumerate() { + let got: String = B(input).chars().collect(); + assert_eq!( + expected, got, + "chars(ith: {:?}, given: {:?})", + i, input, + ); + let got: String = + B(input).char_indices().map(|(_, _, ch)| ch).collect(); + assert_eq!( + expected, got, + "char_indices(ith: {:?}, given: {:?})", + i, input, + ); + + let expected: String = expected.chars().rev().collect(); + + let got: String = B(input).chars().rev().collect(); + assert_eq!( + expected, got, + "chars.rev(ith: {:?}, given: {:?})", + i, input, + ); + let got: String = + B(input).char_indices().rev().map(|(_, _, ch)| ch).collect(); + assert_eq!( + expected, got, + "char_indices.rev(ith: {:?}, given: {:?})", + i, input, + ); + } + } + + #[test] + fn utf8_chunks() { + let mut c = utf8::Utf8Chunks { bytes: b"123\xC0" }; + assert_eq!( + (c.next(), c.next()), + ( + Some(utf8::Utf8Chunk { + valid: "123", + invalid: b"\xC0".as_bstr(), + incomplete: false, + }), + None, + ) + ); + + let mut c = utf8::Utf8Chunks { bytes: b"123\xFF\xFF" }; + assert_eq!( + (c.next(), c.next(), c.next()), + ( + Some(utf8::Utf8Chunk { + valid: "123", + invalid: b"\xFF".as_bstr(), + incomplete: false, + }), + Some(utf8::Utf8Chunk { + valid: "", + invalid: b"\xFF".as_bstr(), + incomplete: false, + }), + None, + ) + ); + + let mut c = utf8::Utf8Chunks { bytes: b"123\xD0" }; + assert_eq!( + (c.next(), c.next()), + ( + Some(utf8::Utf8Chunk { + valid: "123", + invalid: b"\xD0".as_bstr(), + incomplete: true, + }), + None, + ) + ); + + let mut c = utf8::Utf8Chunks { bytes: b"123\xD0456" }; + assert_eq!( + (c.next(), c.next(), c.next()), + ( + Some(utf8::Utf8Chunk { + valid: "123", + invalid: b"\xD0".as_bstr(), + incomplete: false, + }), + Some(utf8::Utf8Chunk { + valid: "456", + invalid: b"".as_bstr(), + incomplete: false, + }), + None, + ) + ); + + let mut c = utf8::Utf8Chunks { bytes: b"123\xE2\x98" }; + assert_eq!( + (c.next(), c.next()), + ( + Some(utf8::Utf8Chunk { + valid: "123", + invalid: b"\xE2\x98".as_bstr(), + incomplete: true, + }), + None, + ) + ); + + let mut c = utf8::Utf8Chunks { bytes: b"123\xF4\x8F\xBF" }; + assert_eq!( + (c.next(), c.next()), + ( + Some(utf8::Utf8Chunk { + valid: "123", + invalid: b"\xF4\x8F\xBF".as_bstr(), + incomplete: true, + }), + None, + ) + ); + } +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/.cargo-checksum.json b/third_party/cargo/vendor/mlua-0.5.3/.cargo-checksum.json new file mode 100644 index 0000000..c936244 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"CHANGELOG.md":"f9703002e8e6aa0df4878d926fadfd9cddb5b4ae199e4fbb03b917c27f8546cc","Cargo.lock":"777b9b72d7cb09fd14cd791dfd75b9fe3b77070f31c88ad1298f87b55885bd2a","Cargo.toml":"70d0d67b49ee5a5c1f5795e56be8eaf258f6a53eb48e87c4f439a3cabc84bba3","LICENSE":"63b61a30d3e3abcfcb1bda4b99f4eea9fdb7d6ab05fbc513461fef6cf89baf29","README.md":"d41475c3d0e5741f1be2471ed0412d073ff8075eec580c66156c5b9b0d385d47","benches/benchmark.rs":"1f6ea9540145e8709413404be5901fc73e511d2d0c3b0d8f5ff42c06a0756dfa","build/find_dummy.rs":"1b44c2e7ca14f50370d0c546ad6fd3f0d918677aabfc62184b243eacabde4679","build/find_normal.rs":"9d4f6170b49861e7e9ad87353aef1ed83e7b94d61496d8130cec35c019fcce84","build/find_vendored.rs":"93182d397c06159c7233de84315bd87a62f8e591aed1b3ce85b295b17e9bce25","build/main.rs":"92338abc9e6aa532c02af988afa1bed3f8cb96872f9331c6730f63c8bb854130","examples/async_http_client.rs":"8314853f0b460c2eeac74512a46f9abf2e3b0dbb93f91ebca1fae9b0989d7f88","examples/async_http_reqwest.rs":"688de8ccc743844b5dec3e00db3209b92abfdfb857287a3b2a4441ab7cadcd10","examples/async_http_server.rs":"b5dd4a50575b49fa4d171898130ffe2229a8be11375f950ca4ecffb52d04eca9","examples/async_tcp_server.rs":"5c1e11ab95cfb6a3b8e5831af1f77f7a44a94c9efe7adfde2a4d42a4f1c673b4","examples/guided_tour.rs":"0ff79ad8b466d22ced7215332e0fb6a42aad70a61d4a2474136a2c4a4f0d1600","examples/repl.rs":"8eee7ffd8d76a7e16519fd7c7177e6b1d3fb271d49117e1e685d6c6cb9f9d04f","examples/serialize.rs":"f0bce9ced7f27f1f58b76edbf2c023fcf725bf06c4886fd428a345dedb964058","src/conversion.rs":"aedf674cec0d3ceac0bc7883173bc73be1b1961a8744b3b82abd4d9ca95e8b37","src/error.rs":"df08616da0c14de72058b1562bb2ad24d3c57c9ac8597be92391734cd65f65c7","src/ffi/compat53.rs":"8371889e719202d90054fda4f18e12ba507b1d02b0e9016d1e49a12bbf408103","src/ffi/glue/glue.c":"11149aa0374c45575a1175e27cf06f55ea1bb4002aaf7bd16b7c29928bd63567","src/ffi/lauxlib.rs":"7f1736a7304ff89a3d4d7969c3ec19c67d0aba5d0e3f72c5164d941d71280dfb","src/ffi/lua.rs":"f2c1bec441d43341584e6f3f37276d90ca5ca624439a5d4259ffb498b4da1051","src/ffi/luaconf.rs":"daebff9277c4aba9a3c80e4cc022f5418bacb9a97e263acbb99e9cb5ed0e36f5","src/ffi/lualib.rs":"4f99283d214d84c4772caa4108044b20ffc86258b1f67b027d9b5c3cf247e5c2","src/ffi/mod.rs":"3a295d9fc7ee3cbbd2ab6f6e75d54c6b2ff45e827269195cedf99db79ce2d28a","src/function.rs":"c138b1c61a4bb291d51a8d0142c60afd4083d021b81749020148a1da76b484f7","src/hook.rs":"5555fd0f00eaf361188c33c6503a6ffd89aefc01ccc42e1bdf2d0b1169afae48","src/lib.rs":"45d62f20b99812283329f1f17500de92843393d759a0e15f3fa1b1e0a07e2711","src/lua.rs":"873ee2411d72c120ef478f67b78bacd145a6e185276fa6bbc12a25c9cbe947f1","src/macros.rs":"8d5e061297113852b616fb518e67d04404607c8bc6748534308dcf8afe3e7726","src/multi.rs":"3efd9e2e148f5f9ded89e1d116fef19e5b63ff6026f0067e6ca16a642cabedf6","src/prelude.rs":"961e393f7728425c189464a6866b2844b7f8b9d93a407e8cab87dab580996576","src/scope.rs":"c9bc5227b7a3b0c856dd64afd0ede392c94943a0e38a0af8063ec1451959da05","src/serde/de.rs":"8e400f5eb0b4f3d4e46ad1394dc7e7a122cdc11b317e0071b3dda25f2ee4d6b9","src/serde/mod.rs":"fe9feffb58dc9fedd87704c411576d68bd700669630e7ce7a733b36bea752ed6","src/serde/ser.rs":"1a43d9ab21e82a04e825ce6e4e3a93713e57c23be4d01d490719b01f0946ebc0","src/stdlib.rs":"630eacd6191b8641ef8e1d8e007da1fe4eddb9311909d7ec536b2ed772413683","src/string.rs":"b3dfbfa0e09478a0c9a1d142f2befcc30a8ec5d2e9a2848ee18696f40a78fc4e","src/table.rs":"ea56c2718e9a515bbf19caeadc9af5d756dcb9e4624d168f7e23723ae154f471","src/thread.rs":"fc81381e11bc8884204b2fd784d920f1f54ccba618e82dcde2e7cc5dfec68c03","src/types.rs":"b77293955ec0e67ab90c6f332b30e6e7deceafdc962b1a4c01df8e7a8932abdc","src/userdata.rs":"7ebc00b1ba49377fb0203d11cb00e5426c1ededff2375aa15b0a425d4b5d3106","src/util.rs":"ab7b34c44c9e7d6244090d73f9aa5890ea0b960ee65c67eec89aa3e1a8217881","src/value.rs":"45dda64f58bd9166773cca900eb67b66037341413c0db1ce3d2b3358e9b2e13b","tests/async.rs":"f07e30efe0ebe8097cf39a7519a2bb9de3a428dfe83ba1cb6f485f427a29403f","tests/byte_string.rs":"e963a5029ea6fc553b424c7c2c5f8fa6823b537432f31905b04883faf171fc3c","tests/compile.rs":"9fa730460ab3b44563a655ec4e525f54de16d2f514434f85c203220fe598902c","tests/compile/async_nonstatic_userdata.rs":"6f2a05b5e92491c31f339581d4a8cbd8ca142d4bee73338cedf259c3d04fc672","tests/compile/async_nonstatic_userdata.stderr":"b05ddacc44725ee4d3a9a15bfc305af9fec1c4763078b5372e567764f4e6f90b","tests/compile/function_borrow.rs":"c568dc806d84529675c5a2708e0147fece59e14e67ef5a4711385d3b2d77b02d","tests/compile/function_borrow.stderr":"19fcc80ed98c372eb29e0600123247d88e4456c27c267b033816ee2fac8caf93","tests/compile/lua_norefunwindsafe.rs":"670b2bb30dd9d63ea6c84812c0b78e8fb13e6f3aa458ff5d18f77e04bc026a12","tests/compile/lua_norefunwindsafe.stderr":"36dde0881fbe093e86b36f1057c9bb26121819b43128e18733c95de7da395a4e","tests/compile/non_send.rs":"404a271ab1ee768942f9610c9b5feab6f3246d0af5a81aa4a86bb96d4daae09d","tests/compile/non_send.stderr":"f01b2b4b8988545ec76a6dd1e2a636f2fc62700e01dbc2e49036512da2fa4e84","tests/compile/ref_nounwindsafe.rs":"a197f02488b0b8a3e4866081f0a191b1a2571d6d45159faf260d6755a12c4b61","tests/compile/ref_nounwindsafe.stderr":"9d19a2a767e7228c625eab1dd41752c71df367567a3b95fd7f18dc0de333a2a2","tests/compile/scope_callback_capture.rs":"67c70f52606e80967f38b90a584676cdc29f08f799c45d4c525c282ffa47bac3","tests/compile/scope_callback_capture.stderr":"e8d76c95c222cc83faac83049180a2cb48bf832243acb219361a4b4f1888c764","tests/compile/scope_callback_inner.rs":"8b667978d01ef169fb75f0afb29d855a385823d0086f788230b27e4072023eb4","tests/compile/scope_callback_inner.stderr":"caba676969d85fda60ea094c402e0fe434a712a116e1fdc955f02a6f758468c6","tests/compile/scope_callback_outer.rs":"255e3dc058e40c039be93e74e535e7d14eef770e880f822c7cb9d18086927393","tests/compile/scope_callback_outer.stderr":"2017b96b0282dea4d86c66fc8d48a2400b774ba84d01148e3212cf7b60302b74","tests/compile/scope_invariance.rs":"724f329670df4ad65ee732eda62e352a1c722eb6ec88243cb7b7652b78cf0a1a","tests/compile/scope_invariance.stderr":"bf87b45c2702af5179a1bad2a6e4365268b817731ed7b77ca586f142ba6d9f31","tests/compile/scope_mutable_aliasing.rs":"b192d9f3f49d03b25e4f0292fe6ac918f4f74a8f75bca0c078928ec21df51526","tests/compile/scope_mutable_aliasing.stderr":"25ab60a7a679a4c87f6cd3538c7724d0aad2beb698fffb6bd7c27eee0078226a","tests/compile/scope_userdata_borrow.rs":"b8ce1c7f23baf0400f8e87a0b095434b7a7773197d7ed0d294726fc91d327ce0","tests/compile/scope_userdata_borrow.stderr":"0e55a40a7ee4ae0c6518855bec44043aaacb98f940a41f9565f991d596ebec61","tests/compile/static_callback_args.rs":"447cb60dad7f98e446c6d7f2072581c7f01f02c2bdba3f976e952d27425883cc","tests/compile/static_callback_args.stderr":"5306a947c40b6b9841626465e3a775f395968ef54c60bb1cc08b5b2836628e39","tests/compile/userdata_borrow.rs":"13662e4d9ade69981dabe891b825ffa32ee54a25f5b3d3cf831e867a60c87555","tests/compile/userdata_borrow.stderr":"24981a303fddd172699cd88bf593e6cc4b829e5d84c52cd508f20eace5aa0f3a","tests/function.rs":"180c07c2b0744535aeedce1984726aa98712be81e8d853c94718af48ea412ad6","tests/hooks.rs":"018f200612b166a3eb2558ad1fafa6b7f10265676f264f71aa48704f3012437a","tests/memory.rs":"f906ede3160e05d96286fb263be3f19c33b92161fac6b1c16896295dbc98c4e2","tests/scope.rs":"acbb19a95287d90976cf7bc1db63d5d3f63563707abf0a77f1a84eab08ce406c","tests/serde.rs":"3da4a74b3ddab83776b7c5908c006b4a493806a1eb05663ae2975759013e1d45","tests/string.rs":"417839965e75477cbb9f6a5342375fc945c35faf871b7562bb6df861e3d59130","tests/table.rs":"f6148446a5ef686cda964b341eec7e53f69108556e779f95cb876ff2a9f060c4","tests/tests.rs":"ee94c24a6995e4fe0ecf23947ba95857b8a4ee6fecee6ceecbb49ace634b5e69","tests/thread.rs":"4e3883f6b0eb82766882890ab441583ec106efdc4ee2b3fadb2dd1b9d7bebb1f","tests/types.rs":"335d779bdf3e2102c4f644c6284dbf6db25908221471c84705286687ffcaf2b9","tests/userdata.rs":"c7321b2ffa2bb6f3b0848a309f2783ec50c8a79aeecf4866d0a1ef0ff9556f19","tests/value.rs":"882a361cbaf5eaba0560d36c3d3e3a7a5f629f171606bf0b4cc9820afed6c81a"},"package":"6f2fc8e1085d53b72898c59ceee1980b5826b0c98ce99886b7518f0ead00e5cb"} \ No newline at end of file diff --git a/third_party/cargo/vendor/mlua-0.5.3/BUILD.bazel b/third_party/cargo/vendor/mlua-0.5.3/BUILD.bazel new file mode 100644 index 0000000..f129128 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/BUILD.bazel @@ -0,0 +1,135 @@ +""" +@generated +cargo-raze crate build file. + +DO NOT EDIT! Replaced on runs of cargo-raze +""" + +# buildifier: disable=load +load( + "@rules_rust//rust:rust.bzl", + "rust_binary", + "rust_library", + "rust_test", +) + +# buildifier: disable=load +load("@bazel_skylib//lib:selects.bzl", "selects") + +package(default_visibility = [ + # Public for visibility by "@raze__crate__version//" targets. + # + # Prefer access through "//third_party/cargo", which limits external + # visibility to explicit Cargo.toml dependencies. + "//visibility:public", +]) + +licenses([ + "notice", # MIT from expression "MIT" +]) + +# Generated Targets +# buildifier: disable=load-on-top +load( + "@rules_rust//cargo:cargo_build_script.bzl", + "cargo_build_script", +) + +cargo_build_script( + name = "mlua_build_script", + srcs = glob(["**/*.rs"]), + build_script_env = { + }, + crate_features = [ + "luajit", + ], + crate_root = "build/main.rs", + data = glob(["**"]), + edition = "2018", + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-raze", + "manual", + ], + version = "0.5.3", + visibility = ["//visibility:private"], + deps = [ + "//third_party/cargo/vendor/cc-1.0.67:cc", + "//third_party/cargo/vendor/pkg-config-0.3.19:pkg_config", + ], +) + +# Unsupported target "benchmark" with type "bench" omitted + +# Unsupported target "async_http_client" with type "example" omitted + +# Unsupported target "async_http_reqwest" with type "example" omitted + +# Unsupported target "async_http_server" with type "example" omitted + +# Unsupported target "async_tcp_server" with type "example" omitted + +# Unsupported target "guided_tour" with type "example" omitted + +# Unsupported target "repl" with type "example" omitted + +# Unsupported target "serialize" with type "example" omitted + +rust_library( + name = "mlua", + srcs = glob(["**/*.rs"]), + crate_features = [ + "luajit", + ], + crate_root = "src/lib.rs", + crate_type = "lib", + data = [], + edition = "2018", + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-raze", + "manual", + ], + version = "0.5.3", + # buildifier: leave-alone + deps = [ + ":mlua_build_script", + "//third_party/cargo/vendor/bstr-0.2.15:bstr", + "//third_party/cargo/vendor/lazy_static-1.4.0:lazy_static", + "//third_party/cargo/vendor/num-traits-0.2.14:num_traits", + ], +) + +# Unsupported target "async" with type "test" omitted + +# Unsupported target "byte_string" with type "test" omitted + +# Unsupported target "compile" with type "test" omitted + +# Unsupported target "function" with type "test" omitted + +# Unsupported target "hooks" with type "test" omitted + +# Unsupported target "memory" with type "test" omitted + +# Unsupported target "scope" with type "test" omitted + +# Unsupported target "serde" with type "test" omitted + +# Unsupported target "string" with type "test" omitted + +# Unsupported target "table" with type "test" omitted + +# Unsupported target "tests" with type "test" omitted + +# Unsupported target "thread" with type "test" omitted + +# Unsupported target "types" with type "test" omitted + +# Unsupported target "userdata" with type "test" omitted + +# Unsupported target "value" with type "test" omitted diff --git a/third_party/cargo/vendor/mlua-0.5.3/CHANGELOG.md b/third_party/cargo/vendor/mlua-0.5.3/CHANGELOG.md new file mode 100644 index 0000000..2ba76c1 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/CHANGELOG.md @@ -0,0 +1,45 @@ +## v0.5.3 + +- Fixed bug when returning nil-prefixed multi values from async function (+ test) +- Performance optimisation for async callbacks (polling) + +## v0.5.2 + +- Some performance optimisations (callbacks) +- `ToLua` implementation for `Cow` and `Cow` +- Fixed bug with `Scope` destruction of partially polled futures + +## v0.5.1 + +- Support cross compilation that should work well for vendored builds (including LuaJIT with some restrictions) +- Fix numeric types conversion for 32bit Lua +- Update tokio to 1.0 for async examples + +## v0.5.0 + +- Serde support under `serialize` feature flag. +- Re-export `mlua_derive`. +- impl `ToLua` and `FromLua` for `HashSet` and `BTreeSet` + +## v0.4.2 + +- Added `Function::dump()` to dump lua function to a binary chunk +- Added `ChunkMode` enum to mark chunks as text or binary +- Updated `set_memory_limit` doc + +## v0.4.0 + +- Lua 5.4 support with `MetaMethod::Close`. +- `lua53` feature is disabled by default. Now preferred Lua version have to be chosen explicitly. +- Provide safety guaraness for Lua state, which means that potenially unsafe operations, like loading C modules (using `require` or `package.loadlib`) are disabled. Equalient for the previous `Lua::new()` function is `Lua::unsafe_new()`. +- New `send` feature to require `Send`. +- New `module` feature, that disables linking to Lua Core Libraries. Required for modules. +- Don't allow `'callback` outlive `'lua` in `Lua::create_function()` to fix [the unsoundness](tests/compile/static_callback_args.rs). +- Added `Lua::into_static()` to make `'static` Lua state. This is useful to spawn async Lua threads that requires `'static`. +- New function `Lua::set_memory_limit()` (similar to `rlua`) to enable memory restrictions in Lua VM (requires Lua >= 5.2). +- `Scope`, temporary removed in v0.3, is back with async support. +- Removed deprecated `Table::call()` function. +- Added hooks support (backported from rlua 0.17). +- New `AnyUserData::has_metamethod()` function. +- LuaJIT 2.0.5 (the latest stable) support. +- Various bug fixes and improvements. diff --git a/third_party/cargo/vendor/mlua-0.5.3/Cargo.lock b/third_party/cargo/vendor/mlua-0.5.3/Cargo.lock new file mode 100644 index 0000000..12486d9 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/Cargo.lock @@ -0,0 +1,1685 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "bstr" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a40b47ad93e1a5404e6c18dec46b628214fee441c70f4ab5d6942142cc268a3d" +dependencies = [ + "lazy_static", + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe" + +[[package]] +name = "byteorder" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b" + +[[package]] +name = "bytes" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" + +[[package]] +name = "cast" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0" +dependencies = [ + "rustc_version", +] + +[[package]] +name = "cc" +version = "1.0.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "2.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +dependencies = [ + "bitflags", + "textwrap", + "unicode-width", +] + +[[package]] +name = "core-foundation" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" + +[[package]] +name = "criterion" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab327ed7354547cc2ef43cbe20ef68b988e70b4b593cbd66a2a61733123a3d23" +dependencies = [ + "atty", + "cast", + "clap", + "criterion-plot", + "csv", + "futures", + "itertools 0.10.0", + "lazy_static", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_cbor", + "serde_derive", + "serde_json", + "tinytemplate", + "tokio", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e022feadec601fba1649cfa83586381a4ad31c6bf3a9ab7d408118b05dd9889d" +dependencies = [ + "cast", + "itertools 0.9.0", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2584f639eb95fea8c798496315b297cf81b9b58b6d30ab066a75455333cf4b12" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "lazy_static", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49" +dependencies = [ + "autocfg", + "cfg-if", + "lazy_static", +] + +[[package]] +name = "csv" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d58633299b24b515ac72a3f869f8b91306a3cec616a602843a383acd6f9e97" +dependencies = [ + "bstr", + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +dependencies = [ + "memchr", +] + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + +[[package]] +name = "encoding_rs" +version = "0.8.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "erased-serde" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0465971a8cc1fa2455c8465aaa377131e1f1cf4983280f474a13e68793aa770c" +dependencies = [ + "serde", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +dependencies = [ + "matches", + "percent-encoding", +] + +[[package]] +name = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "futures" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f55667319111d593ba876406af7c409c0ebb44dc4be6132a783ccf163ea14c1" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c2dd2df839b57db9ab69c2c9d8f3e8c81984781937fe2807dc6dcf3b2ad2939" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15496a72fabf0e62bdc3df11a59a3787429221dd0710ba8ef163d6f7a9112c94" + +[[package]] +name = "futures-executor" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891a4b7b96d84d5940084b2a37632dd65deeae662c114ceaa2c879629c9c0ad1" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71c2c65c57704c32f5241c1223167c2c3294fd34ac020c807ddbe6db287ba59" + +[[package]] +name = "futures-macro" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea405816a5139fb39af82c2beb921d52143f556038378d6db21183a5c37fbfb7" +dependencies = [ + "proc-macro-hack", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85754d98985841b7d4f5e8e6fbfa4a4ac847916893ec511a2917ccd8525b8bb3" + +[[package]] +name = "futures-task" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa189ef211c15ee602667a6fcfe1c1fd9e07d42250d2156382820fba33c9df80" + +[[package]] +name = "futures-timer" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" + +[[package]] +name = "futures-util" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1812c7ab8aedf8d6f2701a43e1243acdbcc2b36ab26e2ad421eb99ac963d96d1" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "proc-macro-hack", + "proc-macro-nested", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + +[[package]] +name = "h2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d832b01df74254fe364568d6ddc294443f61cbec82816b60904303af87efae78" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "half" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62aca2aba2d62b4a7f5b33f3712cb1b0692779a56fb510499d5c0aa594daeaf3" + +[[package]] +name = "hashbrown" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" + +[[package]] +name = "hermit-abi" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" +dependencies = [ + "libc", +] + +[[package]] +name = "http" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7245cd7449cc792608c3c8a9eaf69bd4eabbabf802713748fd739c98b82f0747" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2861bd27ee074e5ee891e8b539837a9430012e249d7f0ca2d795650f579c1994" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "httparse" +version = "1.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "615caabe2c3160b313d52ccc905335f4ed5f10881dd63dc5699d47e90be85691" + +[[package]] +name = "httpdate" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47" + +[[package]] +name = "hyper" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8e946c2b1349055e0b72ae281b238baf1a3ea7307c7e9f9d64673bdd9c26ac7" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "idna" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89829a5d69c23d348314a7ac337fe39173b61149a9864deabd260983aed48c21" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "instant" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ipnet" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135" + +[[package]] +name = "itertools" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d572918e350e82412fe766d24b15e6682fb2ed2bbe018280caa810397cb319" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" + +[[package]] +name = "js-sys" +version = "0.3.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc9f84f9b115ce7843d60706df1422a916680bfdfcbdb0447c5614ff9d7e4d78" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" + +[[package]] +name = "lock_api" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "lua-src" +version = "542.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8866ea13f233a5fd3165080e4029b84f9df7107c80d3b338a5f775a810d9b4" +dependencies = [ + "cc", +] + +[[package]] +name = "luajit-src" +version = "210.1.2+resty29a66f7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ff31ac8626ef6c96d066f42f5adc963a0d1c60047cfa583d6b048c74b7e95f" +dependencies = [ + "cc", +] + +[[package]] +name = "matches" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" + +[[package]] +name = "memchr" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" + +[[package]] +name = "memoffset" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + +[[package]] +name = "mio" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5dede4e2065b3842b8b0af444119f3aa331cc7cc2dd20388bfb0f5d5a38823a" +dependencies = [ + "libc", + "log", + "miow", + "ntapi", + "winapi", +] + +[[package]] +name = "miow" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a33c1b55807fbed163481b5ba66db4b2fa6cde694a5027be10fb724206c5897" +dependencies = [ + "socket2", + "winapi", +] + +[[package]] +name = "mlua" +version = "0.5.3" +dependencies = [ + "bstr", + "cc", + "criterion", + "erased-serde", + "futures", + "futures-core", + "futures-task", + "futures-timer", + "futures-util", + "hyper", + "lazy_static", + "lua-src", + "luajit-src", + "mlua_derive", + "num-traits", + "pkg-config", + "reqwest", + "rustyline", + "serde", + "serde_json", + "tokio", + "trybuild", +] + +[[package]] +name = "mlua_derive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c392ad4a7c4414a819f1b16d04751bd21e94b3425f1b2cf79d4a87a4e78c5203" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "native-tls" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8d96b2e1c8da3957d58100b09f102c6d9cfdfced01b7ec5a8974044bb09dbd4" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "nix" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ccba0cfe4fdf15982d1674c69b1fd80bad427d293849982668dfe454bd61f2" +dependencies = [ + "bitflags", + "cc", + "cfg-if", + "libc", +] + +[[package]] +name = "ntapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +dependencies = [ + "winapi", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10acf907b94fc1b1a152d08ef97e7759650268cf986bf127f387e602b02c7e5a" + +[[package]] +name = "oorandom" +version = "11.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" + +[[package]] +name = "openssl" +version = "0.10.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038d43985d1ddca7a9900630d8cd031b56e4794eecc2e9ea39dd17aa04399a70" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "lazy_static", + "libc", + "openssl-sys", +] + +[[package]] +name = "openssl-probe" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" + +[[package]] +name = "openssl-sys" +version = "0.9.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "921fc71883267538946025deffb622905ecad223c28efbfdef9bb59a0175f3e6" +dependencies = [ + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "parking_lot" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" + +[[package]] +name = "pin-project" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96fa8ebb90271c4477f144354485b8068bd8f6b78b428b01ba892ca26caf0b63" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "758669ae3558c6f74bd2a18b41f7ac0b5a195aea6639d6a9b5e5d1ad5ba24c0b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439697af366c49a6d0a010c56a0d97685bc140ce0d377b13a2ea2aa42d64a827" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" + +[[package]] +name = "plotters" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45ca0ae5f169d0917a7c7f5a9c1a3d3d9598f18f529dd2b8373ed988efea307a" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b07fffcddc1cb3a1de753caa4e4df03b79922ba43cf882acc1bdd7e8df9f4590" + +[[package]] +name = "plotters-svg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b38a02e23bd9604b842a812063aec4ef702b57989c37b655254bb61c471ad211" +dependencies = [ + "plotters-backend", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" + +[[package]] +name = "proc-macro-hack" +version = "0.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" + +[[package]] +name = "proc-macro-nested" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" + +[[package]] +name = "proc-macro2" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rayon" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674" +dependencies = [ + "autocfg", + "crossbeam-deque", + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "lazy_static", + "num_cpus", +] + +[[package]] +name = "redox_syscall" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +dependencies = [ + "getrandom", + "redox_syscall", +] + +[[package]] +name = "regex" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4" +dependencies = [ + "byteorder", +] + +[[package]] +name = "regex-syntax" +version = "0.6.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "reqwest" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0460542b551950620a3648c6aa23318ac6b3cd779114bd873209e6e8b5eb1c34" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "http", + "http-body", + "hyper", + "hyper-tls", + "ipnet", + "js-sys", + "lazy_static", + "log", + "mime", + "native-tls", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-native-tls", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver", +] + +[[package]] +name = "rustyline" +version = "7.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8227301bfc717136f0ecbd3d064ba8199e44497a0bdd46bb01ede4387cfd2cec" +dependencies = [ + "bitflags", + "cfg-if", + "dirs-next", + "fs2", + "libc", + "log", + "memchr", + "nix", + "scopeguard", + "unicode-segmentation", + "unicode-width", + "utf8parse", + "winapi", +] + +[[package]] +name = "ryu" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +dependencies = [ + "lazy_static", + "winapi", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "security-framework" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfd318104249865096c8da1dfabf09ddbb6d0330ea176812a62ec75e40c4166" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee48cdde5ed250b0d3252818f646e174ab414036edb884dde62d80a3ac6082d" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "serde" +version = "1.0.123" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_cbor" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e18acfa2f90e8b735b2836ab8d538de304cbb6729a7360729ea5a895d15a622" +dependencies = [ + "half", + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.123" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "signal-hook-registry" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6" +dependencies = [ + "libc", +] + +[[package]] +name = "slab" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" + +[[package]] +name = "smallvec" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" + +[[package]] +name = "socket2" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" +dependencies = [ + "cfg-if", + "libc", + "winapi", +] + +[[package]] +name = "syn" +version = "1.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "tempfile" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +dependencies = [ + "cfg-if", + "libc", + "rand", + "redox_syscall", + "remove_dir_all", + "winapi", +] + +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "tinytemplate" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2ada8616fad06a2d0c455adc530de4ef57605a8120cc65da9653e0e9623ca74" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "tinyvec" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317cca572a0e89c3ce0ca1f1bdc9369547fe318a683418e42ac8f59d14701023" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] +name = "tokio" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8190d04c665ea9e6b6a0dc45523ade572c088d2e6566244c1122671dbf4ae3a" +dependencies = [ + "autocfg", + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "once_cell", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "tokio-macros", + "winapi", +] + +[[package]] +name = "tokio-macros" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf7b11a536f46a809a8a9f0bb4237020f70ecbf115b842360afb127ea2fda57" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebb7cb2f00c5ae8df755b252306272cd1790d39728363936e01827e11f0b017b" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "log", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +dependencies = [ + "serde", +] + +[[package]] +name = "tower-service" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" + +[[package]] +name = "tracing" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01ebdc2bb4498ab1ab5f5b73c5803825e60199229ccba0698170e3be0e7f959f" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f50de3927f93d202783f4513cda820ab47ef17f624b03c096e86ef00c67e6b5f" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + +[[package]] +name = "trybuild" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99471a206425fba51842a9186315f32d91c56eadc21ea4c21f847b59cf778f8b" +dependencies = [ + "glob", + "lazy_static", + "serde", + "serde_json", + "termcolor", + "toml", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" +dependencies = [ + "matches", +] + +[[package]] +name = "unicode-normalization" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796" + +[[package]] +name = "unicode-width" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" + +[[package]] +name = "unicode-xid" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" + +[[package]] +name = "url" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ccd964113622c8e9322cfac19eb1004a07e636c545f325da085d5cdde6f1f8b" +dependencies = [ + "form_urlencoded", + "idna", + "matches", + "percent-encoding", +] + +[[package]] +name = "utf8parse" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372" + +[[package]] +name = "vcpkg" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb" + +[[package]] +name = "walkdir" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "wasm-bindgen" +version = "0.2.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee1280240b7c461d6a0071313e08f34a60b0365f14260362e5a2b17d1d31aa7" +dependencies = [ + "cfg-if", + "serde", + "serde_json", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b7d8b6942b8bb3a9b0e73fc79b98095a27de6fa247615e59d096754a3bc2aa8" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e67a5806118af01f0d9045915676b22aaebecf4178ae7021bc171dab0b897ab" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ac38da8ef716661f0f36c0d8320b89028efe10c7c0afde65baffb496ce0d3b" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc053ec74d454df287b9374ee8abb36ffd5acb95ba87da3ba5b7d3fe20eb401e" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d6f8ec44822dd71f5f221a5847fb34acd9060535c1211b70a05844c0f6383b1" + +[[package]] +name = "web-sys" +version = "0.3.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec600b26223b2948cedfde2a0aa6756dcf1fef616f43d7b3097aaf53a6c4d92b" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "winreg" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" +dependencies = [ + "winapi", +] diff --git a/third_party/cargo/vendor/mlua-0.5.3/Cargo.toml b/third_party/cargo/vendor/mlua-0.5.3/Cargo.toml new file mode 100644 index 0000000..0260bc8 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/Cargo.toml @@ -0,0 +1,143 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +edition = "2018" +name = "mlua" +version = "0.5.3" +authors = ["Aleksandr Orlenko ", "kyren "] +build = "build/main.rs" +links = "lua" +description = "High level bindings to Lua 5.4/5.3/5.2/5.1 (including LuaJIT)\nwith async/await features and support of writing native lua modules in Rust.\n" +documentation = "https://docs.rs/mlua" +readme = "README.md" +keywords = ["lua", "luajit", "async", "futures", "scripting"] +categories = ["api-bindings", "asynchronous"] +license = "MIT" +repository = "https://github.com/khvzak/mlua" +[package.metadata.docs.rs] +features = ["lua53", "async", "send", "serialize"] +rustdoc-args = ["--cfg", "docsrs"] + +[[example]] +name = "async_http_client" +required-features = ["async"] + +[[example]] +name = "async_http_reqwest" +required-features = ["async", "serialize"] + +[[example]] +name = "async_http_server" +required-features = ["async", "send"] + +[[example]] +name = "async_tcp_server" +required-features = ["async"] + +[[example]] +name = "serialize" +required-features = ["serialize"] + +[[bench]] +name = "benchmark" +harness = false +required-features = ["async"] +[dependencies.bstr] +version = "0.2" +features = ["std"] +default_features = false + +[dependencies.erased-serde] +version = "0.3" +optional = true + +[dependencies.futures-core] +version = "0.3.5" +optional = true + +[dependencies.futures-task] +version = "0.3.5" +optional = true + +[dependencies.futures-util] +version = "0.3.5" +optional = true + +[dependencies.lazy_static] +version = "1.4" + +[dependencies.mlua_derive] +version = "0.5" +optional = true + +[dependencies.num-traits] +version = "0.2.14" + +[dependencies.serde] +version = "1.0" +optional = true +[dev-dependencies.criterion] +version = "0.3.4" +features = ["html_reports", "async_tokio"] + +[dev-dependencies.futures] +version = "0.3.5" + +[dev-dependencies.futures-timer] +version = "3.0" + +[dev-dependencies.hyper] +version = "0.14" +features = ["client", "server"] + +[dev-dependencies.reqwest] +version = "0.11" +features = ["json"] + +[dev-dependencies.rustyline] +version = "7.0" + +[dev-dependencies.serde_json] +version = "1.0" + +[dev-dependencies.tokio] +version = "1.0" +features = ["full"] + +[dev-dependencies.trybuild] +version = "1.0" +[build-dependencies.cc] +version = "1.0" + +[build-dependencies.lua-src] +version = ">= 540.0.0, < 550.0.0" +optional = true + +[build-dependencies.luajit-src] +version = ">= 210.1.2, < 220.0.0" +optional = true + +[build-dependencies.pkg-config] +version = "0.3.17" + +[features] +async = ["futures-core", "futures-task", "futures-util"] +lua51 = [] +lua52 = [] +lua53 = [] +lua54 = [] +luajit = [] +module = ["mlua_derive"] +send = [] +serialize = ["serde", "erased-serde"] +vendored = ["lua-src", "luajit-src"] diff --git a/third_party/cargo/vendor/mlua-0.5.3/LICENSE b/third_party/cargo/vendor/mlua-0.5.3/LICENSE new file mode 100644 index 0000000..66f2fa3 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/LICENSE @@ -0,0 +1,25 @@ +Both mlua and rlua are distributed under the MIT license, which is reproduced +below: + +MIT License + +Copyright (c) 2019-2021 A. Orlenko +Copyright (c) 2017 rlua + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/third_party/cargo/vendor/mlua-0.5.3/README.md b/third_party/cargo/vendor/mlua-0.5.3/README.md new file mode 100644 index 0000000..af6fda8 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/README.md @@ -0,0 +1,239 @@ +# mlua +[![Build Status]][github-actions] [![Latest Version]][crates.io] [![API Documentation]][docs.rs] [![Coverage Status]][codecov.io] + +[Build Status]: https://github.com/khvzak/mlua/workflows/CI/badge.svg +[github-actions]: https://github.com/khvzak/mlua/actions +[Latest Version]: https://img.shields.io/crates/v/mlua.svg +[crates.io]: https://crates.io/crates/mlua +[API Documentation]: https://docs.rs/mlua/badge.svg +[docs.rs]: https://docs.rs/mlua +[Coverage Status]: https://codecov.io/gh/khvzak/mlua/branch/master/graph/badge.svg?token=99339FS1CG +[codecov.io]: https://codecov.io/gh/khvzak/mlua + +[Guided Tour](examples/guided_tour.rs) + +`mlua` is bindings to [Lua](https://www.lua.org) programming language for Rust with a goal to provide +_safe_ (as far as it's possible), high level, easy to use, practical and flexible API. + +Started as [rlua](https://github.com/amethyst/rlua/tree/0.15.3) fork, `mlua` supports Lua 5.4, 5.3, 5.2 and 5.1 including LuaJIT (2.0.5 and 2.1 beta) and allows to write native Lua modules in Rust as well as use Lua in a standalone mode. + +`mlua` tested on Windows/macOS/Linux including module mode in [GitHub Actions] on `x86_64` platform and cross-compilation to `aarch64` (other targes are also supported). + +[GitHub Actions]: https://github.com/khvzak/mlua/actions + +## Usage + +### Feature flags + +`mlua` uses feature flags to reduce the amount of depenendies, compiled code and allow to choose only required set of features. +Below is a list of the available feature flags. By default `mlua` does not enable any features. + +* `lua54`: activate Lua [5.4] support +* `lua53`: activate Lua [5.3] support +* `lua52`: activate Lua [5.2] support +* `lua51`: activate Lua [5.1] support +* `luajit`: activate [LuaJIT] support +* `vendored`: build static Lua(JIT) library from sources during `mlua` compilation using [lua-src] or [luajit-src] crates +* `module`: enable module mode (building loadable `cdylib` library for Lua) +* `async`: enable async/await support (any executor can be used, eg. [tokio] or [async-std]) +* `send`: make `mlua::Lua` transferable across thread boundaries (adds [`Send`] requirement to `mlua::Function` and `mlua::UserData`) +* `serialize`: add serialization and deserialization support to `mlua` types usign [serde] framework + +[5.4]: https://www.lua.org/manual/5.4/manual.html +[5.3]: https://www.lua.org/manual/5.3/manual.html +[5.2]: https://www.lua.org/manual/5.2/manual.html +[5.1]: https://www.lua.org/manual/5.1/manual.html +[LuaJIT]: https://luajit.org/ +[lua-src]: https://github.com/khvzak/lua-src-rs +[luajit-src]: https://github.com/khvzak/luajit-src-rs +[tokio]: https://github.com/tokio-rs/tokio +[async-std]: https://github.com/async-rs/async-std +[`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html +[serde]: https://github.com/serde-rs/serde + +### Async/await support + +`mlua` supports async/await for all Lua versions. This works using Lua [coroutines](https://www.lua.org/manual/5.3/manual.html#2.6) and require running [Thread](https://docs.rs/mlua/latest/mlua/struct.Thread.html) along with enabling `feature = "async"` in `Cargo.toml`. + +**Examples**: +- [HTTP Client](examples/async_http_client.rs) +- [HTTP Client (json)](examples/async_http_reqwest.rs) +- [HTTP Server](examples/async_http_server.rs) +- [TCP Server](examples/async_tcp_server.rs) + +### Serialization (serde) support + +With `serialize` feature flag enabled, `mlua` allows you to serialize/deserialize any type that implements [`serde::Serialize`] and [`serde::Deserialize`] into/from [`mlua::Value`]. In addition `mlua` provides [`serde::Serialize`] trait implementation for it (including `UserData` support). + +[Example](examples/serialize.rs) + +[`serde::Serialize`]: https://docs.serde.rs/serde/ser/trait.Serialize.html +[`serde::Deserialize`]: https://docs.serde.rs/serde/de/trait.Deserialize.html +[`mlua::Value`]: https://docs.rs/mlua/latest/mlua/enum.Value.html + +### Compiling + +You have to enable one of the features `lua54`, `lua53`, `lua52`, `lua51` or `luajit`, according to the choosen Lua version. + +By default `mlua` uses `pkg-config` tool to find lua includes and libraries for the chosen Lua version. +In most cases it works as desired, although sometimes could be more preferable to use a custom lua library. +To achieve this, mlua supports `LUA_INC`, `LUA_LIB`, `LUA_LIB_NAME` and `LUA_LINK` environment variables. +`LUA_LINK` is optional and may be `dylib` (a dynamic library) or `static` (a static library, `.a` archive). + +An example how to use them: +``` sh +my_project $ LUA_INC=$HOME/tmp/lua-5.2.4/src LUA_LIB=$HOME/tmp/lua-5.2.4/src LUA_LIB_NAME=lua LUA_LINK=static cargo build +``` + +`mlua` also supports vendored lua/luajit using the auxilary crates [lua-src](https://crates.io/crates/lua-src) and +[luajit-src](https://crates.io/crates/luajit-src). +Just enable the `vendored` feature and cargo will automatically build and link specified lua/luajit version. This is the easiest way to get started with `mlua`. + +### Standalone mode +In a standalone mode `mlua` allows to add to your application scripting support with a gently configured Lua runtime to ensure safety and soundness. + +Add to `Cargo.toml` : + +``` toml +[dependencies] +mlua = { version = "0.5", features = ["lua53", "vendored"] } +``` + +`main.rs` + +``` rust +use mlua::prelude::*; + +fn main() -> LuaResult<()> { + let lua = Lua::new(); + + let map_table = lua.create_table()?; + map_table.set(1, "one")?; + map_table.set("two", 2)?; + + lua.globals().set("map_table", map_table)?; + + lua.load("for k,v in pairs(map_table) do print(k,v) end").exec()?; + + Ok(()) +} +``` + +### Module mode +In a module mode `mlua` allows to create a compiled Lua module that can be loaded from Lua code using [`require`](https://www.lua.org/manual/5.3/manual.html#pdf-require). In this case `mlua` uses an external Lua runtime which could lead to potential unsafety due to unpredictability of the Lua environment and usage of libraries such as [`debug`](https://www.lua.org/manual/5.3/manual.html#6.10). + +[Example](examples/module) + +Add to `Cargo.toml` : + +``` toml +[lib] +crate-type = ["cdylib"] + +[dependencies] +mlua = { version = "0.5", features = ["lua53", "vendored", "module"] } +``` + +`lib.rs` : + +``` rust +use mlua::prelude::*; + +fn hello(_: &Lua, name: String) -> LuaResult<()> { + println!("hello, {}!", name); + Ok(()) +} + +#[mlua::lua_module] +fn my_module(lua: &Lua) -> LuaResult { + let exports = lua.create_table()?; + exports.set("hello", lua.create_function(hello)?)?; + Ok(exports) +} +``` + +And then (**macOS** example): + +``` sh +$ cargo rustc -- -C link-arg=-undefined -C link-arg=dynamic_lookup +$ ln -s ./target/debug/libmy_module.dylib ./my_module.so +$ lua5.3 -e 'require("my_module").hello("world")' +hello, world! +``` + +On macOS, you need to set additional linker arguments. One option is to compile with `cargo rustc --release -- -C link-arg=-undefined -C link-arg=dynamic_lookup`, the other is to create a `.cargo/config` with the following content: +``` toml +[target.x86_64-apple-darwin] +rustflags = [ + "-C", "link-arg=-undefined", + "-C", "link-arg=dynamic_lookup", +] + +[target.aarch64-apple-darwin] +rustflags = [ + "-C", "link-arg=-undefined", + "-C", "link-arg=dynamic_lookup", +] +``` +On Linux you can build modules normally with `cargo build --release`. +Vendored and non-vendored builds are supported for these OS. + +On Windows `vendored` mode for modules is not supported since you need to link to a Lua dll. +Easiest way is to use either MinGW64 (as part of [MSYS2](https://github.com/msys2/msys2) package) with `pkg-config` or +MSVC with `LUA_INC` / `LUA_LIB` / `LUA_LIB_NAME` environment variables. + +More details about compiling and linking Lua modules can be found on the [Building Modules](http://lua-users.org/wiki/BuildingModules) page. + +## Safety + +One of the `mlua` goals is to provide *safe* API between Rust and Lua. +Every place where the Lua C API may trigger an error longjmp in any way is protected by `lua_pcall`, +and the user of the library is protected from directly interacting with unsafe things like the Lua stack, +and there is overhead associated with this safety. + +Unfortunately, `mlua` does not provide absolute safety even without using `unsafe` . +This library contains a huge amount of unsafe code. There are almost certainly bugs still lurking in this library! +It is surprisingly, fiendishly difficult to use the Lua C API without the potential for unsafety. + +## Panic handling + +`mlua` wraps panics that are generated inside Rust callbacks in a regular Lua error. Panics could be +resumed then by propagating the Lua error to Rust code. + +For example: +``` rust +let lua = Lua::new(); +let f = lua.create_function(|_, ()| -> LuaResult<()> { + panic!("test panic"); +})?; +lua.globals().set("rust_func", f)?; + +let _ = lua.load(r#" + local status, err = pcall(rust_func) + print(err) -- prints: test panic + error(err) -- propagate panic +"#).exec(); + +unreachable!() +``` + +`mlua` should also be panic safe in another way as well, which is that any `Lua` instances or handles +remains usable after a user generated panic, and such panics should not break internal invariants or +leak Lua stack space. This is mostly important to safely use `mlua` types in Drop impls, as you should not be +using panics for general error handling. + +Below is a list of `mlua` behaviors that should be considered a bug. +If you encounter them, a bug report would be very welcome: + + + If your program panics with a message that contains the string "mlua internal error", this is a bug. + + + The above is true even for the internal panic about running out of stack space! There are a few ways to generate normal script errors by running out of stack, but if you encounter a *panic* based on running out of stack, this is a bug. + + + Lua C API errors are handled by lonjmp. All instances where the Lua C API would otherwise longjmp over calling stack frames should be guarded against, except in internal callbacks where this is intentional. If you detect that `mlua` is triggering a longjmp over your Rust stack frames, this is a bug! + + + If you detect that, after catching a panic or during a Drop triggered from a panic, a `Lua` or handle method is triggering other bugs or there is a Lua stack space leak, this is a bug. `mlua` instances are supposed to remain fully usable in the face of user generated panics. This guarantee does not extend to panics marked with "mlua internal error" simply because that is already indicative of a separate bug. + +## License + +This project is licensed under the [MIT license](LICENSE) + diff --git a/third_party/cargo/vendor/mlua-0.5.3/benches/benchmark.rs b/third_party/cargo/vendor/mlua-0.5.3/benches/benchmark.rs new file mode 100644 index 0000000..7f59ce2 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/benches/benchmark.rs @@ -0,0 +1,283 @@ +#![cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + feature(link_args) +)] + +#[cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + link_args = "-pagezero_size 10000 -image_base 100000000", + allow(unused_attributes) +)] +extern "system" {} + +use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; +use std::time::Duration; +use tokio::runtime::Runtime; +use tokio::task; + +use mlua::prelude::*; + +fn collect_gc_twice(lua: &Lua) { + lua.gc_collect().unwrap(); + lua.gc_collect().unwrap(); +} + +fn create_table(c: &mut Criterion) { + let lua = Lua::new(); + + c.bench_function("create [table empty]", |b| { + b.iter_batched( + || collect_gc_twice(&lua), + |_| { + lua.create_table().unwrap(); + }, + BatchSize::SmallInput, + ); + }); +} + +fn create_array(c: &mut Criterion) { + let lua = Lua::new(); + + c.bench_function("create [array] 10", |b| { + b.iter_batched( + || collect_gc_twice(&lua), + |_| { + let table = lua.create_table().unwrap(); + for i in 1..=10 { + table.set(i, i).unwrap(); + } + }, + BatchSize::SmallInput, + ); + }); +} + +fn create_string_table(c: &mut Criterion) { + let lua = Lua::new(); + + c.bench_function("create [table string] 10", |b| { + b.iter_batched( + || collect_gc_twice(&lua), + |_| { + let table = lua.create_table().unwrap(); + for &s in &["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"] { + let s = lua.create_string(s).unwrap(); + table.set(s.clone(), s).unwrap(); + } + }, + BatchSize::SmallInput, + ); + }); +} + +fn call_lua_function(c: &mut Criterion) { + let lua = Lua::new(); + + c.bench_function("call Lua function [sum] 3 10", |b| { + b.iter_batched_ref( + || { + collect_gc_twice(&lua); + lua.load("function(a, b, c) return a + b + c end") + .eval::() + .unwrap() + }, + |function| { + for i in 0..10 { + let _result: i64 = function.call((i, i + 1, i + 2)).unwrap(); + } + }, + BatchSize::SmallInput, + ); + }); +} + +fn call_sum_callback(c: &mut Criterion) { + let lua = Lua::new(); + let callback = lua + .create_function(|_, (a, b, c): (i64, i64, i64)| Ok(a + b + c)) + .unwrap(); + lua.globals().set("callback", callback).unwrap(); + + c.bench_function("call Rust callback [sum] 3 10", |b| { + b.iter_batched_ref( + || { + collect_gc_twice(&lua); + lua.load("function() for i = 1,10 do callback(i, i+1, i+2) end end") + .eval::() + .unwrap() + }, + |function| { + function.call::<_, ()>(()).unwrap(); + }, + BatchSize::SmallInput, + ); + }); +} + +fn call_async_sum_callback(c: &mut Criterion) { + let lua = Lua::new(); + let callback = lua + .create_async_function(|_, (a, b, c): (i64, i64, i64)| async move { + task::yield_now().await; + Ok(a + b + c) + }) + .unwrap(); + lua.globals().set("callback", callback).unwrap(); + + c.bench_function("call async Rust callback [sum] 3 10", |b| { + let rt = Runtime::new().unwrap(); + b.to_async(rt).iter_batched( + || { + collect_gc_twice(&lua); + lua.load("function() for i = 1,10 do callback(i, i+1, i+2) end end") + .eval::() + .unwrap() + }, + |function| async move { + function.call_async::<_, ()>(()).await.unwrap(); + }, + BatchSize::SmallInput, + ); + }); +} + +fn call_concat_callback(c: &mut Criterion) { + let lua = Lua::new(); + let callback = lua + .create_function(|_, (a, b): (LuaString, LuaString)| { + Ok(format!("{}{}", a.to_str()?, b.to_str()?)) + }) + .unwrap(); + lua.globals().set("callback", callback).unwrap(); + + c.bench_function("call Rust callback [concat string] 10", |b| { + b.iter_batched_ref( + || { + collect_gc_twice(&lua); + lua.load("function() for i = 1,10 do callback('a', tostring(i)) end end") + .eval::() + .unwrap() + }, + |function| { + function.call::<_, ()>(()).unwrap(); + }, + BatchSize::SmallInput, + ); + }); +} + +fn create_registry_values(c: &mut Criterion) { + let lua = Lua::new(); + + c.bench_function("create [registry value] 10", |b| { + b.iter_batched( + || collect_gc_twice(&lua), + |_| { + for _ in 0..10 { + lua.create_registry_value(lua.pack(true).unwrap()).unwrap(); + } + lua.expire_registry_values(); + }, + BatchSize::SmallInput, + ); + }); +} + +fn create_userdata(c: &mut Criterion) { + struct UserData(i64); + impl LuaUserData for UserData {} + + let lua = Lua::new(); + + c.bench_function("create [table userdata] 10", |b| { + b.iter_batched( + || collect_gc_twice(&lua), + |_| { + let table: LuaTable = lua.create_table().unwrap(); + for i in 1..11 { + table.set(i, UserData(i)).unwrap(); + } + }, + BatchSize::SmallInput, + ); + }); +} + +fn call_userdata_method(c: &mut Criterion) { + struct UserData(i64); + impl LuaUserData for UserData { + fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_method("method", |_, this, ()| Ok(this.0)); + } + } + + let lua = Lua::new(); + lua.globals().set("userdata", UserData(10)).unwrap(); + + c.bench_function("call [userdata method] 10", |b| { + b.iter_batched_ref( + || { + collect_gc_twice(&lua); + lua.load("function() for i = 1,10 do userdata:method() end end") + .eval::() + .unwrap() + }, + |function| { + function.call::<_, ()>(()).unwrap(); + }, + BatchSize::SmallInput, + ); + }); +} + +fn call_async_userdata_method(c: &mut Criterion) { + #[derive(Clone, Copy)] + struct UserData(i64); + impl LuaUserData for UserData { + fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_async_method("method", |_, this, ()| async move { Ok(this.0) }); + } + } + + let lua = Lua::new(); + lua.globals().set("userdata", UserData(10)).unwrap(); + + c.bench_function("call async [userdata method] 10", |b| { + let rt = Runtime::new().unwrap(); + b.to_async(rt).iter_batched( + || { + collect_gc_twice(&lua); + lua.load("function() for i = 1,10 do userdata:method() end end") + .eval::() + .unwrap() + }, + |function| async move { + function.call_async::<_, ()>(()).await.unwrap(); + }, + BatchSize::SmallInput, + ); + }); +} + +criterion_group! { + name = benches; + config = Criterion::default() + .sample_size(300) + .measurement_time(Duration::from_secs(10)) + .noise_threshold(0.02); + targets = + create_table, + create_array, + create_string_table, + call_lua_function, + call_sum_callback, + call_async_sum_callback, + call_concat_callback, + create_registry_values, + create_userdata, + call_userdata_method, + call_async_userdata_method, +} + +criterion_main!(benches); diff --git a/third_party/cargo/vendor/mlua-0.5.3/build/find_dummy.rs b/third_party/cargo/vendor/mlua-0.5.3/build/find_dummy.rs new file mode 100644 index 0000000..b80fc90 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/build/find_dummy.rs @@ -0,0 +1,5 @@ +use std::path::PathBuf; + +pub fn probe_lua() -> PathBuf { + unreachable!() +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/build/find_normal.rs b/third_party/cargo/vendor/mlua-0.5.3/build/find_normal.rs new file mode 100644 index 0000000..0edc22c --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/build/find_normal.rs @@ -0,0 +1,138 @@ +use std::env; +use std::fs::File; +use std::io::{BufRead, BufReader, Result}; +use std::ops::Bound; +use std::path::{Path, PathBuf}; + +pub fn probe_lua() -> PathBuf { + let include_dir = env::var_os("LUA_INC").unwrap_or_default(); + let lib_dir = env::var_os("LUA_LIB").unwrap_or_default(); + let lua_lib = env::var_os("LUA_LIB_NAME").unwrap_or_default(); + + println!("cargo:rerun-if-env-changed=LUA_INC"); + println!("cargo:rerun-if-env-changed=LUA_LIB"); + println!("cargo:rerun-if-env-changed=LUA_LIB_NAME"); + println!("cargo:rerun-if-env-changed=LUA_LINK"); + + let need_lua_lib = cfg!(any(not(feature = "module"), target_os = "windows")); + + if include_dir != "" && (!need_lua_lib || lib_dir != "") { + if lua_lib == "" { + panic!("LUA_LIB_NAME is not set"); + } + let _version = use_custom_lua(&include_dir, &lib_dir, &lua_lib).unwrap(); + return PathBuf::from(include_dir); + } + + // Find using `pkg-config` + + #[cfg(feature = "lua54")] + { + let mut lua = pkg_config::Config::new() + .range_version((Bound::Included("5.4"), Bound::Excluded("5.5"))) + .cargo_metadata(need_lua_lib) + .probe("lua"); + + if lua.is_err() { + lua = pkg_config::Config::new() + .cargo_metadata(need_lua_lib) + .probe("lua5.4"); + } + + lua.unwrap().include_paths[0].clone() + } + + #[cfg(feature = "lua53")] + { + let mut lua = pkg_config::Config::new() + .range_version((Bound::Included("5.3"), Bound::Excluded("5.4"))) + .cargo_metadata(need_lua_lib) + .probe("lua"); + + if lua.is_err() { + lua = pkg_config::Config::new() + .cargo_metadata(need_lua_lib) + .probe("lua5.3"); + } + + lua.unwrap().include_paths[0].clone() + } + + #[cfg(feature = "lua52")] + { + let mut lua = pkg_config::Config::new() + .range_version((Bound::Included("5.2"), Bound::Excluded("5.3"))) + .cargo_metadata(need_lua_lib) + .probe("lua"); + + if lua.is_err() { + lua = pkg_config::Config::new() + .cargo_metadata(need_lua_lib) + .probe("lua5.2"); + } + + lua.unwrap().include_paths[0].clone() + } + + #[cfg(feature = "lua51")] + { + let mut lua = pkg_config::Config::new() + .range_version((Bound::Included("5.1"), Bound::Excluded("5.2"))) + .cargo_metadata(need_lua_lib) + .probe("lua"); + + if lua.is_err() { + lua = pkg_config::Config::new() + .cargo_metadata(need_lua_lib) + .probe("lua5.1"); + } + + lua.unwrap().include_paths[0].clone() + } + + #[cfg(feature = "luajit")] + { + let lua = pkg_config::Config::new() + .range_version((Bound::Included("2.0.5"), Bound::Unbounded)) + .cargo_metadata(need_lua_lib) + .probe("luajit"); + + lua.unwrap().include_paths[0].clone() + } +} + +fn use_custom_lua>(include_dir: &S, lib_dir: &S, lua_lib: &S) -> Result { + let mut version_found = String::new(); + + // Find LUA_VERSION_NUM + let mut lua_h_path = include_dir.as_ref().to_owned(); + lua_h_path.push("lua.h"); + let f = File::open(lua_h_path)?; + let reader = BufReader::new(f); + for line in reader.lines() { + let line = line?; + let parts = line.split_whitespace().collect::>(); + if parts.len() == 3 && parts[1] == "LUA_VERSION_NUM" { + version_found = parts[2].to_string(); + } + } + + let link_lib = match env::var("LUA_LINK") { + Ok(s) if s == "static" => "static=", + _ => "", + }; + + if cfg!(any(not(feature = "module"), target_os = "windows")) { + println!( + "cargo:rustc-link-search=native={}", + lib_dir.as_ref().display() + ); + println!( + "cargo:rustc-link-lib={}{}", + link_lib, + lua_lib.as_ref().display() + ); + } + + Ok(version_found) +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/build/find_vendored.rs b/third_party/cargo/vendor/mlua-0.5.3/build/find_vendored.rs new file mode 100644 index 0000000..25ed510 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/build/find_vendored.rs @@ -0,0 +1,19 @@ +use std::path::PathBuf; + +pub fn probe_lua() -> PathBuf { + #[cfg(feature = "lua54")] + let artifacts = lua_src::Build::new().build(lua_src::Lua54); + #[cfg(feature = "lua53")] + let artifacts = lua_src::Build::new().build(lua_src::Lua53); + #[cfg(feature = "lua52")] + let artifacts = lua_src::Build::new().build(lua_src::Lua52); + #[cfg(feature = "lua51")] + let artifacts = lua_src::Build::new().build(lua_src::Lua51); + #[cfg(feature = "luajit")] + let artifacts = luajit_src::Build::new().build(); + + #[cfg(not(feature = "module"))] + artifacts.print_cargo_metadata(); + + artifacts.include_dir().to_owned() +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/build/main.rs b/third_party/cargo/vendor/mlua-0.5.3/build/main.rs new file mode 100644 index 0000000..e5149d5 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/build/main.rs @@ -0,0 +1,240 @@ +#![allow(unreachable_code)] + +use std::env; +use std::fs::File; +use std::io::{Error, ErrorKind, Result, Write}; +use std::path::{Path, PathBuf}; +use std::process::Command; + +#[cfg_attr( + all( + feature = "vendored", + any( + feature = "lua54", + feature = "lua53", + feature = "lua52", + feature = "lua51", + feature = "luajit" + ) + ), + path = "find_vendored.rs" +)] +#[cfg_attr( + all( + not(feature = "vendored"), + any( + feature = "lua54", + feature = "lua53", + feature = "lua52", + feature = "lua51", + feature = "luajit" + ) + ), + path = "find_normal.rs" +)] +#[cfg_attr( + not(any( + feature = "lua54", + feature = "lua53", + feature = "lua52", + feature = "lua51", + feature = "luajit" + )), + path = "find_dummy.rs" +)] +mod find; + +trait CommandExt { + fn execute(&mut self) -> Result<()>; +} + +impl CommandExt for Command { + /// Execute the command and return an error if it exited with a failure status. + fn execute(&mut self) -> Result<()> { + self.status() + .and_then(|status| { + if status.success() { + Ok(()) + } else { + Err(Error::new(ErrorKind::Other, "non-zero exit code")) + } + }) + .map_err(|_| { + Error::new( + ErrorKind::Other, + format!("The command {:?} did not run successfully.", self), + ) + }) + } +} + +fn build_glue + std::fmt::Debug>(include_path: &P) { + let build_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + + let mut config = cc::Build::new(); + config.include(include_path); + + // Compile and run glue.c + let glue = build_dir.join("glue"); + + config + .get_compiler() + .to_command() + .arg("src/ffi/glue/glue.c") + .arg("-o") + .arg(&glue) + .execute() + .unwrap(); + + Command::new(glue) + .arg(build_dir.join("glue.rs")) + .execute() + .unwrap(); +} + +// When cross-compiling, we cannot use `build_glue` as we cannot run the generated +// executable. Instead, let's take a stab at synthesizing the likely values. +// If you're cross-compiling and using a non-vendored library then there is a chance +// that the values selected here may be incorrect, but we have no way to determine +// that here. +fn generate_glue() -> Result<()> { + let build_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + let mut glue = File::create(build_dir.join("glue.rs"))?; + writeln!( + glue, + "/* This file was generated by build/main.rs; do not modify by hand */" + )?; + writeln!(glue, "use std::os::raw::*;")?; + + writeln!(glue, "/* luaconf.h */")?; + let pointer_bit_width: usize = env::var("CARGO_CFG_TARGET_POINTER_WIDTH") + .unwrap() + .parse() + .unwrap(); + writeln!( + glue, + "pub const LUA_EXTRASPACE: c_int = {} / 8;", + pointer_bit_width + )?; + + // This is generally hardcoded to this size + writeln!(glue, "pub const LUA_IDSIZE: c_int = 60;")?; + + // Unless the target is restricted, the defaults are 64 bit + writeln!(glue, "pub type LUA_NUMBER = c_double;")?; + writeln!(glue, "pub type LUA_INTEGER = i64;")?; + writeln!(glue, "pub type LUA_UNSIGNED = u64;")?; + + writeln!(glue, "/* lua.h */")?; + let version = if cfg!(any(feature = "luajit", feature = "lua51")) { + (5, 1, 0) + } else if cfg!(feature = "lua52") { + (5, 2, 0) + } else if cfg!(feature = "lua53") { + (5, 3, 0) + } else if cfg!(feature = "lua54") { + (5, 4, 0) + } else { + unreachable!(); + }; + writeln!( + glue, + "pub const LUA_VERSION_NUM: c_int = {};", + (version.0 * 100) + version.1 + )?; + + let max_stack = if pointer_bit_width >= 32 { + 1_000_000 + } else { + 15_000 + }; + writeln!( + glue, + "pub const LUA_REGISTRYINDEX: c_int = -{} - 1000;", + max_stack + )?; + + // These two are only defined in lua 5.1 + writeln!(glue, "pub const LUA_ENVIRONINDEX: c_int = -10001;")?; + writeln!(glue, "pub const LUA_GLOBALSINDEX: c_int = -10002;")?; + + writeln!(glue, "/* lauxlib.h */")?; + // This is only defined in lua 5.3 and up, but we can always generate its value here, + // even if we don't use it. + // This matches the default definition in lauxlib.h + writeln!(glue, "pub const LUAL_NUMSIZES: c_int = std::mem::size_of::() as c_int * 16 + std::mem::size_of::() as c_int;")?; + + writeln!(glue, "/* lualib.h */")?; + write!( + glue, + r#" +#[cfg(feature = "luajit")] +pub const LUA_BITLIBNAME: &str = "bit"; +#[cfg(not(feature = "luajit"))] +pub const LUA_BITLIBNAME: &str = "bit32"; + +pub const LUA_COLIBNAME: &str = "coroutine"; +pub const LUA_DBLIBNAME: &str = "debug"; +pub const LUA_IOLIBNAME: &str = "io"; +pub const LUA_LOADLIBNAME: &str = "package"; +pub const LUA_MATHLIBNAME: &str = "math"; +pub const LUA_OSLIBNAME: &str = "os"; +pub const LUA_STRLIBNAME: &str = "string"; +pub const LUA_TABLIBNAME: &str = "table"; +pub const LUA_UTF8LIBNAME: &str = "utf8"; + +pub const LUA_JITLIBNAME: &str = "jit"; +pub const LUA_FFILIBNAME: &str = "ffi"; +"# + )?; + + Ok(()) +} + +fn main() { + #[cfg(not(any( + feature = "lua54", + feature = "lua53", + feature = "lua52", + feature = "lua51", + feature = "luajit" + )))] + compile_error!("You must enable one of the features: lua54, lua53, lua52, lua51, luajit"); + + #[cfg(all( + feature = "lua54", + any( + feature = "lua53", + feature = "lua52", + feature = "lua51", + feature = "luajit" + ) + ))] + compile_error!("You can enable only one of the features: lua54, lua53, lua52, lua51, luajit"); + + #[cfg(all( + feature = "lua53", + any(feature = "lua52", feature = "lua51", feature = "luajit") + ))] + compile_error!("You can enable only one of the features: lua54, lua53, lua52, lua51, luajit"); + + #[cfg(all(feature = "lua52", any(feature = "lua51", feature = "luajit")))] + compile_error!("You can enable only one of the features: lua54, lua53, lua52, lua51, luajit"); + + #[cfg(all(feature = "lua51", feature = "luajit"))] + compile_error!("You can enable only one of the features: lua54, lua53, lua52, lua51, luajit"); + + // We don't support "vendored module" mode on windows + #[cfg(all(feature = "vendored", feature = "module", target_os = "windows"))] + compile_error!( + "Vendored (static) builds are not supported for modules on Windows.\n" + + "Please, use `pkg-config` or custom mode to link to a Lua dll." + ); + + let include_dir = find::probe_lua(); + if env::var("TARGET").unwrap() != env::var("HOST").unwrap() { + generate_glue().unwrap(); + } else { + build_glue(&include_dir); + } +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/examples/async_http_client.rs b/third_party/cargo/vendor/mlua-0.5.3/examples/async_http_client.rs new file mode 100644 index 0000000..f8c0793 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/examples/async_http_client.rs @@ -0,0 +1,83 @@ +use std::collections::HashMap; +use std::sync::Arc; + +use bstr::BString; +use hyper::body::{Body as HyperBody, HttpBody as _}; +use hyper::Client as HyperClient; +use tokio::sync::Mutex; + +use mlua::{Error, Lua, Result, UserData, UserDataMethods}; + +#[derive(Clone)] +struct BodyReader(Arc>); + +impl BodyReader { + fn new(body: HyperBody) -> Self { + BodyReader(Arc::new(Mutex::new(body))) + } +} + +impl UserData for BodyReader { + fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_async_method("read", |_, reader, ()| async move { + let mut reader = reader.0.lock().await; + if let Some(bytes) = reader.data().await { + let bytes = bytes.map_err(Error::external)?; + return Ok(Some(BString::from(bytes.as_ref()))); + } + Ok(None) + }); + } +} + +#[tokio::main] +async fn main() -> Result<()> { + let lua = Lua::new(); + + let fetch_url = lua.create_async_function(|lua, uri: String| async move { + let client = HyperClient::new(); + let uri = uri.parse().map_err(Error::external)?; + let resp = client.get(uri).await.map_err(Error::external)?; + + let lua_resp = lua.create_table()?; + lua_resp.set("status", resp.status().as_u16())?; + + let mut headers = HashMap::new(); + for (key, value) in resp.headers().iter() { + headers + .entry(key.as_str()) + .or_insert(Vec::new()) + .push(value.to_str().unwrap()); + } + + lua_resp.set("headers", headers)?; + lua_resp.set("body", BodyReader::new(resp.into_body()))?; + + Ok(lua_resp) + })?; + + let globals = lua.globals(); + globals.set("fetch_url", fetch_url)?; + + let f = lua + .load( + r#" + local res = fetch_url(...) + print(res.status) + for key, vals in pairs(res.headers) do + for _, val in ipairs(vals) do + print(key..": "..val) + end + end + repeat + local body = res.body:read() + if body then + print(body) + end + until not body + "#, + ) + .into_function()?; + + f.call_async("http://httpbin.org/ip").await +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/examples/async_http_reqwest.rs b/third_party/cargo/vendor/mlua-0.5.3/examples/async_http_reqwest.rs new file mode 100644 index 0000000..5c68bc6 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/examples/async_http_reqwest.rs @@ -0,0 +1,41 @@ +use mlua::{Error, Lua, LuaSerdeExt, Result}; + +#[tokio::main] +async fn main() -> Result<()> { + let lua = Lua::new(); + let globals = lua.globals(); + globals.set("null", lua.null()?)?; + + let fetch_json = lua.create_async_function(|lua, uri: String| async move { + let resp = reqwest::get(&uri) + .await + .and_then(|resp| resp.error_for_status()) + .map_err(Error::external)?; + let json = resp + .json::() + .await + .map_err(Error::external)?; + lua.to_value(&json) + })?; + globals.set("fetch_json", fetch_json)?; + + let f = lua + .load( + r#" + function print_r(t, indent) + local indent = indent or '' + for k, v in pairs(t) do + io.write(indent, tostring(k)) + if type(v) == "table" then io.write(':\n') print_r(v, indent..' ') + else io.write(': ', v == null and "null" or tostring(v), '\n') end + end + end + + local res = fetch_json(...) + print_r(res) + "#, + ) + .into_function()?; + + f.call_async("https://httpbin.org/anything?arg0=val0").await +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/examples/async_http_server.rs b/third_party/cargo/vendor/mlua-0.5.3/examples/async_http_server.rs new file mode 100644 index 0000000..6eb9fa1 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/examples/async_http_server.rs @@ -0,0 +1,101 @@ +use std::net::SocketAddr; +use std::sync::Arc; + +use hyper::server::conn::AddrStream; +use hyper::service::{make_service_fn, service_fn}; +use hyper::{Body, Request, Response, Server}; + +use mlua::{Error, Function, Lua, Result, Table, UserData, UserDataMethods}; + +#[derive(Clone)] +struct LuaRequest(Arc<(SocketAddr, Request)>); + +impl UserData for LuaRequest { + fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_method("remote_addr", |_lua, req, ()| Ok((req.0).0.to_string())); + methods.add_method("method", |_lua, req, ()| Ok((req.0).1.method().to_string())); + } +} + +async fn run_server(handler: Function<'static>) -> Result<()> { + let make_svc = make_service_fn(|socket: &AddrStream| { + let remote_addr = socket.remote_addr(); + let handler = handler.clone(); + async move { + Ok::<_, Error>(service_fn(move |req: Request| { + let handler = handler.clone(); + async move { + let lua_req = LuaRequest(Arc::new((remote_addr, req))); + let lua_resp: Table = handler.call_async(lua_req).await?; + let body = lua_resp + .get::<_, Option>("body")? + .unwrap_or_default(); + + let mut resp = Response::builder() + .status(lua_resp.get::<_, Option>("status")?.unwrap_or(200)); + + if let Some(headers) = lua_resp.get::<_, Option>("headers")? { + for pair in headers.pairs::() { + let (h, v) = pair?; + resp = resp.header(&h, v); + } + } + + Ok::<_, Error>(resp.body(Body::from(body)).unwrap()) + } + })) + } + }); + + let addr = ([127, 0, 0, 1], 3000).into(); + let server = Server::bind(&addr).executor(LocalExec).serve(make_svc); + + println!("Listening on http://{}", addr); + + tokio::task::LocalSet::new() + .run_until(server) + .await + .map_err(Error::external) +} + +#[tokio::main] +async fn main() -> Result<()> { + let lua = Lua::new().into_static(); + + let handler: Function = lua + .load( + r#" + function(req) + return { + status = 200, + headers = { + ["X-Req-Method"] = req:method(), + ["X-Remote-Addr"] = req:remote_addr(), + }, + body = "Hello, World!" + } + end + "#, + ) + .eval()?; + + run_server(handler).await?; + + // Consume the static reference and drop it. + // This is safe as long as we don't hold any other references to Lua + // or alive resources. + unsafe { Lua::from_static(lua) }; + Ok(()) +} + +#[derive(Clone, Copy, Debug)] +struct LocalExec; + +impl hyper::rt::Executor for LocalExec +where + F: std::future::Future + 'static, // not requiring `Send` +{ + fn execute(&self, fut: F) { + tokio::task::spawn_local(fut); + } +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/examples/async_tcp_server.rs b/third_party/cargo/vendor/mlua-0.5.3/examples/async_tcp_server.rs new file mode 100644 index 0000000..5153cfe --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/examples/async_tcp_server.rs @@ -0,0 +1,128 @@ +use std::sync::Arc; + +use bstr::BString; +use tokio::io::{AsyncReadExt, AsyncWriteExt}; +use tokio::net::{TcpListener, TcpStream}; +use tokio::sync::Mutex; +use tokio::task; + +use mlua::{Function, Lua, Result, UserData, UserDataMethods}; + +#[derive(Clone)] +struct LuaTcp; + +#[derive(Clone)] +struct LuaTcpListener(Arc>); + +#[derive(Clone)] +struct LuaTcpStream(Arc>); + +impl UserData for LuaTcp { + fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_async_function("bind", |_, addr: String| async move { + let listener = TcpListener::bind(addr).await?; + Ok(LuaTcpListener(Arc::new(Mutex::new(listener)))) + }); + } +} + +impl UserData for LuaTcpListener { + fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_async_method("accept", |_, listener, ()| async move { + let (stream, _) = listener.0.lock().await.accept().await?; + Ok(LuaTcpStream(Arc::new(Mutex::new(stream)))) + }); + } +} + +impl UserData for LuaTcpStream { + fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_async_method("peer_addr", |_, stream, ()| async move { + Ok(stream.0.lock().await.peer_addr()?.to_string()) + }); + + methods.add_async_method("read", |_, stream, size: usize| async move { + let mut buf = vec![0; size]; + let n = stream.0.lock().await.read(&mut buf).await?; + buf.truncate(n); + Ok(BString::from(buf)) + }); + + methods.add_async_method("write", |_, stream, data: BString| async move { + let n = stream.0.lock().await.write(&data).await?; + Ok(n) + }); + + methods.add_async_method("close", |_, stream, ()| async move { + stream.0.lock().await.shutdown().await?; + Ok(()) + }); + } +} + +async fn run_server(lua: &'static Lua) -> Result<()> { + let spawn = lua.create_function(move |_, func: Function| { + task::spawn_local(async move { func.call_async::<_, ()>(()).await }); + Ok(()) + })?; + + let globals = lua.globals(); + globals.set("tcp", LuaTcp)?; + globals.set("spawn", spawn)?; + + let server = lua + .load( + r#" + local addr = ... + local listener = tcp.bind(addr) + print("listening on "..addr) + + local accept_new = true + while true do + local stream = listener:accept() + local peer_addr = stream:peer_addr() + print("connected from "..peer_addr) + + if not accept_new then + return + end + + spawn(function() + while true do + local data = stream:read(100) + data = data:match("^%s*(.-)%s*$") -- trim + print("["..peer_addr.."] "..data) + if data == "bye" then + stream:write("bye bye\n") + stream:close() + return + end + if data == "exit" then + stream:close() + accept_new = false + return + end + stream:write("echo: "..data.."\n") + end + end) + end + "#, + ) + .into_function()?; + + task::LocalSet::new() + .run_until(server.call_async::<_, ()>("0.0.0.0:1234")) + .await +} + +#[tokio::main] +async fn main() { + let lua = Lua::new().into_static(); + + run_server(lua).await.unwrap(); + + // Consume the static reference and drop it. + // This is safe as long as we don't hold any other references to Lua + // or alive resources. + unsafe { Lua::from_static(lua) }; +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/examples/guided_tour.rs b/third_party/cargo/vendor/mlua-0.5.3/examples/guided_tour.rs new file mode 100644 index 0000000..540d4b2 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/examples/guided_tour.rs @@ -0,0 +1,201 @@ +use std::f32; +use std::iter::FromIterator; + +use mlua::{Function, Lua, MetaMethod, Result, UserData, UserDataMethods, Variadic}; + +fn main() -> Result<()> { + // You can create a new Lua state with `Lua::new()`. This loads the default Lua std library + // *without* the debug library. + let lua = Lua::new(); + + // You can get and set global variables. Notice that the globals table here is a permanent + // reference to _G, and it is mutated behind the scenes as Lua code is loaded. This API is + // based heavily around sharing and internal mutation (just like Lua itself). + + let globals = lua.globals(); + + globals.set("string_var", "hello")?; + globals.set("int_var", 42)?; + + assert_eq!(globals.get::<_, String>("string_var")?, "hello"); + assert_eq!(globals.get::<_, i64>("int_var")?, 42); + + // You can load and evaluate Lua code. The returned type of `Lua::load` is a builder + // that allows you to change settings before running Lua code. Here, we are using it to set + // the name of the laoded chunk to "example code", which will be used when Lua error + // messages are printed. + + lua.load( + r#" + global = 'foo'..'bar' + "#, + ) + .set_name("example code")? + .exec()?; + assert_eq!(globals.get::<_, String>("global")?, "foobar"); + + assert_eq!(lua.load("1 + 1").eval::()?, 2); + assert_eq!(lua.load("false == false").eval::()?, true); + assert_eq!(lua.load("return 1 + 2").eval::()?, 3); + + // You can create and manage Lua tables + + let array_table = lua.create_table()?; + array_table.set(1, "one")?; + array_table.set(2, "two")?; + array_table.set(3, "three")?; + assert_eq!(array_table.len()?, 3); + + let map_table = lua.create_table()?; + map_table.set("one", 1)?; + map_table.set("two", 2)?; + map_table.set("three", 3)?; + let v: i64 = map_table.get("two")?; + assert_eq!(v, 2); + + // You can pass values like `Table` back into Lua + + globals.set("array_table", array_table)?; + globals.set("map_table", map_table)?; + + lua.load( + r#" + for k, v in pairs(array_table) do + print(k, v) + end + + for k, v in pairs(map_table) do + print(k, v) + end + "#, + ) + .exec()?; + + // You can load Lua functions + + let print: Function = globals.get("print")?; + print.call::<_, ()>("hello from rust")?; + + // This API generally handles variadics using tuples. This is one way to call a function with + // multiple parameters: + + print.call::<_, ()>(("hello", "again", "from", "rust"))?; + + // But, you can also pass variadic arguments with the `Variadic` type. + + print.call::<_, ()>(Variadic::from_iter( + ["hello", "yet", "again", "from", "rust"].iter().cloned(), + ))?; + + // You can bind rust functions to Lua as well. Callbacks receive the Lua state inself as their + // first parameter, and the arguments given to the function as the second parameter. The type + // of the arguments can be anything that is convertible from the parameters given by Lua, in + // this case, the function expects two string sequences. + + let check_equal = lua.create_function(|_, (list1, list2): (Vec, Vec)| { + // This function just checks whether two string lists are equal, and in an inefficient way. + // Lua callbacks return `mlua::Result`, an Ok value is a normal return, and an Err return + // turns into a Lua 'error'. Again, any type that is convertible to Lua may be returned. + Ok(list1 == list2) + })?; + globals.set("check_equal", check_equal)?; + + // You can also accept runtime variadic arguments to rust callbacks. + + let join = lua.create_function(|_, strings: Variadic| { + // (This is quadratic!, it's just an example!) + Ok(strings.iter().fold("".to_owned(), |a, b| a + b)) + })?; + globals.set("join", join)?; + + assert_eq!( + lua.load(r#"check_equal({"a", "b", "c"}, {"a", "b", "c"})"#) + .eval::()?, + true + ); + assert_eq!( + lua.load(r#"check_equal({"a", "b", "c"}, {"d", "e", "f"})"#) + .eval::()?, + false + ); + assert_eq!(lua.load(r#"join("a", "b", "c")"#).eval::()?, "abc"); + + // Callbacks receive a Lua state as their first parameter so that they can use it to + // create new Lua values, if necessary. + + let create_table = lua.create_function(|lua, ()| { + let t = lua.create_table()?; + t.set(1, 1)?; + t.set(2, 2)?; + Ok(t) + })?; + globals.set("create_table", create_table)?; + + assert_eq!(lua.load(r#"create_table()[2]"#).eval::()?, 2); + + // You can create userdata with methods and metamethods defined on them. + // Here's a worked example that shows many of the features of this API + // together + + #[derive(Copy, Clone)] + struct Vec2(f32, f32); + + impl UserData for Vec2 { + fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_method("magnitude", |_, vec, ()| { + let mag_squared = vec.0 * vec.0 + vec.1 * vec.1; + Ok(mag_squared.sqrt()) + }); + + methods.add_meta_function(MetaMethod::Add, |_, (vec1, vec2): (Vec2, Vec2)| { + Ok(Vec2(vec1.0 + vec2.0, vec1.1 + vec2.1)) + }); + } + } + + let vec2_constructor = lua.create_function(|_, (x, y): (f32, f32)| Ok(Vec2(x, y)))?; + globals.set("vec2", vec2_constructor)?; + + assert!( + (lua.load("(vec2(1, 2) + vec2(2, 2)):magnitude()") + .eval::()? + - 5.0) + .abs() + < f32::EPSILON + ); + + // Normally, Rust types passed to `Lua` must be `'static`, because there is no way to be + // sure of their lifetime inside the Lua state. There is, however, a limited way to lift this + // requirement. You can call `Lua::scope` to create userdata and callbacks types that only live + // for as long as the call to scope, but do not have to be `'static` (and `Send`). + + { + let mut rust_val = 0; + + lua.scope(|scope| { + // We create a 'sketchy' Lua callback that holds a mutable reference to the variable + // `rust_val`. Outside of a `Lua::scope` call, this would not be allowed + // because it could be unsafe. + + lua.globals().set( + "sketchy", + scope.create_function_mut(|_, ()| { + rust_val = 42; + Ok(()) + })?, + )?; + + lua.load("sketchy()").exec() + })?; + + assert_eq!(rust_val, 42); + } + + // We were able to run our 'sketchy' function inside the scope just fine. However, if we + // try to run our 'sketchy' function outside of the scope, the function we created will have + // been invalidated and we will generate an error. If our function wasn't invalidated, we + // might be able to improperly access the freed `rust_val` which would be unsafe. + assert!(lua.load("sketchy()").exec().is_err()); + + Ok(()) +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/examples/repl.rs b/third_party/cargo/vendor/mlua-0.5.3/examples/repl.rs new file mode 100644 index 0000000..a5fe47a --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/examples/repl.rs @@ -0,0 +1,48 @@ +//! This example shows a simple read-evaluate-print-loop (REPL). + +use mlua::{Error, Lua, MultiValue}; +use rustyline::Editor; + +fn main() { + let lua = Lua::new(); + let mut editor = Editor::<()>::new(); + + loop { + let mut prompt = "> "; + let mut line = String::new(); + + loop { + match editor.readline(prompt) { + Ok(input) => line.push_str(&input), + Err(_) => return, + } + + match lua.load(&line).eval::() { + Ok(values) => { + editor.add_history_entry(line); + println!( + "{}", + values + .iter() + .map(|value| format!("{:?}", value)) + .collect::>() + .join("\t") + ); + break; + } + Err(Error::SyntaxError { + incomplete_input: true, + .. + }) => { + // continue reading input and append it to `line` + line.push_str("\n"); // separate input lines + prompt = ">> "; + } + Err(e) => { + eprintln!("error: {}", e); + break; + } + } + } + } +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/examples/serialize.rs b/third_party/cargo/vendor/mlua-0.5.3/examples/serialize.rs new file mode 100644 index 0000000..d1b9e42 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/examples/serialize.rs @@ -0,0 +1,66 @@ +use mlua::{Error, Lua, LuaSerdeExt, Result, UserData, Value}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize)] +enum Transmission { + Manual, + Automatic, +} + +#[derive(Serialize, Deserialize)] +struct Engine { + v: u32, + kw: u32, +} + +#[derive(Serialize, Deserialize)] +struct Car { + active: bool, + model: String, + transmission: Transmission, + engine: Engine, +} + +impl UserData for Car {} + +fn main() -> Result<()> { + let lua = Lua::new(); + let globals = lua.globals(); + + // Create Car struct from a Lua table + let car: Car = lua.from_value(lua.load(r#" + {active = true, model = "Volkswagen Golf", transmission = "Automatic", engine = {v = 1499, kw = 90}} + "#).eval()?)?; + + // Set it as (serializable) userdata + globals.set("null", lua.null()?)?; + globals.set("array_mt", lua.array_metatable()?)?; + globals.set("car", lua.create_ser_userdata(car)?)?; + + // Create a Lua table with multiple data types + let val: Value = lua + .load(r#"{driver = "Boris", car = car, price = null, points = setmetatable({}, array_mt)}"#) + .eval()?; + + // Serialize the table above to JSON + let json_str = serde_json::to_string(&val).map_err(Error::external)?; + println!("{}", json_str); + + // Create Lua Value from JSON (or any serializable type) + let json = serde_json::json!({ + "key": "value", + "null": null, + "array": [], + }); + globals.set("json_value", lua.to_value(&json)?)?; + lua.load( + r#" + assert(json_value["key"] == "value") + assert(json_value["null"] == null) + assert(#(json_value["array"]) == 0) + "#, + ) + .exec()?; + + Ok(()) +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/src/conversion.rs b/third_party/cargo/vendor/mlua-0.5.3/src/conversion.rs new file mode 100644 index 0000000..bec7758 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/src/conversion.rs @@ -0,0 +1,569 @@ +use std::borrow::Cow; +use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; +use std::ffi::{CStr, CString}; +use std::hash::{BuildHasher, Hash}; +use std::string::String as StdString; + +use bstr::{BStr, BString}; +use num_traits::cast; + +use crate::error::{Error, Result}; +use crate::function::Function; +use crate::lua::Lua; +use crate::string::String; +use crate::table::Table; +use crate::thread::Thread; +use crate::types::{LightUserData, MaybeSend}; +use crate::userdata::{AnyUserData, UserData}; +use crate::value::{FromLua, Nil, ToLua, Value}; + +impl<'lua> ToLua<'lua> for Value<'lua> { + fn to_lua(self, _: &'lua Lua) -> Result> { + Ok(self) + } +} + +impl<'lua> FromLua<'lua> for Value<'lua> { + fn from_lua(lua_value: Value<'lua>, _: &'lua Lua) -> Result { + Ok(lua_value) + } +} + +impl<'lua> ToLua<'lua> for String<'lua> { + fn to_lua(self, _: &'lua Lua) -> Result> { + Ok(Value::String(self)) + } +} + +impl<'lua> FromLua<'lua> for String<'lua> { + fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result> { + let ty = value.type_name(); + lua.coerce_string(value)? + .ok_or_else(|| Error::FromLuaConversionError { + from: ty, + to: "String", + message: Some("expected string or number".to_string()), + }) + } +} + +impl<'lua> ToLua<'lua> for Table<'lua> { + fn to_lua(self, _: &'lua Lua) -> Result> { + Ok(Value::Table(self)) + } +} + +impl<'lua> FromLua<'lua> for Table<'lua> { + fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result> { + match value { + Value::Table(table) => Ok(table), + _ => Err(Error::FromLuaConversionError { + from: value.type_name(), + to: "table", + message: None, + }), + } + } +} + +impl<'lua> ToLua<'lua> for Function<'lua> { + fn to_lua(self, _: &'lua Lua) -> Result> { + Ok(Value::Function(self)) + } +} + +impl<'lua> FromLua<'lua> for Function<'lua> { + fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result> { + match value { + Value::Function(table) => Ok(table), + _ => Err(Error::FromLuaConversionError { + from: value.type_name(), + to: "function", + message: None, + }), + } + } +} + +impl<'lua> ToLua<'lua> for Thread<'lua> { + fn to_lua(self, _: &'lua Lua) -> Result> { + Ok(Value::Thread(self)) + } +} + +impl<'lua> FromLua<'lua> for Thread<'lua> { + fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result> { + match value { + Value::Thread(t) => Ok(t), + _ => Err(Error::FromLuaConversionError { + from: value.type_name(), + to: "thread", + message: None, + }), + } + } +} + +impl<'lua> ToLua<'lua> for AnyUserData<'lua> { + fn to_lua(self, _: &'lua Lua) -> Result> { + Ok(Value::UserData(self)) + } +} + +impl<'lua> FromLua<'lua> for AnyUserData<'lua> { + fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result> { + match value { + Value::UserData(ud) => Ok(ud), + _ => Err(Error::FromLuaConversionError { + from: value.type_name(), + to: "userdata", + message: None, + }), + } + } +} + +impl<'lua, T: 'static + MaybeSend + UserData> ToLua<'lua> for T { + fn to_lua(self, lua: &'lua Lua) -> Result> { + Ok(Value::UserData(lua.create_userdata(self)?)) + } +} + +impl<'lua, T: 'static + UserData + Clone> FromLua<'lua> for T { + fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result { + match value { + Value::UserData(ud) => Ok(ud.borrow::()?.clone()), + _ => Err(Error::FromLuaConversionError { + from: value.type_name(), + to: "userdata", + message: None, + }), + } + } +} + +impl<'lua> ToLua<'lua> for Error { + fn to_lua(self, _: &'lua Lua) -> Result> { + Ok(Value::Error(self)) + } +} + +impl<'lua> FromLua<'lua> for Error { + fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result { + match value { + Value::Error(err) => Ok(err), + val => Ok(Error::RuntimeError( + lua.coerce_string(val)? + .and_then(|s| Some(s.to_str().ok()?.to_owned())) + .unwrap_or_else(|| "".to_owned()), + )), + } + } +} + +impl<'lua> ToLua<'lua> for bool { + fn to_lua(self, _: &'lua Lua) -> Result> { + Ok(Value::Boolean(self)) + } +} + +impl<'lua> FromLua<'lua> for bool { + fn from_lua(v: Value<'lua>, _: &'lua Lua) -> Result { + match v { + Value::Nil => Ok(false), + Value::Boolean(b) => Ok(b), + _ => Ok(true), + } + } +} + +impl<'lua> ToLua<'lua> for LightUserData { + fn to_lua(self, _: &'lua Lua) -> Result> { + Ok(Value::LightUserData(self)) + } +} + +impl<'lua> FromLua<'lua> for LightUserData { + fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result { + match value { + Value::LightUserData(ud) => Ok(ud), + _ => Err(Error::FromLuaConversionError { + from: value.type_name(), + to: "light userdata", + message: None, + }), + } + } +} + +impl<'lua> ToLua<'lua> for StdString { + fn to_lua(self, lua: &'lua Lua) -> Result> { + Ok(Value::String(lua.create_string(&self)?)) + } +} + +impl<'lua> FromLua<'lua> for StdString { + fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result { + let ty = value.type_name(); + Ok(lua + .coerce_string(value)? + .ok_or_else(|| Error::FromLuaConversionError { + from: ty, + to: "String", + message: Some("expected string or number".to_string()), + })? + .to_str()? + .to_owned()) + } +} + +impl<'lua> ToLua<'lua> for &str { + fn to_lua(self, lua: &'lua Lua) -> Result> { + Ok(Value::String(lua.create_string(self)?)) + } +} + +impl<'lua> ToLua<'lua> for Cow<'_, str> { + fn to_lua(self, lua: &'lua Lua) -> Result> { + Ok(Value::String(lua.create_string(self.as_bytes())?)) + } +} + +impl<'lua> ToLua<'lua> for CString { + fn to_lua(self, lua: &'lua Lua) -> Result> { + Ok(Value::String(lua.create_string(self.as_bytes())?)) + } +} + +impl<'lua> FromLua<'lua> for CString { + fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result { + let ty = value.type_name(); + let string = lua + .coerce_string(value)? + .ok_or_else(|| Error::FromLuaConversionError { + from: ty, + to: "CString", + message: Some("expected string or number".to_string()), + })?; + + match CStr::from_bytes_with_nul(string.as_bytes_with_nul()) { + Ok(s) => Ok(s.into()), + Err(_) => Err(Error::FromLuaConversionError { + from: ty, + to: "CString", + message: Some("invalid C-style string".to_string()), + }), + } + } +} + +impl<'lua> ToLua<'lua> for &CStr { + fn to_lua(self, lua: &'lua Lua) -> Result> { + Ok(Value::String(lua.create_string(self.to_bytes())?)) + } +} + +impl<'lua> ToLua<'lua> for Cow<'_, CStr> { + fn to_lua(self, lua: &'lua Lua) -> Result> { + Ok(Value::String(lua.create_string(self.to_bytes())?)) + } +} + +impl<'lua> ToLua<'lua> for BString { + fn to_lua(self, lua: &'lua Lua) -> Result> { + Ok(Value::String(lua.create_string(&self)?)) + } +} + +impl<'lua> FromLua<'lua> for BString { + fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result { + let ty = value.type_name(); + Ok(BString::from( + lua.coerce_string(value)? + .ok_or_else(|| Error::FromLuaConversionError { + from: ty, + to: "String", + message: Some("expected string or number".to_string()), + })? + .as_bytes() + .to_vec(), + )) + } +} + +impl<'lua> ToLua<'lua> for &BStr { + fn to_lua(self, lua: &'lua Lua) -> Result> { + Ok(Value::String(lua.create_string(&self)?)) + } +} + +macro_rules! lua_convert_int { + ($x:ty) => { + impl<'lua> ToLua<'lua> for $x { + fn to_lua(self, _: &'lua Lua) -> Result> { + if let Some(i) = cast(self) { + Ok(Value::Integer(i)) + } else { + cast(self) + .ok_or_else(|| Error::ToLuaConversionError { + from: stringify!($x), + to: "number", + message: Some("out of range".to_owned()), + }) + .map(Value::Number) + } + } + } + + impl<'lua> FromLua<'lua> for $x { + fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result { + let ty = value.type_name(); + (if let Some(i) = lua.coerce_integer(value.clone())? { + cast(i) + } else { + cast(lua.coerce_number(value)?.ok_or_else(|| { + Error::FromLuaConversionError { + from: ty, + to: stringify!($x), + message: Some( + "expected number or string coercible to number".to_string(), + ), + } + })?) + }) + .ok_or_else(|| Error::FromLuaConversionError { + from: ty, + to: stringify!($x), + message: Some("out of range".to_owned()), + }) + } + } + }; +} + +lua_convert_int!(i8); +lua_convert_int!(u8); +lua_convert_int!(i16); +lua_convert_int!(u16); +lua_convert_int!(i32); +lua_convert_int!(u32); +lua_convert_int!(i64); +lua_convert_int!(u64); +//lua_convert_int!(i128); +//lua_convert_int!(u128); +lua_convert_int!(isize); +lua_convert_int!(usize); + +macro_rules! lua_convert_float { + ($x:ty) => { + impl<'lua> ToLua<'lua> for $x { + fn to_lua(self, _: &'lua Lua) -> Result> { + cast(self) + .ok_or_else(|| Error::ToLuaConversionError { + from: stringify!($x), + to: "number", + message: Some("out of range".to_string()), + }) + .map(Value::Number) + } + } + + impl<'lua> FromLua<'lua> for $x { + fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result { + let ty = value.type_name(); + lua.coerce_number(value)? + .ok_or_else(|| Error::FromLuaConversionError { + from: ty, + to: stringify!($x), + message: Some("expected number or string coercible to number".to_string()), + }) + .and_then(|n| { + cast(n).ok_or_else(|| Error::FromLuaConversionError { + from: ty, + to: stringify!($x), + message: Some("number out of range".to_string()), + }) + }) + } + } + }; +} + +lua_convert_float!(f32); +lua_convert_float!(f64); + +impl<'lua, T> ToLua<'lua> for &[T] +where + T: Clone + ToLua<'lua>, +{ + fn to_lua(self, lua: &'lua Lua) -> Result> { + Ok(Value::Table( + lua.create_sequence_from(self.iter().cloned())?, + )) + } +} + +macro_rules! lua_convert_array { + ($($N:literal)+) => { + $( + impl<'lua, T> ToLua<'lua> for [T; $N] + where + T: Clone + ToLua<'lua>, + { + fn to_lua(self, lua: &'lua Lua) -> Result> { + (&self).to_lua(lua) + } + } + + impl<'lua, T> ToLua<'lua> for &[T; $N] + where + T: Clone + ToLua<'lua>, + { + fn to_lua(self, lua: &'lua Lua) -> Result> { + Ok(Value::Table( + lua.create_sequence_from(self.iter().cloned())?, + )) + } + } + )+ + } +} + +lua_convert_array! { + 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 +} + +impl<'lua, T: ToLua<'lua>> ToLua<'lua> for Vec { + fn to_lua(self, lua: &'lua Lua) -> Result> { + Ok(Value::Table(lua.create_sequence_from(self)?)) + } +} + +impl<'lua, T: FromLua<'lua>> FromLua<'lua> for Vec { + fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result { + if let Value::Table(table) = value { + table.sequence_values().collect() + } else { + Err(Error::FromLuaConversionError { + from: value.type_name(), + to: "Vec", + message: Some("expected table".to_string()), + }) + } + } +} + +impl<'lua, K: Eq + Hash + ToLua<'lua>, V: ToLua<'lua>, S: BuildHasher> ToLua<'lua> + for HashMap +{ + fn to_lua(self, lua: &'lua Lua) -> Result> { + Ok(Value::Table(lua.create_table_from(self)?)) + } +} + +impl<'lua, K: Eq + Hash + FromLua<'lua>, V: FromLua<'lua>, S: BuildHasher + Default> FromLua<'lua> + for HashMap +{ + fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result { + if let Value::Table(table) = value { + table.pairs().collect() + } else { + Err(Error::FromLuaConversionError { + from: value.type_name(), + to: "HashMap", + message: Some("expected table".to_string()), + }) + } + } +} + +impl<'lua, K: Ord + ToLua<'lua>, V: ToLua<'lua>> ToLua<'lua> for BTreeMap { + fn to_lua(self, lua: &'lua Lua) -> Result> { + Ok(Value::Table(lua.create_table_from(self)?)) + } +} + +impl<'lua, K: Ord + FromLua<'lua>, V: FromLua<'lua>> FromLua<'lua> for BTreeMap { + fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result { + if let Value::Table(table) = value { + table.pairs().collect() + } else { + Err(Error::FromLuaConversionError { + from: value.type_name(), + to: "BTreeMap", + message: Some("expected table".to_string()), + }) + } + } +} + +impl<'lua, T: Eq + Hash + ToLua<'lua>, S: BuildHasher> ToLua<'lua> for HashSet { + fn to_lua(self, lua: &'lua Lua) -> Result> { + Ok(Value::Table(lua.create_table_from( + self.into_iter().map(|val| (val, true)), + )?)) + } +} + +impl<'lua, T: Eq + Hash + FromLua<'lua>, S: BuildHasher + Default> FromLua<'lua> for HashSet { + fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result { + if let Value::Table(table) = value { + table + .pairs::>() + .map(|res| res.map(|(k, _)| k)) + .collect() + } else { + Err(Error::FromLuaConversionError { + from: value.type_name(), + to: "HashSet", + message: Some("expected table".to_string()), + }) + } + } +} + +impl<'lua, T: Ord + ToLua<'lua>> ToLua<'lua> for BTreeSet { + fn to_lua(self, lua: &'lua Lua) -> Result> { + Ok(Value::Table(lua.create_table_from( + self.into_iter().map(|val| (val, true)), + )?)) + } +} + +impl<'lua, T: Ord + FromLua<'lua>> FromLua<'lua> for BTreeSet { + fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result { + if let Value::Table(table) = value { + table + .pairs::>() + .map(|res| res.map(|(k, _)| k)) + .collect() + } else { + Err(Error::FromLuaConversionError { + from: value.type_name(), + to: "BTreeSet", + message: Some("expected table".to_string()), + }) + } + } +} + +impl<'lua, T: ToLua<'lua>> ToLua<'lua> for Option { + fn to_lua(self, lua: &'lua Lua) -> Result> { + match self { + Some(val) => val.to_lua(lua), + None => Ok(Nil), + } + } +} + +impl<'lua, T: FromLua<'lua>> FromLua<'lua> for Option { + fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result { + match value { + Nil => Ok(None), + value => Ok(Some(T::from_lua(value, lua)?)), + } + } +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/src/error.rs b/third_party/cargo/vendor/mlua-0.5.3/src/error.rs new file mode 100644 index 0000000..ad58307 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/src/error.rs @@ -0,0 +1,329 @@ +use std::error::Error as StdError; +use std::fmt; +use std::io::Error as IoError; +use std::net::AddrParseError; +use std::result::Result as StdResult; +use std::str::Utf8Error; +use std::string::String as StdString; +use std::sync::Arc; + +/// Error type returned by `mlua` methods. +#[derive(Debug, Clone)] +pub enum Error { + /// Syntax error while parsing Lua source code. + SyntaxError { + /// The error message as returned by Lua. + message: StdString, + /// `true` if the error can likely be fixed by appending more input to the source code. + /// + /// This is useful for implementing REPLs as they can query the user for more input if this + /// is set. + incomplete_input: bool, + }, + /// Lua runtime error, aka `LUA_ERRRUN`. + /// + /// The Lua VM returns this error when a builtin operation is performed on incompatible types. + /// Among other things, this includes invoking operators on wrong types (such as calling or + /// indexing a `nil` value). + RuntimeError(StdString), + /// Lua memory error, aka `LUA_ERRMEM` + /// + /// The Lua VM returns this error when the allocator does not return the requested memory, aka + /// it is an out-of-memory error. + MemoryError(StdString), + /// Lua garbage collector error, aka `LUA_ERRGCMM`. + /// + /// The Lua VM returns this error when there is an error running a `__gc` metamethod. + #[cfg(any(feature = "lua53", feature = "lua52"))] + GarbageCollectorError(StdString), + /// Potentially unsafe action in safe mode. + SafetyError(StdString), + /// Setting memory limit is not available. + /// + /// This error can only happen when Lua state was not created by us and does not have the + /// custom allocator attached. + MemoryLimitNotAvailable, + /// Main thread is not available. + /// + /// This error can only happen in Lua5.1/LuaJIT module mode, when module loaded within a coroutine. + /// These Lua versions does not have `LUA_RIDX_MAINTHREAD` registry key. + MainThreadNotAvailable, + /// A mutable callback has triggered Lua code that has called the same mutable callback again. + /// + /// This is an error because a mutable callback can only be borrowed mutably once. + RecursiveMutCallback, + /// Either a callback or a userdata method has been called, but the callback or userdata has + /// been destructed. + /// + /// This can happen either due to to being destructed in a previous __gc, or due to being + /// destructed from exiting a `Lua::scope` call. + CallbackDestructed, + /// Not enough stack space to place arguments to Lua functions or return values from callbacks. + /// + /// Due to the way `mlua` works, it should not be directly possible to run out of stack space + /// during normal use. The only way that this error can be triggered is if a `Function` is + /// called with a huge number of arguments, or a rust callback returns a huge number of return + /// values. + StackError, + /// Too many arguments to `Function::bind` + BindError, + /// A Rust value could not be converted to a Lua value. + ToLuaConversionError { + /// Name of the Rust type that could not be converted. + from: &'static str, + /// Name of the Lua type that could not be created. + to: &'static str, + /// A message indicating why the conversion failed in more detail. + message: Option, + }, + /// A Lua value could not be converted to the expected Rust type. + FromLuaConversionError { + /// Name of the Lua type that could not be converted. + from: &'static str, + /// Name of the Rust type that could not be created. + to: &'static str, + /// A string containing more detailed error information. + message: Option, + }, + /// [`Thread::resume`] was called on an inactive coroutine. + /// + /// A coroutine is inactive if its main function has returned or if an error has occured inside + /// the coroutine. + /// + /// [`Thread::status`] can be used to check if the coroutine can be resumed without causing this + /// error. + /// + /// [`Thread::resume`]: struct.Thread.html#method.resume + /// [`Thread::status`]: struct.Thread.html#method.status + CoroutineInactive, + /// An [`AnyUserData`] is not the expected type in a borrow. + /// + /// This error can only happen when manually using [`AnyUserData`], or when implementing + /// metamethods for binary operators. Refer to the documentation of [`UserDataMethods`] for + /// details. + /// + /// [`AnyUserData`]: struct.AnyUserData.html + /// [`UserDataMethods`]: trait.UserDataMethods.html + UserDataTypeMismatch, + /// An [`AnyUserData`] borrow failed because it has been destructed. + /// + /// This error can happen either due to to being destructed in a previous __gc, or due to being + /// destructed from exiting a `Lua::scope` call. + /// + /// [`AnyUserData`]: struct.AnyUserData.html + UserDataDestructed, + /// An [`AnyUserData`] immutable borrow failed because it is already borrowed mutably. + /// + /// This error can occur when a method on a [`UserData`] type calls back into Lua, which then + /// tries to call a method on the same [`UserData`] type. Consider restructuring your API to + /// prevent these errors. + /// + /// [`AnyUserData`]: struct.AnyUserData.html + /// [`UserData`]: trait.UserData.html + UserDataBorrowError, + /// An [`AnyUserData`] mutable borrow failed because it is already borrowed. + /// + /// This error can occur when a method on a [`UserData`] type calls back into Lua, which then + /// tries to call a method on the same [`UserData`] type. Consider restructuring your API to + /// prevent these errors. + /// + /// [`AnyUserData`]: struct.AnyUserData.html + /// [`UserData`]: trait.UserData.html + UserDataBorrowMutError, + /// A `RegistryKey` produced from a different Lua state was used. + MismatchedRegistryKey, + /// A Rust callback returned `Err`, raising the contained `Error` as a Lua error. + CallbackError { + /// Lua call stack backtrace. + traceback: StdString, + /// Original error returned by the Rust code. + cause: Arc, + }, + /// Serialization error. + #[cfg(feature = "serialize")] + #[cfg_attr(docsrs, doc(cfg(feature = "serialize")))] + SerializeError(StdString), + /// Deserialization error. + #[cfg(feature = "serialize")] + #[cfg_attr(docsrs, doc(cfg(feature = "serialize")))] + DeserializeError(StdString), + /// A custom error. + /// + /// This can be used for returning user-defined errors from callbacks. + /// + /// Returning `Err(ExternalError(...))` from a Rust callback will raise the error as a Lua + /// error. The Rust code that originally invoked the Lua code then receives a `CallbackError`, + /// from which the original error (and a stack traceback) can be recovered. + #[cfg(feature = "send")] + ExternalError(Arc), + #[cfg(not(feature = "send"))] + ExternalError(Arc), +} + +/// A specialized `Result` type used by `mlua`'s API. +pub type Result = StdResult; + +impl fmt::Display for Error { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match *self { + Error::SyntaxError { ref message, .. } => write!(fmt, "syntax error: {}", message), + Error::RuntimeError(ref msg) => write!(fmt, "runtime error: {}", msg), + Error::MemoryError(ref msg) => { + write!(fmt, "memory error: {}", msg) + } + #[cfg(any(feature = "lua53", feature = "lua52"))] + Error::GarbageCollectorError(ref msg) => { + write!(fmt, "garbage collector error: {}", msg) + } + Error::SafetyError(ref msg) => { + write!(fmt, "safety error: {}", msg) + }, + Error::MemoryLimitNotAvailable => { + write!(fmt, "setting memory limit is not available") + } + Error::MainThreadNotAvailable => { + write!(fmt, "main thread is not available in Lua 5.1") + } + Error::RecursiveMutCallback => write!(fmt, "mutable callback called recursively"), + Error::CallbackDestructed => write!( + fmt, + "a destructed callback or destructed userdata method was called" + ), + Error::StackError => write!( + fmt, + "out of Lua stack, too many arguments to a Lua function or too many return values from a callback" + ), + Error::BindError => write!( + fmt, + "too many arguments to Function::bind" + ), + Error::ToLuaConversionError { + from, + to, + ref message, + } => { + write!(fmt, "error converting {} to Lua {}", from, to)?; + match *message { + None => Ok(()), + Some(ref message) => write!(fmt, " ({})", message), + } + } + Error::FromLuaConversionError { + from, + to, + ref message, + } => { + write!(fmt, "error converting Lua {} to {}", from, to)?; + match *message { + None => Ok(()), + Some(ref message) => write!(fmt, " ({})", message), + } + } + Error::CoroutineInactive => write!(fmt, "cannot resume inactive coroutine"), + Error::UserDataTypeMismatch => write!(fmt, "userdata is not expected type"), + Error::UserDataDestructed => write!(fmt, "userdata has been destructed"), + Error::UserDataBorrowError => write!(fmt, "userdata already mutably borrowed"), + Error::UserDataBorrowMutError => write!(fmt, "userdata already borrowed"), + Error::MismatchedRegistryKey => { + write!(fmt, "RegistryKey used from different Lua state") + } + Error::CallbackError { ref traceback, .. } => { + write!(fmt, "callback error: {}", traceback) + } + #[cfg(feature = "serialize")] + Error::SerializeError(ref err) => { + write!(fmt, "serialize error: {}", err) + }, + #[cfg(feature = "serialize")] + Error::DeserializeError(ref err) => { + write!(fmt, "deserialize error: {}", err) + }, + Error::ExternalError(ref err) => write!(fmt, "{}", err), + } + } +} + +impl StdError for Error { + fn source(&self) -> Option<&(dyn StdError + 'static)> { + match *self { + Error::CallbackError { ref cause, .. } => Some(cause.as_ref()), + Error::ExternalError(ref err) => err.source(), + _ => None, + } + } +} + +impl Error { + #[cfg(feature = "send")] + pub fn external>>(err: T) -> Error { + Error::ExternalError(err.into().into()) + } + + #[cfg(not(feature = "send"))] + pub fn external>>(err: T) -> Error { + Error::ExternalError(err.into().into()) + } +} + +pub trait ExternalError { + fn to_lua_err(self) -> Error; +} + +#[cfg(feature = "send")] +impl>> ExternalError for E { + fn to_lua_err(self) -> Error { + Error::external(self) + } +} + +#[cfg(not(feature = "send"))] +impl>> ExternalError for E { + fn to_lua_err(self) -> Error { + Error::external(self) + } +} + +pub trait ExternalResult { + fn to_lua_err(self) -> Result; +} + +impl ExternalResult for StdResult +where + E: ExternalError, +{ + fn to_lua_err(self) -> Result { + self.map_err(|e| e.to_lua_err()) + } +} + +impl std::convert::From for Error { + fn from(err: AddrParseError) -> Self { + Error::external(err) + } +} + +impl std::convert::From for Error { + fn from(err: IoError) -> Self { + Error::external(err) + } +} + +impl std::convert::From for Error { + fn from(err: Utf8Error) -> Self { + Error::external(err) + } +} + +#[cfg(feature = "serialize")] +impl serde::ser::Error for Error { + fn custom(msg: T) -> Self { + Self::SerializeError(msg.to_string()) + } +} + +#[cfg(feature = "serialize")] +impl serde::de::Error for Error { + fn custom(msg: T) -> Self { + Self::DeserializeError(msg.to_string()) + } +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/src/ffi/compat53.rs b/third_party/cargo/vendor/mlua-0.5.3/src/ffi/compat53.rs new file mode 100644 index 0000000..ecaa21d --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/src/ffi/compat53.rs @@ -0,0 +1,809 @@ +// The MIT License (MIT) +// +// Copyright (c) 2019-2021 A. Orlenko +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +// Based on github.com/keplerproject/lua-compat-5.3 + +#![allow(clippy::needless_return)] + +use std::ffi::CStr; +use std::mem; +use std::os::raw::{c_char, c_int, c_void}; +use std::ptr; + +use super::lauxlib::{ + luaL_callmeta, luaL_error, luaL_getmetafield_old, luaL_loadbuffer, luaL_newmetatable_old, +}; + +#[cfg(any(feature = "lua51", feature = "luajit"))] +use super::lauxlib::{luaL_Reg, luaL_checktype, luaL_getmetatable}; + +#[cfg(feature = "lua52")] +use super::lauxlib::{luaL_checkstack, luaL_getsubtable}; + +use super::lua::{ + self, lua_CFunction, lua_Debug, lua_Integer, lua_Number, lua_State, lua_Writer, lua_call, + lua_createtable, lua_dump_old, lua_error, lua_getfield_old, lua_getstack, lua_gettable_old, + lua_gettop, lua_insert, lua_isstring, lua_istable, lua_newuserdata, lua_pop, lua_pushboolean, + lua_pushcfunction, lua_pushfstring, lua_pushinteger, lua_pushliteral, lua_pushlstring_old, + lua_pushnil, lua_pushnumber, lua_pushthread, lua_pushvalue, lua_rawget_old, lua_rawgeti_old, + lua_rawset, lua_replace, lua_setfield, lua_setglobal, lua_setmetatable, lua_settable, + lua_toboolean, lua_tointeger, lua_tolstring, lua_tonumber, lua_topointer, lua_tostring, + lua_touserdata, lua_type, lua_typename, +}; + +#[cfg(any(feature = "lua51", feature = "luajit"))] +use super::lua::{ + lua_checkstack, lua_concat, lua_equal, lua_getfenv, lua_getinfo, lua_getmetatable, + lua_isnumber, lua_lessthan, lua_newtable, lua_next, lua_objlen, lua_pushcclosure, + lua_pushlightuserdata, lua_pushstring_old, lua_rawequal, lua_remove, lua_resume_old, + lua_setfenv, lua_settop, LUA_OPADD, LUA_OPUNM, +}; + +#[cfg(feature = "lua52")] +use super::lua::{ + lua_absindex, lua_getglobal_old, lua_getuservalue_old, lua_pushstring, lua_rawgetp_old, + lua_rawsetp, lua_tonumberx, +}; + +unsafe fn compat53_reverse(L: *mut lua_State, mut a: c_int, mut b: c_int) { + while a < b { + lua_pushvalue(L, a); + lua_pushvalue(L, b); + lua_replace(L, a); + lua_replace(L, b); + a += 1; + b -= 1; + } +} + +const COMPAT53_LEVELS1: c_int = 12; // size of the first part of the stack +const COMPAT53_LEVELS2: c_int = 10; // size of the second part of the stack + +unsafe fn compat53_countlevels(L: *mut lua_State) -> c_int { + let mut ar: lua_Debug = mem::zeroed(); + let (mut li, mut le) = (1, 1); + // find an upper bound + while lua_getstack(L, le, &mut ar) != 0 { + li = le; + le *= 2; + } + // do a binary search + while li < le { + let m = (li + le) / 2; + if lua_getstack(L, m, &mut ar) != 0 { + li = m + 1 + } else { + le = m; + } + } + le - 1 +} + +unsafe fn compat53_checkmode( + L: *mut lua_State, + mode: *const c_char, + modename: *const c_char, + err: c_int, +) -> c_int { + unsafe fn strchr(s: *const c_char, c: c_char) -> *const c_char { + let mut st = s; + while *st != 0 && *st != c { + st = st.offset(1); + } + if *st == c { + st + } else { + ptr::null() + } + } + + if !mode.is_null() && strchr(mode, *modename).is_null() { + lua_pushfstring( + L, + cstr!("attempt to load a %s chunk (mode is '%s')"), + modename, + mode, + ); + return err; + } + lua::LUA_OK +} + +#[cfg(any(feature = "lua51", feature = "luajit"))] +unsafe fn compat53_findfield(L: *mut lua_State, objidx: c_int, level: c_int) -> c_int { + if level == 0 || lua_istable(L, -1) == 0 { + return 0; // not found + } + + lua_pushnil(L); // start 'next' loop + while lua_next(L, -2) != 0 { + // for each pair in table + if lua_type(L, -2) == lua::LUA_TSTRING { + // ignore non-string keys + if lua_rawequal(L, objidx, -1) != 0 { + // found object? + lua_pop(L, 1); // remove value (but keep name) + return 1; + } else if compat53_findfield(L, objidx, level - 1) != 0 { + // try recursively + lua_remove(L, -2); // remove table (but keep name) + lua_pushliteral(L, "."); + lua_insert(L, -2); // place '.' between the two names + lua_concat(L, 3); + return 1; + } + } + lua_pop(L, 1); // remove value + } + return 0; // not found +} + +#[cfg(any(feature = "lua51", feature = "luajit"))] +unsafe fn compat53_pushglobalfuncname(L: *mut lua_State, ar: *mut lua_Debug) -> c_int { + let top = lua_gettop(L); + lua_getinfo(L, cstr!("f"), ar); // push function + lua_pushvalue(L, lua::LUA_GLOBALSINDEX); + if compat53_findfield(L, top + 1, 2) != 0 { + lua_copy(L, -1, top + 1); // move name to proper place + lua_pop(L, 2); // remove pushed values + return 1; + } else { + lua_settop(L, top); // remove function and global table + return 0; + } +} + +#[cfg(any(feature = "lua51", feature = "luajit"))] +unsafe fn compat53_pushfuncname(L: *mut lua_State, ar: *mut lua_Debug) { + if *(*ar).namewhat != b'\0' as c_char { + // is there a name? + lua_pushfstring(L, cstr!("function '%s'"), (*ar).name); + } else if *(*ar).what == b'm' as c_char { + // main? + lua_pushliteral(L, "main chunk"); + } else if *(*ar).what == b'C' as c_char { + if compat53_pushglobalfuncname(L, ar) != 0 { + lua_pushfstring(L, cstr!("function '%s'"), lua_tostring(L, -1)); + lua_remove(L, -2); // remove name + } else { + lua_pushliteral(L, "?"); + } + } else { + lua_pushfstring( + L, + cstr!("function <%s:%d>"), + (*ar).short_src.as_ptr(), + (*ar).linedefined, + ); + } +} + +unsafe fn compat53_call_lua(L: *mut lua_State, code: &str, nargs: c_int, nret: c_int) { + lua_rawgetp(L, lua::LUA_REGISTRYINDEX, code.as_ptr() as *const c_void); + if lua_type(L, -1) != lua::LUA_TFUNCTION { + lua_pop(L, 1); + if luaL_loadbuffer( + L, + code.as_ptr() as *const c_char, + code.as_bytes().len(), + cstr!("=none"), + ) != 0 + { + lua_error(L); + } + lua_pushvalue(L, -1); + lua_rawsetp(L, lua::LUA_REGISTRYINDEX, code.as_ptr() as *const c_void); + } + lua_insert(L, -nargs - 1); + lua_call(L, nargs, nret); +} + +// +// lua ported functions +// + +#[cfg(any(feature = "lua51", feature = "luajit"))] +#[inline(always)] +pub fn lua_upvalueindex(i: c_int) -> c_int { + lua::LUA_GLOBALSINDEX - i +} + +#[cfg(any(feature = "lua51", feature = "luajit"))] +pub unsafe fn lua_absindex(L: *mut lua_State, mut idx: c_int) -> c_int { + if idx < 0 && idx > lua::LUA_REGISTRYINDEX { + idx += lua_gettop(L) + 1; + } + idx +} + +#[cfg(any(feature = "lua51", feature = "luajit"))] +static COMPAT53_ARITH_CODE: &str = r#" +local op,a,b=... +if op == 0 then return a+b +elseif op == 1 then return a-b +elseif op == 2 then return a*b +elseif op == 3 then return a/b +elseif op == 4 then return a%b +elseif op == 5 then return a^b +elseif op == 6 then return -a +end +"#; + +#[cfg(any(feature = "lua51", feature = "luajit"))] +pub unsafe fn lua_arith(L: *mut lua_State, op: c_int) { + if op < LUA_OPADD || op > LUA_OPUNM { + luaL_error(L, cstr!("invalid 'op' argument for lua_arith")); + } + luaL_checkstack(L, 5, cstr!("not enough stack slots")); + if op == LUA_OPUNM { + lua_pushvalue(L, -1); + } + lua_pushnumber(L, op as lua_Number); + lua_insert(L, -3); + compat53_call_lua(L, COMPAT53_ARITH_CODE, 3, 1); +} + +pub unsafe fn lua_rotate(L: *mut lua_State, mut idx: c_int, mut n: c_int) { + idx = lua_absindex(L, idx); + let n_elems = lua_gettop(L) - idx + 1; + if n < 0 { + n += n_elems; + } + if n > 0 && n < n_elems { + luaL_checkstack(L, 2, cstr!("not enough stack slots available")); + n = n_elems - n; + compat53_reverse(L, idx, idx + n - 1); + compat53_reverse(L, idx + n, idx + n_elems - 1); + compat53_reverse(L, idx, idx + n_elems - 1); + } +} + +#[cfg(any(feature = "lua51", feature = "luajit"))] +pub unsafe fn lua_copy(L: *mut lua_State, fromidx: c_int, toidx: c_int) { + let abs_to = lua_absindex(L, toidx); + luaL_checkstack(L, 1, cstr!("not enough stack slots")); + lua_pushvalue(L, fromidx); + lua_replace(L, abs_to); +} + +pub unsafe fn lua_isinteger(L: *mut lua_State, idx: c_int) -> c_int { + if lua_type(L, idx) == lua::LUA_TNUMBER { + let n = lua_tonumber(L, idx); + let i = lua_tointeger(L, idx); + if (n - i as lua_Number).abs() < lua_Number::EPSILON { + return 1; + } + } + return 0; +} + +#[cfg(any(feature = "lua51", feature = "luajit"))] +pub unsafe fn lua_tonumberx(L: *mut lua_State, i: c_int, isnum: *mut c_int) -> lua_Number { + let n = lua_tonumber(L, i); + if !isnum.is_null() { + *isnum = if n != 0.0 || lua_isnumber(L, i) != 0 { + 1 + } else { + 0 + }; + } + return n; +} + +// Implemented for Lua 5.2 as well +// See https://github.com/keplerproject/lua-compat-5.3/issues/40 +pub unsafe fn lua_tointegerx(L: *mut lua_State, i: c_int, isnum: *mut c_int) -> lua_Integer { + let mut ok = 0; + let n = lua_tonumberx(L, i, &mut ok); + let n_int = n as lua_Integer; + if ok != 0 && (n - n_int as lua_Number).abs() < lua_Number::EPSILON { + if !isnum.is_null() { + *isnum = 1; + } + return n_int; + } + if !isnum.is_null() { + *isnum = 0; + } + return 0; +} + +#[cfg(any(feature = "lua51", feature = "luajit"))] +pub unsafe fn lua_rawlen(L: *mut lua_State, idx: c_int) -> usize { + lua_objlen(L, idx) +} + +#[cfg(any(feature = "lua51", feature = "luajit"))] +pub unsafe fn lua_compare(L: *mut lua_State, mut idx1: c_int, mut idx2: c_int, op: c_int) -> c_int { + match op { + lua::LUA_OPEQ => lua_equal(L, idx1, idx2), + lua::LUA_OPLT => lua_lessthan(L, idx1, idx2), + lua::LUA_OPLE => { + luaL_checkstack(L, 5, cstr!("not enough stack slots")); + idx1 = lua_absindex(L, idx1); + idx2 = lua_absindex(L, idx2); + lua_pushvalue(L, idx1); + lua_pushvalue(L, idx2); + compat53_call_lua(L, "local a,b=...\nreturn a<=b\n", 2, 1); + let result = lua_toboolean(L, -1); + lua_pop(L, 1); + result + } + _ => luaL_error(L, cstr!("invalid 'op' argument for lua_compare")), + } +} + +#[cfg(any(feature = "lua51", feature = "luajit"))] +pub unsafe fn lua_pushlstring(L: *mut lua_State, s: *const c_char, l: usize) -> *const c_char { + if l == 0 { + lua_pushlstring_old(L, cstr!(""), 0); + } else { + lua_pushlstring_old(L, s, l); + } + lua_tostring(L, -1) +} + +#[cfg(feature = "lua52")] +pub unsafe fn lua_pushlstring(L: *mut lua_State, s: *const c_char, l: usize) -> *const c_char { + if l == 0 { + lua_pushlstring_old(L, cstr!(""), 0) + } else { + lua_pushlstring_old(L, s, l) + } +} + +#[cfg(any(feature = "lua51", feature = "luajit"))] +pub unsafe fn lua_pushstring(L: *mut lua_State, s: *const c_char) -> *const c_char { + lua_pushstring_old(L, s); + lua_tostring(L, -1) +} + +#[cfg(feature = "lua52")] +pub unsafe fn lua_getglobal(L: *mut lua_State, var: *const c_char) -> c_int { + lua_getglobal_old(L, var); + lua_type(L, -1) +} + +pub unsafe fn lua_gettable(L: *mut lua_State, idx: c_int) -> c_int { + lua_gettable_old(L, idx); + lua_type(L, -1) +} + +pub unsafe fn lua_getfield(L: *mut lua_State, idx: c_int, k: *const c_char) -> c_int { + lua_getfield_old(L, idx, k); + lua_type(L, -1) +} + +pub unsafe fn lua_geti(L: *mut lua_State, mut idx: c_int, n: lua_Integer) -> c_int { + idx = lua_absindex(L, idx); + lua_pushinteger(L, n); + lua_gettable(L, idx); + lua_type(L, -1) +} + +// A new version which returns c_int +pub unsafe fn lua_rawget(L: *mut lua_State, idx: c_int) -> c_int { + lua_rawget_old(L, idx); + lua_type(L, -1) +} + +// A new version which returns c_int +pub unsafe fn lua_rawgeti(L: *mut lua_State, idx: c_int, n: lua_Integer) -> c_int { + lua_rawgeti_old(L, idx, n); + lua_type(L, -1) +} + +#[cfg(any(feature = "lua51", feature = "luajit"))] +pub unsafe fn lua_rawgetp(L: *mut lua_State, idx: c_int, p: *const c_void) -> c_int { + let abs_i = lua_absindex(L, idx); + lua_pushlightuserdata(L, p as *mut c_void); + lua_rawget(L, abs_i); + lua_type(L, -1) +} + +#[cfg(feature = "lua52")] +pub unsafe fn lua_rawgetp(L: *mut lua_State, idx: c_int, p: *const c_void) -> c_int { + lua_rawgetp_old(L, idx, p); + lua_type(L, -1) +} + +#[cfg(any(feature = "lua51", feature = "luajit"))] +pub unsafe fn lua_getuservalue(L: *mut lua_State, idx: c_int) -> c_int { + lua_getfenv(L, idx); + lua_type(L, -1) +} + +#[cfg(feature = "lua52")] +pub unsafe fn lua_getuservalue(L: *mut lua_State, idx: c_int) -> c_int { + lua_getuservalue_old(L, idx); + lua_type(L, -1) +} + +pub unsafe fn lua_seti(L: *mut lua_State, mut idx: c_int, n: lua_Integer) { + luaL_checkstack(L, 1, cstr!("not enough stack slots available")); + idx = lua_absindex(L, idx); + lua_pushinteger(L, n); + lua_insert(L, -2); + lua_settable(L, idx); +} + +#[cfg(any(feature = "lua51", feature = "luajit"))] +pub unsafe fn lua_rawsetp(L: *mut lua_State, idx: c_int, p: *const c_void) { + let abs_i = lua_absindex(L, idx); + luaL_checkstack(L, 1, cstr!("not enough stack slots")); + lua_pushlightuserdata(L, p as *mut c_void); + lua_insert(L, -2); + lua_rawset(L, abs_i); +} + +#[cfg(any(feature = "lua51", feature = "luajit"))] +pub unsafe fn lua_setuservalue(L: *mut lua_State, idx: c_int) { + luaL_checktype(L, -1, lua::LUA_TTABLE); + lua_setfenv(L, idx); +} + +pub unsafe fn lua_dump( + L: *mut lua_State, + writer: lua_Writer, + data: *mut c_void, + _strip: c_int, +) -> c_int { + lua_dump_old(L, writer, data) +} + +#[cfg(any(feature = "lua51", feature = "luajit"))] +pub unsafe fn lua_resume(L: *mut lua_State, _from: *mut lua_State, narg: c_int) -> c_int { + lua_resume_old(L, narg) +} + +#[cfg(any(feature = "lua51", feature = "luajit"))] +pub unsafe fn lua_len(L: *mut lua_State, idx: c_int) { + match lua_type(L, idx) { + lua::LUA_TSTRING => { + lua_pushnumber(L, lua_objlen(L, idx) as lua_Number); + } + lua::LUA_TTABLE => { + if luaL_callmeta(L, idx, cstr!("__len")) == 0 { + lua_pushnumber(L, lua_objlen(L, idx) as lua_Number); + } + } + lua::LUA_TUSERDATA if luaL_callmeta(L, idx, cstr!("__len")) != 0 => {} + _ => { + luaL_error( + L, + cstr!("attempt to get length of a %s value"), + lua_typename(L, lua_type(L, idx)), + ); + } + } +} + +pub unsafe fn lua_stringtonumber(L: *mut lua_State, s: *const c_char) -> usize { + use std::str::FromStr; + + let cs = CStr::from_ptr(s); + if let Ok(rs) = cs.to_str() { + if let Ok(n) = f64::from_str(rs.trim()) { + lua_pushnumber(L, n as lua_Number); + return cs.to_bytes_with_nul().len(); + } + } + 0 +} + +pub unsafe fn lua_getextraspace(L: *mut lua_State) -> *mut c_void { + use super::glue::LUA_EXTRASPACE; + + luaL_checkstack(L, 4, cstr!("not enough stack slots available")); + lua_pushliteral(L, "__compat53_extraspace"); + lua_pushvalue(L, -1); + lua_rawget(L, lua::LUA_REGISTRYINDEX); + if lua_istable(L, -1) == 0 { + lua_pop(L, 1); + lua_createtable(L, 0, 2); + lua_createtable(L, 0, 1); + lua_pushliteral(L, "k"); + lua_setfield(L, -2, cstr!("__mode")); + lua_setmetatable(L, -2); + lua_pushvalue(L, -2); + lua_pushvalue(L, -2); + lua_rawset(L, lua::LUA_REGISTRYINDEX); + } + lua_replace(L, -2); + let is_main = lua_pushthread(L); + lua_rawget(L, -2); + let mut _ptr = lua_touserdata(L, -1); + if _ptr.is_null() { + lua_pop(L, 1); + _ptr = lua_newuserdata(L, LUA_EXTRASPACE as usize); + if is_main != 0 { + // mem::size_of::() == 1 + ptr::write_bytes(_ptr, 0, LUA_EXTRASPACE as usize); + lua_pushthread(L); + lua_pushvalue(L, -2); + lua_rawset(L, -4); + lua_pushboolean(L, 1); + lua_pushvalue(L, -2); + lua_rawset(L, -4); + } else { + lua_pushboolean(L, 1); + lua_rawget(L, -3); + let mptr = lua_touserdata(L, -1); + if !mptr.is_null() { + ptr::copy_nonoverlapping(mptr, _ptr, LUA_EXTRASPACE as usize) + } else { + ptr::write_bytes(_ptr, 0, LUA_EXTRASPACE as usize); + } + lua_pop(L, 1); + lua_pushthread(L); + lua_pushvalue(L, -2); + lua_rawset(L, -4); + } + } + lua_pop(L, 2); + return _ptr; +} + +#[cfg(any(feature = "lua51", feature = "luajit"))] +#[inline(always)] +pub unsafe fn lua_pushglobaltable(L: *mut lua_State) { + lua_pushvalue(L, lua::LUA_GLOBALSINDEX); +} + +// +// lauxlib ported functions +// + +#[cfg(any(feature = "lua51", feature = "luajit"))] +pub unsafe fn luaL_checkstack(L: *mut lua_State, sz: c_int, msg: *const c_char) { + if lua_checkstack(L, sz + lua::LUA_MINSTACK) == 0 { + if !msg.is_null() { + luaL_error(L, cstr!("stack overflow (%s)"), msg); + } else { + lua_pushliteral(L, "stack overflow"); + lua_error(L); + } + } +} + +pub unsafe fn luaL_checkversion(_L: *mut lua_State) { + // Void +} + +pub unsafe fn luaL_getmetafield(L: *mut lua_State, obj: c_int, e: *const c_char) -> c_int { + if luaL_getmetafield_old(L, obj, e) != 0 { + lua_type(L, -1) + } else { + lua::LUA_TNIL + } +} + +pub unsafe fn luaL_newmetatable(L: *mut lua_State, tname: *const c_char) -> c_int { + if luaL_newmetatable_old(L, tname) != 0 { + lua_pushstring(L, tname); + lua_setfield(L, -2, cstr!("__name")); + 1 + } else { + 0 + } +} + +#[cfg(any(feature = "lua51", feature = "luajit"))] +pub unsafe fn luaL_loadbufferx( + L: *mut lua_State, + buff: *const c_char, + sz: usize, + name: *const c_char, + mode: *const c_char, +) -> c_int { + let status = if sz > 0 && *buff as u8 == lua::LUA_SIGNATURE[0] { + compat53_checkmode(L, mode, cstr!("binary"), lua::LUA_ERRSYNTAX) + } else { + compat53_checkmode(L, mode, cstr!("text"), lua::LUA_ERRSYNTAX) + }; + if status != lua::LUA_OK { + return status; + } + luaL_loadbuffer(L, buff, sz, name) +} + +#[cfg(any(feature = "lua51", feature = "luajit"))] +pub unsafe fn luaL_len(L: *mut lua_State, idx: c_int) -> lua_Integer { + let mut isnum = 0; + luaL_checkstack(L, 1, cstr!("not enough stack slots")); + lua_len(L, idx); + let res = lua_tointegerx(L, -1, &mut isnum); + lua::lua_pop(L, 1); + if isnum == 0 { + luaL_error(L, cstr!("object length is not an integer")); + } + res +} + +#[cfg(any(feature = "lua51", feature = "luajit"))] +pub unsafe fn luaL_traceback( + L: *mut lua_State, + L1: *mut lua_State, + msg: *const c_char, + mut level: c_int, +) { + let mut ar: lua_Debug = std::mem::zeroed(); + let top = lua_gettop(L); + let numlevels = compat53_countlevels(L1); + let mark = if numlevels > COMPAT53_LEVELS1 + COMPAT53_LEVELS2 { + COMPAT53_LEVELS1 + } else { + 0 + }; + + if !msg.is_null() { + lua_pushfstring(L, cstr!("%s\n"), msg); + } + lua_pushliteral(L, "stack traceback:"); + while lua_getstack(L1, level, &mut ar) != 0 { + level += 1; + if level == mark { + // too many levels? + lua_pushliteral(L, "\n\t..."); // add a '...' + level = numlevels - COMPAT53_LEVELS2; // and skip to last ones + } else { + lua_getinfo(L1, cstr!("Slnt"), &mut ar); + lua_pushfstring(L, cstr!("\n\t%s:"), cstr!("ok") /*ar.short_src*/); + if ar.currentline > 0 { + lua_pushfstring(L, cstr!("%d:"), ar.currentline); + } + lua_pushliteral(L, " in "); + compat53_pushfuncname(L, &mut ar); + lua_concat(L, lua_gettop(L) - top); + } + } + lua_concat(L, lua_gettop(L) - top); +} + +pub unsafe fn luaL_tolstring(L: *mut lua_State, idx: c_int, len: *mut usize) -> *const c_char { + if luaL_callmeta(L, idx, cstr!("__tostring")) == 0 { + let t = lua_type(L, idx); + match t { + lua::LUA_TNIL => { + lua_pushliteral(L, "nil"); + } + lua::LUA_TSTRING | lua::LUA_TNUMBER => { + lua_pushvalue(L, idx); + } + lua::LUA_TBOOLEAN => { + if lua_toboolean(L, idx) == 0 { + lua_pushliteral(L, "false"); + } else { + lua_pushliteral(L, "true"); + } + } + _ => { + let tt = luaL_getmetafield(L, idx, cstr!("__name")); + let name = if tt == lua::LUA_TSTRING { + lua_tostring(L, -1) + } else { + lua_typename(L, t) + }; + lua_pushfstring(L, cstr!("%s: %p"), name, lua_topointer(L, idx)); + if tt != lua::LUA_TNIL { + lua_replace(L, -2); + } + } + }; + } else if lua_isstring(L, -1) == 0 { + luaL_error(L, cstr!("'__tostring' must return a string")); + } + lua_tolstring(L, -1, len) +} + +#[cfg(any(feature = "lua51", feature = "luajit"))] +pub unsafe fn luaL_setmetatable(L: *mut lua_State, tname: *const c_char) { + luaL_checkstack(L, 1, cstr!("not enough stack slots")); + luaL_getmetatable(L, tname); + lua_setmetatable(L, -2); +} + +#[cfg(any(feature = "lua51", feature = "luajit"))] +pub unsafe fn luaL_testudata(L: *mut lua_State, i: c_int, tname: *const c_char) -> *mut c_void { + let mut p = lua_touserdata(L, i); + luaL_checkstack(L, 2, cstr!("not enough stack slots")); + if p.is_null() || lua_getmetatable(L, i) == 0 { + return ptr::null_mut(); + } else { + luaL_getmetatable(L, tname); + let res = lua_rawequal(L, -1, -2); + lua_pop(L, 2); + if res == 0 { + p = ptr::null_mut(); + } + } + return p; +} + +#[cfg(any(feature = "lua51", feature = "luajit"))] +pub unsafe fn luaL_setfuncs(L: *mut lua_State, mut l: *const luaL_Reg, nup: c_int) { + luaL_checkstack(L, nup + 1, cstr!("too many upvalues")); + while !(*l).name.is_null() { + // fill the table with given functions + l = l.offset(1); + lua_pushstring(L, (*l).name); + for _ in 0..nup { + // copy upvalues to the top + lua_pushvalue(L, -(nup + 1)); + } + lua_pushcclosure(L, (*l).func, nup); // closure with those upvalues + lua_settable(L, -(nup + 3)); // table must be below the upvalues, the name and the closure + } + lua_pop(L, nup); // remove upvalues +} + +#[cfg(any(feature = "lua51", feature = "luajit"))] +pub unsafe fn luaL_getsubtable(L: *mut lua_State, idx: c_int, fname: *const c_char) -> c_int { + let abs_i = lua_absindex(L, idx); + luaL_checkstack(L, 3, cstr!("not enough stack slots")); + lua_pushstring(L, fname); + lua_gettable(L, abs_i); + if lua_istable(L, -1) != 0 { + return 1; + } + lua_pop(L, 1); + lua_newtable(L); + lua_pushstring(L, fname); + lua_pushvalue(L, -2); + lua_settable(L, abs_i); + return 0; +} + +pub unsafe fn luaL_requiref( + L: *mut lua_State, + modname: *const c_char, + openf: lua_CFunction, + glb: c_int, +) { + luaL_checkstack(L, 3, cstr!("not enough stack slots available")); + luaL_getsubtable(L, lua::LUA_REGISTRYINDEX, cstr!("_LOADED")); + if lua_getfield(L, -1, modname) == lua::LUA_TNIL { + lua_pop(L, 1); + lua_pushcfunction(L, openf); + lua_pushstring(L, modname); + #[cfg(any(feature = "lua52", feature = "lua51"))] + { + lua_call(L, 1, 1); + lua_pushvalue(L, -1); + lua_setfield(L, -3, modname); + } + #[cfg(feature = "luajit")] + { + lua_call(L, 1, 0); + lua_getfield(L, -1, modname); + } + } + if cfg!(any(feature = "lua52", feature = "lua51")) && glb != 0 { + lua_pushvalue(L, -1); + lua_setglobal(L, modname); + } + if cfg!(feature = "luajit") && glb == 0 { + lua_pushnil(L); + lua_setglobal(L, modname); + } + lua_replace(L, -2); +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/src/ffi/glue/glue.c b/third_party/cargo/vendor/mlua-0.5.3/src/ffi/glue/glue.c new file mode 100644 index 0000000..b739a53 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/src/ffi/glue/glue.c @@ -0,0 +1,289 @@ +// The MIT License (MIT) +// +// Copyright (c) 2019-2021 A. Orlenko +// Copyright (c) 2014 J.C. Moyer +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include +#include +#include +#include + +#include +#include +#include + +#ifndef LUA_EXTRASPACE +#define LUA_EXTRASPACE (sizeof(void*)) +#endif + +// Macros taken from https://gcc.gnu.org/onlinedocs/cpp/Stringification.html +#define xstr(s) str(s) +#define str(s) #s + +typedef struct rs_item { + int type; + const char *name; + union { + int int_val; + const char *str_val; + LUA_INTEGER lua_int_val; + }; +} rs_item; + + +#define TY_INT 0 +#define RS_INT(name, val) \ + { TY_INT, name, .int_val = val } + +#if LUA_VERSION_NUM >= 503 +#define TY_LUAINT 1 +#define RS_LUAINT(name, val) \ + { TY_LUAINT, name, .lua_int_val = val } +#endif + +#define TY_STR 2 +#define RS_STR(name, val) \ + { TY_STR, name, .str_val = val } + +#define TY_TYPE 3 +#define RS_TYPE(name, val) \ + { TY_TYPE, name, .str_val = val } + +#define TY_COMMENT 4 +#define RS_COMMENT(val) \ + { TY_COMMENT, NULL, .str_val = val } + +#define TY_RAW 5 +#define RS_RAW(val) \ + { TY_RAW, NULL, .str_val = val } + +const char *rs_int_type(int width) { + switch (width) { + default: + case 2: + return "i16"; + case 4: + return "i32"; + case 8: + return "i64"; + case 16: + return "i128"; + } +} + +const char *rs_uint_type(int width) { + switch (width) { + default: + case 2: + return "u16"; + case 4: + return "u32"; + case 8: + return "u64"; + case 16: + return "u128"; + } +} + +int try_write(char **str, char c, size_t n, size_t *written, size_t szstr) { + if (szstr - *written < n) { + return 0; + } + for (; n; n--, *written++) + *(*str)++ = c; + return 1; +} + +// converts \ in a string to \\ so that it can be used as a rust string literal +// ensures that `out` will always have a null terminating character +size_t escape(const char *in, char *out, size_t szout) { + size_t written = 0; + char cur; + + while ((cur = *in++)) { + switch (cur) { + case '\\': + if (!try_write(&out, cur, 2, &written, szout)) + goto finalize; + break; + default: + if (!try_write(&out, cur, 1, &written, szout)) + goto finalize; + break; + } + } + +finalize: + if (written + 1 <= szout) { + *out++ = '\0'; + written++; + } + return written; +} + +int write_int_item(FILE *f, const char *name, int value) { + return fprintf(f, "pub const %s: c_int = %d;\n", name, value); +} + +#if LUA_VERSION_NUM >= 503 +int write_lua_int_item(FILE *f, const char *name, LUA_INTEGER value) { + return fprintf(f, "pub const %s: LUA_INTEGER = " LUA_INTEGER_FMT ";\n", name, + value); +} +#endif + +int write_str_item(FILE *f, const char *name, const char *value) { + size_t len = strlen(value); + size_t bufsz = len * 2 + 1; + char *buf = malloc(bufsz); + int ret; + escape(value, buf, bufsz); + ret = fprintf(f, "pub const %s: &str = \"%s\";\n", name, buf); + free(buf); + return ret; +} + +int write_type(FILE *f, const char *name, const char *value) { + return fprintf(f, "pub type %s = %s;\n", name, value); +} + +int write_comment(FILE *f, const char *value) { + return fprintf(f, "/* %s */\n", value); +} + +int write_raw(FILE *f, const char *value) { return fputs(value, f) >= 0; } + +int write_item(FILE *f, const rs_item *c) { + switch (c->type) { + case TY_INT: + return write_int_item(f, c->name, c->int_val); +#if LUA_VERSION_NUM >= 503 + case TY_LUAINT: + return write_lua_int_item(f, c->name, c->lua_int_val); +#endif + case TY_STR: + return write_str_item(f, c->name, c->str_val); + case TY_TYPE: + return write_type(f, c->name, c->str_val); + case TY_COMMENT: + return write_comment(f, c->str_val); + case TY_RAW: + return write_raw(f, c->str_val); + default: + return 0; + } +} + +int write_items_(FILE *f, const rs_item items[], size_t num) { + size_t i; + for (i = 0; i < num; i++) { + if (!write_item(f, &items[i])) + return 0; + } + return 1; +} + +#define write_items(f, cs) write_items_(f, cs, sizeof(cs) / sizeof(cs[0])) + +int main(int argc, const char **argv) { + if (argc <= 1) { + printf("usage: %s \n", argv[0]); + return EXIT_FAILURE; + } + + const char *filename = argv[1]; + + FILE *f = fopen(filename, "w"); + + if (!f) { + printf("could not open file: errno = %d\n", errno); + return EXIT_FAILURE; + } + + const rs_item glue_entries[] = { + RS_COMMENT("this file was generated by glue.c; do not modify it by hand"), + RS_RAW("use std::os::raw::*;\n"), + + // == luaconf.h ========================================================== + + RS_COMMENT("luaconf.h"), + RS_INT("LUA_EXTRASPACE", LUA_EXTRASPACE), + RS_INT("LUA_IDSIZE", LUA_IDSIZE), + RS_TYPE("LUA_NUMBER", + sizeof(LUA_NUMBER) > sizeof(float) ? "c_double" : "c_float"), + RS_TYPE("LUA_INTEGER", rs_int_type(sizeof(LUA_INTEGER))), +#if LUA_VERSION_NUM >= 502 + RS_TYPE("LUA_UNSIGNED", rs_uint_type(sizeof(LUA_UNSIGNED))), +#else + RS_TYPE("LUA_UNSIGNED", rs_uint_type(sizeof(size_t))), +#endif + + // == lua.h ============================================================== + + RS_COMMENT("lua.h"), + RS_INT("LUA_VERSION_NUM", LUA_VERSION_NUM), + RS_INT("LUA_REGISTRYINDEX", LUA_REGISTRYINDEX), +#if LUA_VERSION_NUM == 501 + RS_INT("LUA_ENVIRONINDEX", LUA_ENVIRONINDEX), + RS_INT("LUA_GLOBALSINDEX", LUA_GLOBALSINDEX), +#endif + + // == lauxlib.h ========================================================== + + RS_COMMENT("lauxlib.h"), +#if LUA_VERSION_NUM >= 503 + RS_INT("LUAL_NUMSIZES", LUAL_NUMSIZES), +#endif + + // == lualib.h =========================================================== + + RS_COMMENT("lualib.h"), + RS_STR("LUA_COLIBNAME", LUA_COLIBNAME), + RS_STR("LUA_TABLIBNAME", LUA_TABLIBNAME), + RS_STR("LUA_IOLIBNAME", LUA_IOLIBNAME), + RS_STR("LUA_OSLIBNAME", LUA_OSLIBNAME), + RS_STR("LUA_STRLIBNAME", LUA_STRLIBNAME), +#ifdef LUA_UTF8LIBNAME + RS_STR("LUA_UTF8LIBNAME", LUA_UTF8LIBNAME), +#endif +#ifdef LUA_BITLIBNAME + RS_STR("LUA_BITLIBNAME", LUA_BITLIBNAME), +#endif + RS_STR("LUA_MATHLIBNAME", LUA_MATHLIBNAME), + RS_STR("LUA_DBLIBNAME", LUA_DBLIBNAME), + RS_STR("LUA_LOADLIBNAME", LUA_LOADLIBNAME), +#ifdef LUA_JITLIBNAME + RS_STR("LUA_JITLIBNAME", LUA_JITLIBNAME), +#endif +#ifdef LUA_FFILIBNAME + RS_STR("LUA_FFILIBNAME", LUA_FFILIBNAME), +#endif + }; + + if (!write_items(f, glue_entries)) { + printf("%s: error generating %s; aborting\n", argv[0], filename); + return EXIT_FAILURE; + } + + fclose(f); + + return EXIT_SUCCESS; +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/src/ffi/lauxlib.rs b/third_party/cargo/vendor/mlua-0.5.3/src/ffi/lauxlib.rs new file mode 100644 index 0000000..b3c0a81 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/src/ffi/lauxlib.rs @@ -0,0 +1,306 @@ +// The MIT License (MIT) +// +// Copyright (c) 2019-2021 A. Orlenko +// Copyright (c) 2014 J.C. Moyer +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +//! Contains definitions from `lauxlib.h`. + +use std::os::raw::{c_char, c_int, c_long, c_void}; +use std::ptr; + +use super::lua::{self, lua_CFunction, lua_Integer, lua_Number, lua_State}; + +#[cfg(any(feature = "lua54", feature = "lua53"))] +pub use super::glue::LUAL_NUMSIZES; + +#[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))] +pub use super::compat53::{luaL_getmetafield, luaL_newmetatable, luaL_requiref, luaL_tolstring}; + +#[cfg(any(feature = "lua51", feature = "luajit"))] +pub use super::compat53::{ + luaL_checkstack, luaL_checkversion, luaL_getsubtable, luaL_len, luaL_loadbufferx, + luaL_setfuncs, luaL_setmetatable, luaL_testudata, luaL_traceback, +}; + +// extra error code for 'luaL_load' +pub const LUA_ERRFILE: c_int = lua::LUA_ERRERR + 1; + +#[repr(C)] +pub struct luaL_Reg { + pub name: *const c_char, + pub func: lua_CFunction, +} + +#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] +#[inline(always)] +pub unsafe fn luaL_checkversion(L: *mut lua_State) { + #[cfg(any(feature = "lua54", feature = "lua53"))] + luaL_checkversion_( + L, + lua::LUA_VERSION_NUM as lua_Number, + LUAL_NUMSIZES as usize, + ); + #[cfg(feature = "lua52")] + luaL_checkversion_(L, lua::LUA_VERSION_NUM as lua_Number); +} + +extern "C" { + #[cfg(any(feature = "lua54", feature = "lua53"))] + pub fn luaL_checkversion_(L: *mut lua_State, ver: lua_Number, sz: usize); + #[cfg(feature = "lua52")] + pub fn luaL_checkversion_(L: *mut lua_State, ver: lua_Number); + + #[cfg(any(feature = "lua54", feature = "lua53"))] + pub fn luaL_getmetafield(L: *mut lua_State, obj: c_int, e: *const c_char) -> c_int; + #[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))] + #[link_name = "luaL_getmetafield"] + pub fn luaL_getmetafield_old(L: *mut lua_State, obj: c_int, e: *const c_char) -> c_int; + + pub fn luaL_callmeta(L: *mut lua_State, obj: c_int, e: *const c_char) -> c_int; + #[cfg(any(feature = "lua54", feature = "lua53"))] + pub fn luaL_tolstring(L: *mut lua_State, idx: c_int, len: *mut usize) -> *const c_char; + pub fn luaL_argerror(L: *mut lua_State, arg: c_int, l: *const c_char) -> c_int; + pub fn luaL_checklstring(L: *mut lua_State, arg: c_int, l: *mut usize) -> *const c_char; + pub fn luaL_optlstring( + L: *mut lua_State, + arg: c_int, + def: *const c_char, + l: *mut usize, + ) -> *const c_char; + pub fn luaL_checknumber(L: *mut lua_State, arg: c_int) -> lua_Number; + pub fn luaL_optnumber(L: *mut lua_State, arg: c_int, def: lua_Number) -> lua_Number; + pub fn luaL_checkinteger(L: *mut lua_State, arg: c_int) -> lua_Integer; + pub fn luaL_optinteger(L: *mut lua_State, arg: c_int, def: lua_Integer) -> lua_Integer; + + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + pub fn luaL_checkstack(L: *mut lua_State, sz: c_int, msg: *const c_char); + pub fn luaL_checktype(L: *mut lua_State, arg: c_int, t: c_int); + pub fn luaL_checkany(L: *mut lua_State, arg: c_int); + + #[cfg(any(feature = "lua54", feature = "lua53"))] + pub fn luaL_newmetatable(L: *mut lua_State, tname: *const c_char) -> c_int; + #[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))] + #[link_name = "luaL_newmetatable"] + pub fn luaL_newmetatable_old(L: *mut lua_State, tname: *const c_char) -> c_int; + + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + pub fn luaL_setmetatable(L: *mut lua_State, tname: *const c_char); + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + pub fn luaL_testudata(L: *mut lua_State, ud: c_int, tname: *const c_char) -> *mut c_void; + pub fn luaL_checkudata(L: *mut lua_State, ud: c_int, tname: *const c_char) -> *mut c_void; + + pub fn luaL_where(L: *mut lua_State, lvl: c_int); + pub fn luaL_error(L: *mut lua_State, fmt: *const c_char, ...) -> !; + + // TODO: test this + pub fn luaL_checkoption( + L: *mut lua_State, + arg: c_int, + def: *const c_char, + lst: *const *const c_char, + ) -> c_int; + + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + pub fn luaL_fileresult(L: *mut lua_State, stat: c_int, fname: *const c_char) -> c_int; + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + pub fn luaL_execresult(L: *mut lua_State, stat: c_int) -> c_int; +} + +// pre-defined references +pub const LUA_NOREF: c_int = -2; +pub const LUA_REFNIL: c_int = -1; + +extern "C" { + pub fn luaL_ref(L: *mut lua_State, t: c_int) -> c_int; + pub fn luaL_unref(L: *mut lua_State, t: c_int, r: c_int); + + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + pub fn luaL_loadfilex(L: *mut lua_State, filename: *const c_char, mode: *const c_char) + -> c_int; + #[cfg(any(feature = "lua51", feature = "luajit"))] + pub fn luaL_loadfile(L: *mut lua_State, filename: *const c_char) -> c_int; +} + +#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] +#[inline(always)] +pub unsafe fn luaL_loadfile(L: *mut lua_State, f: *const c_char) -> c_int { + luaL_loadfilex(L, f, ptr::null()) +} + +extern "C" { + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + pub fn luaL_loadbufferx( + L: *mut lua_State, + buff: *const c_char, + sz: usize, + name: *const c_char, + mode: *const c_char, + ) -> c_int; + #[cfg(any(feature = "lua51", feature = "luajit"))] + pub fn luaL_loadbuffer( + L: *mut lua_State, + buff: *const c_char, + sz: usize, + name: *const c_char, + ) -> c_int; + pub fn luaL_loadstring(L: *mut lua_State, s: *const c_char) -> c_int; + + pub fn luaL_newstate() -> *mut lua_State; + + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + pub fn luaL_len(L: *mut lua_State, idx: c_int) -> lua_Integer; + + // TODO (lua54): luaL_addgsub + + pub fn luaL_gsub( + L: *mut lua_State, + s: *const c_char, + p: *const c_char, + r: *const c_char, + ) -> *const c_char; + + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + pub fn luaL_setfuncs(L: *mut lua_State, l: *const luaL_Reg, nup: c_int); + + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + pub fn luaL_getsubtable(L: *mut lua_State, idx: c_int, fname: *const c_char) -> c_int; + + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + pub fn luaL_traceback(L: *mut lua_State, L1: *mut lua_State, msg: *const c_char, level: c_int); + + // Skip Lua 5.2 implementation in favor of the compat53 one + #[cfg(any(feature = "lua54", feature = "lua53"))] + pub fn luaL_requiref( + L: *mut lua_State, + modname: *const c_char, + openf: lua_CFunction, + glb: c_int, + ); +} + +#[inline(always)] +#[allow(unused_variables)] +pub unsafe fn luaL_newlibtable(L: *mut lua_State, l: *const luaL_Reg) { + // TODO: figure out how to pass an appropriate hint for the second param + // this involves correcting the second parameter's type; in C this is + // sizeof(l)/sizeof(l[0]) + lua::lua_createtable(L, 0, 0) +} + +#[inline(always)] +pub unsafe fn luaL_newlib(L: *mut lua_State, l: *const luaL_Reg) { + luaL_checkversion(L); + luaL_newlibtable(L, l); + luaL_setfuncs(L, l, 0) +} + +#[inline(always)] +pub unsafe fn luaL_argcheck(L: *mut lua_State, cond: c_int, arg: c_int, extramsg: *const c_char) { + if cond == 0 { + luaL_argerror(L, arg, extramsg); + } +} + +#[inline(always)] +pub unsafe fn luaL_checkstring(L: *mut lua_State, n: c_int) -> *const c_char { + luaL_checklstring(L, n, ptr::null_mut()) +} + +#[inline(always)] +pub unsafe fn luaL_optstring(L: *mut lua_State, n: c_int, d: *const c_char) -> *const c_char { + luaL_optlstring(L, n, d, ptr::null_mut()) +} + +// From 5.3 user manual: +// Macros to project non-default integer types (luaL_checkint, luaL_optint, +// luaL_checklong, luaL_optlong) were deprecated. Use their equivalent over +// lua_Integer with a type cast (or, when possible, use lua_Integer in your +// code). +#[inline(always)] +//#[deprecated] +pub unsafe fn luaL_checkint(L: *mut lua_State, n: c_int) -> c_int { + luaL_checkinteger(L, n) as c_int +} + +#[inline(always)] +//#[deprecated] +pub unsafe fn luaL_optint(L: *mut lua_State, n: c_int, d: c_int) -> c_int { + luaL_optinteger(L, n, d as lua_Integer) as c_int +} + +#[inline(always)] +//#[deprecated] +pub unsafe fn luaL_checklong(L: *mut lua_State, n: c_int) -> c_long { + luaL_checkinteger(L, n) as c_long +} + +#[inline(always)] +//#[deprecated] +pub unsafe fn luaL_optlong(L: *mut lua_State, n: c_int, d: c_long) -> c_long { + luaL_optinteger(L, n, d as lua_Integer) as c_long +} + +#[inline(always)] +pub unsafe fn luaL_typename(L: *mut lua_State, i: c_int) -> *const c_char { + lua::lua_typename(L, lua::lua_type(L, i)) +} + +#[inline(always)] +pub unsafe fn luaL_dofile(L: *mut lua_State, filename: *const c_char) -> c_int { + let status = luaL_loadfile(L, filename); + if status == 0 { + lua::lua_pcall(L, 0, lua::LUA_MULTRET, 0) + } else { + status + } +} + +#[inline(always)] +pub unsafe fn luaL_dostring(L: *mut lua_State, s: *const c_char) -> c_int { + let status = luaL_loadstring(L, s); + if status == 0 { + lua::lua_pcall(L, 0, lua::LUA_MULTRET, 0) + } else { + status + } +} + +#[inline(always)] +pub unsafe fn luaL_getmetatable(L: *mut lua_State, n: *const c_char) { + lua::lua_getfield(L, lua::LUA_REGISTRYINDEX, n); +} + +// luaL_opt would be implemented here but it is undocumented, so it's omitted + +#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] +#[inline(always)] +pub unsafe fn luaL_loadbuffer( + L: *mut lua_State, + s: *const c_char, + sz: usize, + n: *const c_char, +) -> c_int { + luaL_loadbufferx(L, s, sz, n, ptr::null()) +} + +// TODO: Add buffer API + +// omitted: old module system compatibility (removed in 5.4) diff --git a/third_party/cargo/vendor/mlua-0.5.3/src/ffi/lua.rs b/third_party/cargo/vendor/mlua-0.5.3/src/ffi/lua.rs new file mode 100644 index 0000000..c0b76cc --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/src/ffi/lua.rs @@ -0,0 +1,808 @@ +// The MIT License (MIT) +// +// Copyright (c) 2019-2021 A. Orlenko +// Copyright (c) 2014 J.C. Moyer +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +//! Contains definitions from `lua.h`. + +#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] +use std::os::raw::c_uchar; +use std::os::raw::{c_char, c_int, c_void}; +#[cfg(feature = "lua54")] +use std::os::raw::{c_uint, c_ushort}; +use std::ptr; + +use super::luaconf; + +#[cfg(any(feature = "lua51", feature = "luajit"))] +pub use super::glue::{LUA_ENVIRONINDEX, LUA_GLOBALSINDEX}; +pub use super::glue::{LUA_REGISTRYINDEX, LUA_VERSION_NUM}; + +#[cfg(not(feature = "luajit"))] +pub const LUA_SIGNATURE: &[u8] = b"\x1bLua"; +#[cfg(feature = "luajit")] +pub const LUA_SIGNATURE: &[u8] = b"\x1bLJ"; + +// option for multiple returns in 'lua_pcall' and 'lua_call' +pub const LUA_MULTRET: c_int = -1; + +#[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))] +pub use super::compat53::{ + lua_dump, lua_getextraspace, lua_getfield, lua_geti, lua_gettable, lua_getuservalue, + lua_isinteger, lua_pushlstring, lua_rawget, lua_rawgeti, lua_rawgetp, lua_rotate, lua_seti, + lua_stringtonumber, lua_tointegerx, +}; + +#[cfg(any(feature = "lua51", feature = "luajit"))] +pub use super::compat53::{ + lua_absindex, lua_arith, lua_compare, lua_copy, lua_len, lua_pushglobaltable, lua_pushstring, + lua_rawlen, lua_rawsetp, lua_resume as lua_resume_53, lua_setuservalue, lua_tonumberx, + lua_upvalueindex, +}; + +#[cfg(feature = "lua52")] +pub use super::compat53::lua_getglobal; + +#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] +#[inline(always)] +pub fn lua_upvalueindex(i: c_int) -> c_int { + LUA_REGISTRYINDEX - i +} + +// thread status +pub const LUA_OK: c_int = 0; +pub const LUA_YIELD: c_int = 1; +pub const LUA_ERRRUN: c_int = 2; +pub const LUA_ERRSYNTAX: c_int = 3; +pub const LUA_ERRMEM: c_int = 4; +#[cfg(any(feature = "lua53", feature = "lua52"))] +pub const LUA_ERRGCMM: c_int = 5; +#[cfg(any(feature = "lua54", feature = "lua51", feature = "luajit"))] +pub const LUA_ERRERR: c_int = 5; +#[cfg(any(feature = "lua53", feature = "lua52"))] +pub const LUA_ERRERR: c_int = 6; + +pub type lua_State = c_void; + +// basic types +pub const LUA_TNONE: c_int = -1; + +pub const LUA_TNIL: c_int = 0; +pub const LUA_TBOOLEAN: c_int = 1; +pub const LUA_TLIGHTUSERDATA: c_int = 2; +pub const LUA_TNUMBER: c_int = 3; +pub const LUA_TSTRING: c_int = 4; +pub const LUA_TTABLE: c_int = 5; +pub const LUA_TFUNCTION: c_int = 6; +pub const LUA_TUSERDATA: c_int = 7; +pub const LUA_TTHREAD: c_int = 8; + +#[cfg(feature = "lua54")] +pub const LUA_NUMTYPES: c_int = 9; +#[cfg(any(feature = "lua53", feature = "lua52"))] +pub const LUA_NUMTAGS: c_int = 9; + +// minimum stack available to a C function +pub const LUA_MINSTACK: c_int = 20; + +// predefined values in the registry +#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] +pub const LUA_RIDX_MAINTHREAD: lua_Integer = 1; +#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] +pub const LUA_RIDX_GLOBALS: lua_Integer = 2; +#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] +pub const LUA_RIDX_LAST: lua_Integer = LUA_RIDX_GLOBALS; + +/// A Lua number, usually equivalent to `f64`. +pub type lua_Number = luaconf::LUA_NUMBER; + +/// A Lua integer, usually equivalent to `i64`. +pub type lua_Integer = luaconf::LUA_INTEGER; + +// unsigned integer type +pub type lua_Unsigned = luaconf::LUA_UNSIGNED; + +// type for continuation-function contexts +#[cfg(any(feature = "lua54", feature = "lua53"))] +pub type lua_KContext = luaconf::LUA_KCONTEXT; + +/// Type for native functions that can be passed to Lua. +pub type lua_CFunction = unsafe extern "C" fn(L: *mut lua_State) -> c_int; + +// Type for continuation functions +#[cfg(any(feature = "lua54", feature = "lua53"))] +pub type lua_KFunction = + unsafe extern "C" fn(L: *mut lua_State, status: c_int, ctx: lua_KContext) -> c_int; + +// Type for functions that read/write blocks when loading/dumping Lua chunks +pub type lua_Reader = + unsafe extern "C" fn(L: *mut lua_State, ud: *mut c_void, sz: *mut usize) -> *const c_char; +pub type lua_Writer = + unsafe extern "C" fn(L: *mut lua_State, p: *const c_void, sz: usize, ud: *mut c_void) -> c_int; + +// Type for memory-allocation functions. +pub type lua_Alloc = unsafe extern "C" fn( + ud: *mut c_void, + ptr: *mut c_void, + osize: usize, + nsize: usize, +) -> *mut c_void; + +// Type for warning functions +#[cfg(feature = "lua54")] +pub type lua_WarnFunction = + unsafe extern "C" fn(ud: *mut c_void, msg: *const c_char, tocont: c_int); + +extern "C" { + // state manipulation + pub fn lua_newstate(f: lua_Alloc, ud: *mut c_void) -> *mut lua_State; + pub fn lua_close(L: *mut lua_State); + pub fn lua_newthread(L: *mut lua_State) -> *mut lua_State; + #[cfg(feature = "lua54")] + pub fn lua_resetthread(L: *mut lua_State) -> c_int; + + pub fn lua_atpanic(L: *mut lua_State, panicf: lua_CFunction) -> lua_CFunction; + + #[cfg(feature = "lua54")] + pub fn lua_version(L: *mut lua_State) -> lua_Number; + #[cfg(feature = "lua53")] + pub fn lua_version(L: *mut lua_State) -> *const lua_Number; + + // basic stack manipulation + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + pub fn lua_absindex(L: *mut lua_State, idx: c_int) -> c_int; + pub fn lua_gettop(L: *mut lua_State) -> c_int; + pub fn lua_settop(L: *mut lua_State, idx: c_int); + pub fn lua_pushvalue(L: *mut lua_State, idx: c_int); + #[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))] + pub fn lua_remove(L: *mut lua_State, idx: c_int); + #[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))] + pub fn lua_insert(L: *mut lua_State, idx: c_int); + #[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))] + pub fn lua_replace(L: *mut lua_State, idx: c_int); + #[cfg(any(feature = "lua54", feature = "lua53"))] + pub fn lua_rotate(L: *mut lua_State, idx: c_int, n: c_int); + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + pub fn lua_copy(L: *mut lua_State, fromidx: c_int, toidx: c_int); + pub fn lua_checkstack(L: *mut lua_State, sz: c_int) -> c_int; + + pub fn lua_xmove(from: *mut lua_State, to: *mut lua_State, n: c_int); + + // access functions (stack -> C) + pub fn lua_isnumber(L: *mut lua_State, idx: c_int) -> c_int; + pub fn lua_isstring(L: *mut lua_State, idx: c_int) -> c_int; + pub fn lua_iscfunction(L: *mut lua_State, idx: c_int) -> c_int; + #[cfg(any(feature = "lua54", feature = "lua53"))] + pub fn lua_isinteger(L: *mut lua_State, idx: c_int) -> c_int; + pub fn lua_isuserdata(L: *mut lua_State, idx: c_int) -> c_int; + pub fn lua_type(L: *mut lua_State, idx: c_int) -> c_int; + pub fn lua_typename(L: *mut lua_State, tp: c_int) -> *const c_char; + + #[cfg(any(feature = "lua51", feature = "luajit"))] + pub fn lua_tonumber(L: *mut lua_State, idx: c_int) -> lua_Number; + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + pub fn lua_tonumberx(L: *mut lua_State, idx: c_int, isnum: *mut c_int) -> lua_Number; + #[cfg(any(feature = "lua51", feature = "luajit"))] + pub fn lua_tointeger(L: *mut lua_State, idx: c_int) -> lua_Integer; + #[cfg(any(feature = "lua54", feature = "lua53"))] + pub fn lua_tointegerx(L: *mut lua_State, idx: c_int, isnum: *mut c_int) -> lua_Integer; + pub fn lua_toboolean(L: *mut lua_State, idx: c_int) -> c_int; + pub fn lua_tolstring(L: *mut lua_State, idx: c_int, len: *mut usize) -> *const c_char; + #[cfg(any(feature = "lua51", feature = "luajit"))] + pub fn lua_objlen(L: *mut lua_State, idx: c_int) -> usize; + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + pub fn lua_rawlen(L: *mut lua_State, idx: c_int) -> usize; + pub fn lua_tocfunction(L: *mut lua_State, idx: c_int) -> lua_CFunction; + pub fn lua_touserdata(L: *mut lua_State, idx: c_int) -> *mut c_void; + pub fn lua_tothread(L: *mut lua_State, idx: c_int) -> *mut lua_State; + pub fn lua_topointer(L: *mut lua_State, idx: c_int) -> *const c_void; +} + +// Comparison and arithmetic functions +pub const LUA_OPADD: c_int = 0; +pub const LUA_OPSUB: c_int = 1; +pub const LUA_OPMUL: c_int = 2; + +#[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))] +pub const LUA_OPDIV: c_int = 3; +#[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))] +pub const LUA_OPMOD: c_int = 4; +#[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))] +pub const LUA_OPPOW: c_int = 5; +#[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))] +pub const LUA_OPUNM: c_int = 6; + +#[cfg(any(feature = "lua54", feature = "lua53"))] +pub const LUA_OPMOD: c_int = 3; +#[cfg(any(feature = "lua54", feature = "lua53"))] +pub const LUA_OPPOW: c_int = 4; +#[cfg(any(feature = "lua54", feature = "lua53"))] +pub const LUA_OPDIV: c_int = 5; +#[cfg(any(feature = "lua54", feature = "lua53"))] +pub const LUA_OPIDIV: c_int = 6; +#[cfg(any(feature = "lua54", feature = "lua53"))] +pub const LUA_OPBAND: c_int = 7; +#[cfg(any(feature = "lua54", feature = "lua53"))] +pub const LUA_OPBOR: c_int = 8; +#[cfg(any(feature = "lua54", feature = "lua53"))] +pub const LUA_OPBXOR: c_int = 9; +#[cfg(any(feature = "lua54", feature = "lua53"))] +pub const LUA_OPSHL: c_int = 10; +#[cfg(any(feature = "lua54", feature = "lua53"))] +pub const LUA_OPSHR: c_int = 11; +#[cfg(any(feature = "lua54", feature = "lua53"))] +pub const LUA_OPUNM: c_int = 12; +#[cfg(any(feature = "lua54", feature = "lua53"))] +pub const LUA_OPBNOT: c_int = 13; + +extern "C" { + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + pub fn lua_arith(L: *mut lua_State, op: c_int); +} + +pub const LUA_OPEQ: c_int = 0; +pub const LUA_OPLT: c_int = 1; +pub const LUA_OPLE: c_int = 2; + +extern "C" { + #[cfg(any(feature = "lua51", feature = "luajit"))] + pub fn lua_equal(L: *mut lua_State, idx1: c_int, idx2: c_int) -> c_int; + pub fn lua_rawequal(L: *mut lua_State, idx1: c_int, idx2: c_int) -> c_int; + #[cfg(any(feature = "lua51", feature = "luajit"))] + pub fn lua_lessthan(L: *mut lua_State, idx1: c_int, idx2: c_int) -> c_int; + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + pub fn lua_compare(L: *mut lua_State, idx1: c_int, idx2: c_int, op: c_int) -> c_int; +} + +// push functions (C -> stack) +extern "C" { + pub fn lua_pushnil(L: *mut lua_State); + pub fn lua_pushnumber(L: *mut lua_State, n: lua_Number); + pub fn lua_pushinteger(L: *mut lua_State, n: lua_Integer); + + #[cfg(any(feature = "lua54", feature = "lua53"))] + pub fn lua_pushlstring(L: *mut lua_State, s: *const c_char, l: usize) -> *const c_char; + #[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))] + #[link_name = "lua_pushlstring"] + pub fn lua_pushlstring_old(L: *mut lua_State, s: *const c_char, l: usize) -> *const c_char; + + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + pub fn lua_pushstring(L: *mut lua_State, s: *const c_char) -> *const c_char; + #[cfg(any(feature = "lua51", feature = "luajit"))] + #[link_name = "lua_pushstring"] + pub fn lua_pushstring_old(L: *mut lua_State, s: *const c_char) -> *const c_char; + + // TODO: omitted: + // lua_pushvfstring + pub fn lua_pushfstring(L: *mut lua_State, fmt: *const c_char, ...) -> *const c_char; + pub fn lua_pushcclosure(L: *mut lua_State, f: lua_CFunction, n: c_int); + pub fn lua_pushboolean(L: *mut lua_State, b: c_int); + pub fn lua_pushlightuserdata(L: *mut lua_State, p: *mut c_void); + pub fn lua_pushthread(L: *mut lua_State) -> c_int; +} + +// get functions (Lua -> stack) +extern "C" { + #[cfg(any(feature = "lua54", feature = "lua53"))] + pub fn lua_getglobal(L: *mut lua_State, var: *const c_char) -> c_int; + #[cfg(feature = "lua52")] + #[link_name = "lua_getglobal"] + pub fn lua_getglobal_old(L: *mut lua_State, var: *const c_char); + + #[cfg(any(feature = "lua54", feature = "lua53"))] + pub fn lua_gettable(L: *mut lua_State, idx: c_int) -> c_int; + #[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))] + #[link_name = "lua_gettable"] + pub fn lua_gettable_old(L: *mut lua_State, idx: c_int); + + #[cfg(any(feature = "lua54", feature = "lua53"))] + pub fn lua_getfield(L: *mut lua_State, idx: c_int, k: *const c_char) -> c_int; + #[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))] + #[link_name = "lua_getfield"] + pub fn lua_getfield_old(L: *mut lua_State, idx: c_int, k: *const c_char); + + #[cfg(any(feature = "lua54", feature = "lua53"))] + pub fn lua_geti(L: *mut lua_State, idx: c_int, n: lua_Integer) -> c_int; + + #[cfg(any(feature = "lua54", feature = "lua53"))] + pub fn lua_rawget(L: *mut lua_State, idx: c_int) -> c_int; + #[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))] + #[link_name = "lua_rawget"] + pub fn lua_rawget_old(L: *mut lua_State, idx: c_int); + + #[cfg(any(feature = "lua54", feature = "lua53"))] + pub fn lua_rawgeti(L: *mut lua_State, idx: c_int, n: lua_Integer) -> c_int; + #[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))] + #[link_name = "lua_rawgeti"] + pub fn lua_rawgeti_old(L: *mut lua_State, idx: c_int, n: lua_Integer); + + #[cfg(any(feature = "lua54", feature = "lua53"))] + pub fn lua_rawgetp(L: *mut lua_State, idx: c_int, p: *const c_void) -> c_int; + #[cfg(feature = "lua52")] + #[link_name = "lua_rawgetp"] + pub fn lua_rawgetp_old(L: *mut lua_State, idx: c_int, p: *const c_void); + + pub fn lua_createtable(L: *mut lua_State, narr: c_int, nrec: c_int); + #[cfg(feature = "lua54")] + pub fn lua_newuserdatauv(L: *mut lua_State, sz: usize, nuvalue: c_int) -> *mut c_void; + #[cfg(any( + feature = "lua53", + feature = "lua52", + feature = "lua51", + feature = "luajit" + ))] + pub fn lua_newuserdata(L: *mut lua_State, sz: usize) -> *mut c_void; + pub fn lua_getmetatable(L: *mut lua_State, objindex: c_int) -> c_int; + + #[cfg(feature = "lua54")] + pub fn lua_getiuservalue(L: *mut lua_State, idx: c_int, n: c_int) -> c_int; + #[cfg(feature = "lua53")] + pub fn lua_getuservalue(L: *mut lua_State, idx: c_int) -> c_int; + #[cfg(feature = "lua52")] + #[link_name = "lua_getuservalue"] + pub fn lua_getuservalue_old(L: *mut lua_State, idx: c_int); + #[cfg(any(feature = "lua51", feature = "luajit"))] + pub fn lua_getfenv(L: *mut lua_State, idx: c_int); +} + +#[cfg(feature = "lua54")] +#[inline(always)] +pub unsafe fn lua_newuserdata(L: *mut lua_State, sz: usize) -> *mut c_void { + lua_newuserdatauv(L, sz, 1) +} + +#[cfg(feature = "lua54")] +#[inline(always)] +pub unsafe fn lua_getuservalue(L: *mut lua_State, idx: c_int) -> c_int { + lua_getiuservalue(L, idx, 1) +} + +// set functions (stack -> Lua) +extern "C" { + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + pub fn lua_setglobal(L: *mut lua_State, var: *const c_char); + pub fn lua_settable(L: *mut lua_State, idx: c_int); + pub fn lua_setfield(L: *mut lua_State, idx: c_int, k: *const c_char); + #[cfg(any(feature = "lua54", feature = "lua53"))] + pub fn lua_seti(L: *mut lua_State, idx: c_int, n: lua_Integer); + pub fn lua_rawset(L: *mut lua_State, idx: c_int); + pub fn lua_rawseti(L: *mut lua_State, idx: c_int, n: lua_Integer); + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + pub fn lua_rawsetp(L: *mut lua_State, idx: c_int, p: *const c_void); + pub fn lua_setmetatable(L: *mut lua_State, objindex: c_int) -> c_int; + #[cfg(feature = "lua54")] + pub fn lua_setiuservalue(L: *mut lua_State, idx: c_int, n: c_int) -> c_int; + #[cfg(any(feature = "lua53", feature = "lua52"))] + pub fn lua_setuservalue(L: *mut lua_State, idx: c_int); + #[cfg(any(feature = "lua51", feature = "luajit"))] + pub fn lua_setfenv(L: *mut lua_State, idx: c_int) -> c_int; +} + +#[cfg(feature = "lua54")] +#[inline(always)] +pub unsafe fn lua_setuservalue(L: *mut lua_State, idx: c_int) { + lua_setiuservalue(L, idx, 1); +} + +// 'load' and 'call' functions (load and run Lua code) +extern "C" { + #[cfg(any(feature = "lua54", feature = "lua53"))] + pub fn lua_callk( + L: *mut lua_State, + nargs: c_int, + nresults: c_int, + ctx: lua_KContext, + k: Option, + ); + #[cfg(feature = "lua52")] + pub fn lua_callk( + L: *mut lua_State, + nargs: c_int, + nresults: c_int, + ctx: c_int, + k: Option, + ); + + #[cfg(any(feature = "lua54", feature = "lua53"))] + pub fn lua_pcallk( + L: *mut lua_State, + nargs: c_int, + nresults: c_int, + errfunc: c_int, + ctx: lua_KContext, + k: Option, + ) -> c_int; + #[cfg(feature = "lua52")] + pub fn lua_pcallk( + L: *mut lua_State, + nargs: c_int, + nresults: c_int, + errfunc: c_int, + ctx: c_int, + k: Option, + ) -> c_int; + + #[cfg(feature = "lua52")] + pub fn lua_getctx(L: *mut lua_State, ctx: *mut c_int) -> c_int; + + #[cfg(any(feature = "lua51", feature = "luajit"))] + pub fn lua_call(L: *mut lua_State, nargs: c_int, nresults: c_int); + #[cfg(any(feature = "lua51", feature = "luajit"))] + pub fn lua_pcall(L: *mut lua_State, nargs: c_int, nresults: c_int, errfunc: c_int) -> c_int; + + // TODO + pub fn lua_load( + L: *mut lua_State, + reader: lua_Reader, + dt: *mut c_void, + chunkname: *const c_char, + mode: *const c_char, + ) -> c_int; + + #[cfg(any(feature = "lua54", feature = "lua53"))] + pub fn lua_dump( + L: *mut lua_State, + writer: lua_Writer, + data: *mut c_void, + strip: c_int, + ) -> c_int; + #[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))] + #[link_name = "lua_dump"] + pub fn lua_dump_old(L: *mut lua_State, writer: lua_Writer, data: *mut c_void) -> c_int; +} + +#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] +#[inline(always)] +pub unsafe fn lua_call(L: *mut lua_State, n: c_int, r: c_int) { + lua_callk(L, n, r, 0, None) +} + +#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] +#[inline(always)] +pub unsafe fn lua_pcall(L: *mut lua_State, n: c_int, r: c_int, f: c_int) -> c_int { + lua_pcallk(L, n, r, f, 0, None) +} + +// coroutine functions +extern "C" { + #[cfg(any(feature = "lua54", feature = "lua53"))] + pub fn lua_yieldk( + L: *mut lua_State, + nresults: c_int, + ctx: lua_KContext, + k: Option, + ) -> c_int; + #[cfg(feature = "lua52")] + pub fn lua_yieldk( + L: *mut lua_State, + nresults: c_int, + ctx: c_int, + k: Option, + ) -> c_int; + #[cfg(any(feature = "lua51", feature = "luajit"))] + pub fn lua_yield(L: *mut lua_State, nresults: c_int) -> c_int; + + #[cfg(feature = "lua54")] + pub fn lua_resume( + L: *mut lua_State, + from: *mut lua_State, + narg: c_int, + nres: *mut c_int, + ) -> c_int; + #[cfg(any(feature = "lua53", feature = "lua52"))] + #[link_name = "lua_resume"] + pub fn lua_resume_53(L: *mut lua_State, from: *mut lua_State, narg: c_int) -> c_int; + #[cfg(any(feature = "lua51", feature = "luajit"))] + #[link_name = "lua_resume"] + pub fn lua_resume_old(L: *mut lua_State, narg: c_int) -> c_int; + + pub fn lua_status(L: *mut lua_State) -> c_int; + #[cfg(any(feature = "lua54", feature = "lua53"))] + pub fn lua_isyieldable(L: *mut lua_State) -> c_int; +} + +#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] +#[inline(always)] +pub unsafe fn lua_yield(L: *mut lua_State, n: c_int) -> c_int { + lua_yieldk(L, n, 0, None) +} + +#[cfg(any( + feature = "lua53", + feature = "lua52", + feature = "lua51", + feature = "luajit" +))] +pub unsafe fn lua_resume( + L: *mut lua_State, + from: *mut lua_State, + narg: c_int, + nres: *mut c_int, +) -> c_int { + let ret = lua_resume_53(L, from, narg); + if ret == LUA_OK || ret == LUA_YIELD { + *nres = lua_gettop(L); + } + ret +} + +// warning-related functions +#[cfg(feature = "lua54")] +extern "C" { + pub fn lua_setwarnf(L: *mut lua_State, f: lua_WarnFunction, ud: *mut c_void); + pub fn lua_warning(L: *mut lua_State, msg: *const c_char, tocont: c_int); +} + +// garbage-collection function and options +pub const LUA_GCSTOP: c_int = 0; +pub const LUA_GCRESTART: c_int = 1; +pub const LUA_GCCOLLECT: c_int = 2; +pub const LUA_GCCOUNT: c_int = 3; +pub const LUA_GCCOUNTB: c_int = 4; +pub const LUA_GCSTEP: c_int = 5; +pub const LUA_GCSETPAUSE: c_int = 6; +pub const LUA_GCSETSTEPMUL: c_int = 7; +#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] +pub const LUA_GCISRUNNING: c_int = 9; +#[cfg(feature = "lua54")] +pub const LUA_GCGEN: c_int = 10; +#[cfg(feature = "lua54")] +pub const LUA_GCINC: c_int = 11; + +extern "C" { + #[cfg(feature = "lua54")] + pub fn lua_gc(L: *mut lua_State, what: c_int, ...) -> c_int; + #[cfg(any( + feature = "lua53", + feature = "lua52", + feature = "lua51", + feature = "luajit" + ))] + pub fn lua_gc(L: *mut lua_State, what: c_int, data: c_int) -> c_int; +} + +// miscellaneous functions +extern "C" { + pub fn lua_error(L: *mut lua_State) -> !; + pub fn lua_next(L: *mut lua_State, idx: c_int) -> c_int; + pub fn lua_concat(L: *mut lua_State, n: c_int); + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + pub fn lua_len(L: *mut lua_State, idx: c_int); + #[cfg(any(feature = "lua54", feature = "lua53"))] + pub fn lua_stringtonumber(L: *mut lua_State, s: *const c_char) -> usize; + pub fn lua_getallocf(L: *mut lua_State, ud: *mut *mut c_void) -> lua_Alloc; + pub fn lua_setallocf(L: *mut lua_State, f: lua_Alloc, ud: *mut c_void); + #[cfg(feature = "lua54")] + pub fn lua_toclose(L: *mut lua_State, idx: c_int); +} + +// some useful macros +// here, implemented as Rust functions +#[cfg(any(feature = "lua54", feature = "lua53"))] +#[inline(always)] +pub unsafe fn lua_getextraspace(L: *mut lua_State) -> *mut c_void { + L.offset(-super::glue::LUA_EXTRASPACE as isize) as *mut c_void +} + +#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] +#[inline(always)] +pub unsafe fn lua_tonumber(L: *mut lua_State, i: c_int) -> lua_Number { + lua_tonumberx(L, i, ptr::null_mut()) +} + +#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] +#[inline(always)] +pub unsafe fn lua_tointeger(L: *mut lua_State, i: c_int) -> lua_Integer { + lua_tointegerx(L, i, ptr::null_mut()) +} + +#[inline(always)] +pub unsafe fn lua_pop(L: *mut lua_State, n: c_int) { + lua_settop(L, -n - 1) +} + +#[inline(always)] +pub unsafe fn lua_newtable(L: *mut lua_State) { + lua_createtable(L, 0, 0) +} + +#[inline(always)] +pub unsafe fn lua_register(L: *mut lua_State, n: *const c_char, f: lua_CFunction) { + lua_pushcfunction(L, f); + lua_setglobal(L, n) +} + +#[inline(always)] +pub unsafe fn lua_pushcfunction(L: *mut lua_State, f: lua_CFunction) { + lua_pushcclosure(L, f, 0) +} + +#[inline(always)] +pub unsafe fn lua_isfunction(L: *mut lua_State, n: c_int) -> c_int { + (lua_type(L, n) == LUA_TFUNCTION) as c_int +} + +#[inline(always)] +pub unsafe fn lua_istable(L: *mut lua_State, n: c_int) -> c_int { + (lua_type(L, n) == LUA_TTABLE) as c_int +} + +#[inline(always)] +pub unsafe fn lua_islightuserdata(L: *mut lua_State, n: c_int) -> c_int { + (lua_type(L, n) == LUA_TLIGHTUSERDATA) as c_int +} + +#[inline(always)] +pub unsafe fn lua_isnil(L: *mut lua_State, n: c_int) -> c_int { + (lua_type(L, n) == LUA_TNIL) as c_int +} + +#[inline(always)] +pub unsafe fn lua_isboolean(L: *mut lua_State, n: c_int) -> c_int { + (lua_type(L, n) == LUA_TBOOLEAN) as c_int +} + +#[inline(always)] +pub unsafe fn lua_isthread(L: *mut lua_State, n: c_int) -> c_int { + (lua_type(L, n) == LUA_TTHREAD) as c_int +} + +#[inline(always)] +pub unsafe fn lua_isnone(L: *mut lua_State, n: c_int) -> c_int { + (lua_type(L, n) == LUA_TNONE) as c_int +} + +#[inline(always)] +pub unsafe fn lua_isnoneornil(L: *mut lua_State, n: c_int) -> c_int { + (lua_type(L, n) <= 0) as c_int +} + +#[inline(always)] +pub unsafe fn lua_pushliteral(L: *mut lua_State, s: &'static str) -> *const c_char { + use std::ffi::CString; + let c_str = CString::new(s).unwrap(); + lua_pushlstring(L, c_str.as_ptr(), c_str.as_bytes().len()) +} + +#[cfg(any(feature = "lua51", feature = "luajit"))] +#[inline(always)] +pub unsafe fn lua_setglobal(L: *mut lua_State, var: *const c_char) { + lua_setfield(L, LUA_GLOBALSINDEX, var) +} + +#[cfg(any(feature = "lua51", feature = "luajit"))] +#[inline(always)] +pub unsafe fn lua_getglobal(L: *mut lua_State, var: *const c_char) -> c_int { + lua_getfield(L, LUA_GLOBALSINDEX, var) +} + +#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] +#[inline(always)] +pub unsafe fn lua_pushglobaltable(L: *mut lua_State) -> c_int { + lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS) +} + +#[inline(always)] +pub unsafe fn lua_tostring(L: *mut lua_State, i: c_int) -> *const c_char { + lua_tolstring(L, i, ptr::null_mut()) +} + +#[cfg(any(feature = "lua54", feature = "lua53"))] +#[inline(always)] +pub unsafe fn lua_insert(L: *mut lua_State, idx: c_int) { + lua_rotate(L, idx, 1) +} + +#[cfg(any(feature = "lua54", feature = "lua53"))] +#[inline(always)] +pub unsafe fn lua_remove(L: *mut lua_State, idx: c_int) { + lua_rotate(L, idx, -1); + lua_pop(L, 1) +} + +#[cfg(any(feature = "lua54", feature = "lua53"))] +#[inline(always)] +pub unsafe fn lua_replace(L: *mut lua_State, idx: c_int) { + lua_copy(L, -1, idx); + lua_pop(L, 1) +} + +// Debug API +// Event codes +pub const LUA_HOOKCALL: c_int = 0; +pub const LUA_HOOKRET: c_int = 1; +pub const LUA_HOOKLINE: c_int = 2; +pub const LUA_HOOKCOUNT: c_int = 3; +pub const LUA_HOOKTAILCALL: c_int = 4; + +// Event masks +pub const LUA_MASKCALL: c_int = 1 << (LUA_HOOKCALL as usize); +pub const LUA_MASKRET: c_int = 1 << (LUA_HOOKRET as usize); +pub const LUA_MASKLINE: c_int = 1 << (LUA_HOOKLINE as usize); +pub const LUA_MASKCOUNT: c_int = 1 << (LUA_HOOKCOUNT as usize); + +/// Type for functions to be called on debug events. +pub type lua_Hook = unsafe extern "C" fn(L: *mut lua_State, ar: *mut lua_Debug); + +extern "C" { + pub fn lua_getstack(L: *mut lua_State, level: c_int, ar: *mut lua_Debug) -> c_int; + pub fn lua_getinfo(L: *mut lua_State, what: *const c_char, ar: *mut lua_Debug) -> c_int; + pub fn lua_getlocal(L: *mut lua_State, ar: *const lua_Debug, n: c_int) -> *const c_char; + pub fn lua_setlocal(L: *mut lua_State, ar: *const lua_Debug, n: c_int) -> *const c_char; + pub fn lua_getupvalue(L: *mut lua_State, funcindex: c_int, n: c_int) -> *const c_char; + pub fn lua_setupvalue(L: *mut lua_State, funcindex: c_int, n: c_int) -> *const c_char; + + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + pub fn lua_upvalueid(L: *mut lua_State, fidx: c_int, n: c_int) -> *mut c_void; + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + pub fn lua_upvaluejoin(L: *mut lua_State, fidx1: c_int, n1: c_int, fidx2: c_int, n2: c_int); + + pub fn lua_sethook(L: *mut lua_State, func: Option, mask: c_int, count: c_int); + pub fn lua_gethook(L: *mut lua_State) -> Option; + pub fn lua_gethookmask(L: *mut lua_State) -> c_int; + pub fn lua_gethookcount(L: *mut lua_State) -> c_int; + + #[cfg(feature = "lua54")] + pub fn lua_setcstacklimit(L: *mut lua_State, limit: c_uint) -> c_int; +} + +#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] +#[repr(C)] +pub struct lua_Debug { + pub event: c_int, + pub name: *const c_char, + pub namewhat: *const c_char, + pub what: *const c_char, + pub source: *const c_char, + #[cfg(feature = "lua54")] + pub srclen: usize, + pub currentline: c_int, + pub linedefined: c_int, + pub lastlinedefined: c_int, + pub nups: c_uchar, + pub nparams: c_uchar, + pub isvararg: c_char, + pub istailcall: c_char, + #[cfg(feature = "lua54")] + pub ftransfer: c_ushort, + #[cfg(feature = "lua54")] + pub ntransfer: c_ushort, + pub short_src: [c_char; luaconf::LUA_IDSIZE as usize], + // lua.h mentions this is for private use + i_ci: *mut c_void, +} + +#[cfg(any(feature = "lua51", feature = "luajit"))] +#[repr(C)] +pub struct lua_Debug { + pub event: c_int, + pub name: *const c_char, + pub namewhat: *const c_char, + pub what: *const c_char, + pub source: *const c_char, + pub currentline: c_int, + pub nups: c_int, + pub linedefined: c_int, + pub lastlinedefined: c_int, + pub short_src: [c_char; luaconf::LUA_IDSIZE as usize], + // lua.h mentions this is for private use + i_ci: c_int, +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/src/ffi/luaconf.rs b/third_party/cargo/vendor/mlua-0.5.3/src/ffi/luaconf.rs new file mode 100644 index 0000000..be67a75 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/src/ffi/luaconf.rs @@ -0,0 +1,36 @@ +// The MIT License (MIT) +// +// Copyright (c) 2019-2021 A. Orlenko +// Copyright (c) 2014 J.C. Moyer +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +//! Contains definitions from `luaconf.h`. + +pub use super::glue::LUA_INTEGER; +pub use super::glue::LUA_NUMBER; +pub use super::glue::LUA_UNSIGNED; + +pub use super::glue::LUA_IDSIZE; + +#[cfg(any(feature = "lua54", feature = "lua53"))] +pub use super::glue::LUAL_NUMSIZES; + +#[cfg(any(feature = "lua54", feature = "lua53"))] +pub type LUA_KCONTEXT = isize; // intptr_t diff --git a/third_party/cargo/vendor/mlua-0.5.3/src/ffi/lualib.rs b/third_party/cargo/vendor/mlua-0.5.3/src/ffi/lualib.rs new file mode 100644 index 0000000..806fa03 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/src/ffi/lualib.rs @@ -0,0 +1,67 @@ +// The MIT License (MIT) +// +// Copyright (c) 2019-2021 A. Orlenko +// Copyright (c) 2014 J.C. Moyer +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +//! Contains definitions from `lualib.h`. + +use std::os::raw::c_int; + +use super::lua::lua_State; + +pub use super::glue::{ + LUA_COLIBNAME, LUA_DBLIBNAME, LUA_IOLIBNAME, LUA_LOADLIBNAME, LUA_MATHLIBNAME, LUA_OSLIBNAME, + LUA_STRLIBNAME, LUA_TABLIBNAME, +}; + +#[cfg(any(feature = "lua54", feature = "lua53"))] +pub use super::glue::LUA_UTF8LIBNAME; + +#[cfg(any(feature = "lua52", feature = "luajit"))] +pub use super::glue::LUA_BITLIBNAME; + +#[cfg(feature = "luajit")] +pub use super::glue::{LUA_FFILIBNAME, LUA_JITLIBNAME}; + +extern "C" { + pub fn luaopen_base(L: *mut lua_State) -> c_int; + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + pub fn luaopen_coroutine(L: *mut lua_State) -> c_int; + pub fn luaopen_table(L: *mut lua_State) -> c_int; + pub fn luaopen_io(L: *mut lua_State) -> c_int; + pub fn luaopen_os(L: *mut lua_State) -> c_int; + pub fn luaopen_string(L: *mut lua_State) -> c_int; + #[cfg(any(feature = "lua54", feature = "lua53"))] + pub fn luaopen_utf8(L: *mut lua_State) -> c_int; + #[cfg(feature = "lua52")] + pub fn luaopen_bit32(L: *mut lua_State) -> c_int; + pub fn luaopen_math(L: *mut lua_State) -> c_int; + pub fn luaopen_debug(L: *mut lua_State) -> c_int; + pub fn luaopen_package(L: *mut lua_State) -> c_int; + #[cfg(feature = "luajit")] + pub fn luaopen_bit(L: *mut lua_State) -> c_int; + #[cfg(feature = "luajit")] + pub fn luaopen_jit(L: *mut lua_State) -> c_int; + #[cfg(feature = "luajit")] + pub fn luaopen_ffi(L: *mut lua_State) -> c_int; + + pub fn luaL_openlibs(L: *mut lua_State); +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/src/ffi/mod.rs b/third_party/cargo/vendor/mlua-0.5.3/src/ffi/mod.rs new file mode 100644 index 0000000..3157944 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/src/ffi/mod.rs @@ -0,0 +1,290 @@ +// The MIT License (MIT) +// +// Copyright (c) 2019-2021 A. Orlenko +// Copyright (c) 2014 J.C. Moyer +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +//! Low level bindings to Lua. + +#![allow(non_camel_case_types, non_snake_case, dead_code)] + +use std::os::raw::c_int; + +// This is more or less in the order it appears in the Lua manual, with the +// exception of constants, which appear scattered throughout the manual text. + +// C API types +pub use self::lua::{ + lua_Alloc, lua_CFunction, lua_Debug, lua_Hook, lua_Integer, lua_Number, lua_Reader, lua_State, + lua_Unsigned, lua_Writer, +}; + +#[cfg(feature = "lua54")] +pub use self::lua::lua_WarnFunction; + +#[cfg(any(feature = "lua54", feature = "lua53"))] +pub use self::lua::{lua_KContext, lua_KFunction}; + +#[cfg(any(feature = "lua51", feature = "luajit"))] +pub use self::lua::{lua_getfenv, lua_setfenv}; + +// C API functions +pub use self::lua::{ + lua_absindex, + lua_arith, + lua_atpanic, + lua_call, + lua_checkstack, + lua_close, + lua_compare, + lua_concat, + lua_copy, + lua_createtable, + lua_dump, + lua_error, + lua_gc, + lua_getallocf, + lua_getextraspace, + lua_getfield, + lua_getglobal, + lua_gethook, + lua_gethookcount, + lua_gethookmask, + lua_geti, + lua_getinfo, + lua_getlocal, + lua_getmetatable, + lua_getstack, + lua_gettable, + lua_gettop, + lua_getupvalue, + lua_getuservalue, + lua_insert, + lua_isboolean, + lua_iscfunction, + lua_isfunction, + lua_isinteger, + lua_islightuserdata, + lua_isnil, + lua_isnone, + lua_isnoneornil, + lua_isnumber, + lua_isstring, + lua_istable, + lua_isthread, + lua_isuserdata, + lua_len, + lua_load, + lua_newstate, + lua_newtable, + lua_newthread, + lua_newuserdata, + lua_next, + lua_pcall, + lua_pop, + lua_pushboolean, + lua_pushcclosure, + lua_pushcfunction, + lua_pushfstring, + lua_pushglobaltable, + lua_pushinteger, + lua_pushlightuserdata, + lua_pushliteral, + lua_pushlstring, + lua_pushnil, + lua_pushnumber, + lua_pushstring, + lua_pushthread, + lua_pushvalue, + // omitted: lua_pushvfstring + lua_rawequal, + lua_rawget, + lua_rawgeti, + lua_rawgetp, + lua_rawlen, + lua_rawset, + lua_rawseti, + lua_rawsetp, + lua_register, + lua_remove, + lua_replace, + lua_resume, + lua_rotate, + lua_setallocf, + lua_setfield, + lua_setglobal, + lua_sethook, + lua_seti, + lua_setlocal, + lua_setmetatable, + lua_settable, + lua_settop, + lua_setupvalue, + lua_setuservalue, + lua_status, + lua_stringtonumber, + lua_toboolean, + lua_tocfunction, + lua_tointeger, + lua_tointegerx, + lua_tolstring, + lua_tonumber, + lua_tonumberx, + lua_topointer, + lua_tostring, + lua_tothread, + lua_touserdata, + lua_type, + lua_typename, + lua_upvalueindex, + lua_xmove, + lua_yield, +}; + +#[cfg(feature = "lua54")] +pub use self::lua::{ + lua_getiuservalue, lua_newuserdatauv, lua_resetthread, lua_setcstacklimit, lua_setiuservalue, + lua_setwarnf, lua_toclose, lua_warning, +}; + +#[cfg(any(feature = "lua54", feature = "lua53"))] +pub use self::lua::{lua_isyieldable, lua_version}; + +#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] +pub use self::lua::{lua_callk, lua_pcallk, lua_upvalueid, lua_upvaluejoin, lua_yieldk}; + +// auxiliary library types +pub use self::lauxlib::luaL_Reg; + +// auxiliary library functions +pub use self::lauxlib::{ + luaL_argcheck, luaL_argerror, luaL_callmeta, luaL_checkany, luaL_checkint, luaL_checkinteger, + luaL_checklong, luaL_checklstring, luaL_checknumber, luaL_checkoption, luaL_checkstack, + luaL_checkstring, luaL_checktype, luaL_checkudata, luaL_checkversion, luaL_dofile, + luaL_dostring, luaL_error, luaL_getmetafield, luaL_getmetatable, luaL_getsubtable, luaL_gsub, + luaL_len, luaL_loadbuffer, luaL_loadbufferx, luaL_loadfile, luaL_loadstring, luaL_newlib, + luaL_newlibtable, luaL_newmetatable, luaL_newstate, luaL_optint, luaL_optinteger, luaL_optlong, + luaL_optlstring, luaL_optnumber, luaL_optstring, luaL_ref, luaL_requiref, luaL_setfuncs, + luaL_setmetatable, luaL_testudata, luaL_tolstring, luaL_traceback, luaL_typename, luaL_unref, + luaL_where, +}; + +#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] +pub use self::lauxlib::{luaL_execresult, luaL_fileresult, luaL_loadfilex}; + +// lualib.h functions +pub use self::lualib::{ + luaL_openlibs, luaopen_base, luaopen_debug, luaopen_io, luaopen_math, luaopen_os, + luaopen_package, luaopen_string, luaopen_table, +}; + +#[cfg(any(feature = "lua54", feature = "lua53"))] +pub use self::lualib::{luaopen_coroutine, luaopen_utf8}; + +#[cfg(feature = "lua52")] +pub use self::lualib::{luaopen_bit32, luaopen_coroutine}; + +#[cfg(feature = "luajit")] +pub use self::lualib::{luaopen_bit, luaopen_ffi, luaopen_jit}; + +// constants from lua.h +pub use self::lua::{ + LUA_ERRERR, LUA_ERRMEM, LUA_ERRRUN, LUA_ERRSYNTAX, LUA_GCCOLLECT, LUA_GCCOUNT, LUA_GCCOUNTB, + LUA_GCRESTART, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, LUA_GCSTEP, LUA_GCSTOP, LUA_HOOKCALL, + LUA_HOOKCOUNT, LUA_HOOKLINE, LUA_HOOKRET, LUA_HOOKTAILCALL, LUA_MASKCALL, LUA_MASKCOUNT, + LUA_MASKLINE, LUA_MASKRET, LUA_MINSTACK, LUA_MULTRET, LUA_OK, LUA_OPADD, LUA_OPDIV, LUA_OPEQ, + LUA_OPLE, LUA_OPLT, LUA_OPMOD, LUA_OPMUL, LUA_OPPOW, LUA_OPSUB, LUA_OPUNM, LUA_REGISTRYINDEX, + LUA_SIGNATURE, LUA_TBOOLEAN, LUA_TFUNCTION, LUA_TLIGHTUSERDATA, LUA_TNIL, LUA_TNONE, + LUA_TNUMBER, LUA_TSTRING, LUA_TTABLE, LUA_TTHREAD, LUA_TUSERDATA, LUA_YIELD, +}; + +#[cfg(any(feature = "lua54", feature = "lua53"))] +pub use self::lua::{ + LUA_OPBAND, LUA_OPBNOT, LUA_OPBOR, LUA_OPBXOR, LUA_OPIDIV, LUA_OPSHL, LUA_OPSHR, +}; + +#[cfg(feature = "lua54")] +pub use self::lua::{LUA_GCGEN, LUA_GCINC}; + +#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] +pub use self::lua::{LUA_GCISRUNNING, LUA_RIDX_GLOBALS, LUA_RIDX_MAINTHREAD}; + +#[cfg(any(feature = "lua53", feature = "lua52"))] +pub use self::lua::LUA_ERRGCMM; + +#[cfg(any(feature = "lua51", feature = "luajit"))] +pub use self::lua::{LUA_ENVIRONINDEX, LUA_GLOBALSINDEX}; + +// constants from lauxlib.h +pub use self::lauxlib::{LUA_ERRFILE, LUA_NOREF, LUA_REFNIL}; + +// constants from lualib.h +pub use self::lualib::{ + LUA_COLIBNAME, LUA_DBLIBNAME, LUA_IOLIBNAME, LUA_LOADLIBNAME, LUA_MATHLIBNAME, LUA_OSLIBNAME, + LUA_STRLIBNAME, LUA_TABLIBNAME, +}; + +#[cfg(any(feature = "lua54", feature = "lua53"))] +pub use self::lualib::LUA_UTF8LIBNAME; + +#[cfg(any(feature = "lua52", feature = "luajit"))] +pub use self::lualib::LUA_BITLIBNAME; + +#[cfg(feature = "luajit")] +pub use self::lualib::{LUA_FFILIBNAME, LUA_JITLIBNAME}; + +// Not actually defined in lua.h / luaconf.h +pub const LUA_MAX_UPVALUES: c_int = 255; + +// Copied from https://github.com/rust-lang/rust/blob/master/src/libstd/sys_common/alloc.rs +#[cfg(all(any( + target_arch = "x86", + target_arch = "arm", + target_arch = "mips", + target_arch = "powerpc", + target_arch = "powerpc64", + target_arch = "asmjs", + target_arch = "wasm32", + target_arch = "hexagon" +)))] +pub const SYS_MIN_ALIGN: usize = 8; +#[cfg(all(any( + target_arch = "x86_64", + target_arch = "aarch64", + target_arch = "mips64", + target_arch = "s390x", + target_arch = "sparc64", + target_arch = "riscv64" +)))] +pub const SYS_MIN_ALIGN: usize = 16; + +#[allow(unused_imports, dead_code, non_camel_case_types)] +#[allow(clippy::unreadable_literal)] +mod glue { + include!(concat!(env!("OUT_DIR"), "/glue.rs")); +} + +#[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))] +mod compat53; + +mod lauxlib; +mod lua; +mod luaconf; +mod lualib; diff --git a/third_party/cargo/vendor/mlua-0.5.3/src/function.rs b/third_party/cargo/vendor/mlua-0.5.3/src/function.rs new file mode 100644 index 0000000..9a9c205 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/src/function.rs @@ -0,0 +1,251 @@ +use std::os::raw::{c_int, c_void}; +use std::{ptr, slice}; + +use crate::error::{Error, Result}; +use crate::ffi; +use crate::types::LuaRef; +use crate::util::{ + assert_stack, check_stack, error_traceback, pop_error, protect_lua_closure, StackGuard, +}; +use crate::value::{FromLuaMulti, MultiValue, ToLuaMulti}; + +#[cfg(feature = "async")] +use {futures_core::future::LocalBoxFuture, futures_util::future}; + +/// Handle to an internal Lua function. +#[derive(Clone, Debug)] +pub struct Function<'lua>(pub(crate) LuaRef<'lua>); + +impl<'lua> Function<'lua> { + /// Calls the function, passing `args` as function arguments. + /// + /// The function's return values are converted to the generic type `R`. + /// + /// # Examples + /// + /// Call Lua's built-in `tostring` function: + /// + /// ``` + /// # use mlua::{Function, Lua, Result}; + /// # fn main() -> Result<()> { + /// # let lua = Lua::new(); + /// let globals = lua.globals(); + /// + /// let tostring: Function = globals.get("tostring")?; + /// + /// assert_eq!(tostring.call::<_, String>(123)?, "123"); + /// + /// # Ok(()) + /// # } + /// ``` + /// + /// Call a function with multiple arguments: + /// + /// ``` + /// # use mlua::{Function, Lua, Result}; + /// # fn main() -> Result<()> { + /// # let lua = Lua::new(); + /// let sum: Function = lua.load( + /// r#" + /// function(a, b) + /// return a + b + /// end + /// "#).eval()?; + /// + /// assert_eq!(sum.call::<_, u32>((3, 4))?, 3 + 4); + /// + /// # Ok(()) + /// # } + /// ``` + pub fn call, R: FromLuaMulti<'lua>>(&self, args: A) -> Result { + let lua = self.0.lua; + + let args = args.to_lua_multi(lua)?; + let nargs = args.len() as c_int; + + let results = unsafe { + let _sg = StackGuard::new(lua.state); + check_stack(lua.state, nargs + 3)?; + + ffi::lua_pushcfunction(lua.state, error_traceback); + let stack_start = ffi::lua_gettop(lua.state); + lua.push_ref(&self.0); + for arg in args { + lua.push_value(arg)?; + } + let ret = ffi::lua_pcall(lua.state, nargs, ffi::LUA_MULTRET, stack_start); + if ret != ffi::LUA_OK { + return Err(pop_error(lua.state, ret)); + } + let nresults = ffi::lua_gettop(lua.state) - stack_start; + let mut results = MultiValue::new(); + assert_stack(lua.state, 2); + for _ in 0..nresults { + results.push_front(lua.pop_value()); + } + ffi::lua_pop(lua.state, 1); + results + }; + R::from_lua_multi(results, lua) + } + + /// Returns a Feature that, when polled, calls `self`, passing `args` as function arguments, + /// and drives the execution. + /// + /// Internaly it wraps the function to an [`AsyncThread`]. + /// + /// Requires `feature = "async"` + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// use futures_timer::Delay; + /// # use mlua::{Lua, Result}; + /// # #[tokio::main] + /// # async fn main() -> Result<()> { + /// # let lua = Lua::new(); + /// + /// let sleep = lua.create_async_function(move |_lua, n: u64| async move { + /// Delay::new(Duration::from_millis(n)).await; + /// Ok(()) + /// })?; + /// + /// sleep.call_async(10).await?; + /// + /// # Ok(()) + /// # } + /// ``` + /// + /// [`AsyncThread`]: struct.AsyncThread.html + #[cfg(feature = "async")] + #[cfg_attr(docsrs, doc(cfg(feature = "async")))] + pub fn call_async<'fut, A, R>(&self, args: A) -> LocalBoxFuture<'fut, Result> + where + 'lua: 'fut, + A: ToLuaMulti<'lua>, + R: FromLuaMulti<'lua> + 'fut, + { + let lua = self.0.lua; + match lua.create_thread(self.clone()) { + Ok(t) => Box::pin(t.into_async(args)), + Err(e) => Box::pin(future::err(e)), + } + } + + /// Returns a function that, when called, calls `self`, passing `args` as the first set of + /// arguments. + /// + /// If any arguments are passed to the returned function, they will be passed after `args`. + /// + /// # Examples + /// + /// ``` + /// # use mlua::{Function, Lua, Result}; + /// # fn main() -> Result<()> { + /// # let lua = Lua::new(); + /// let sum: Function = lua.load( + /// r#" + /// function(a, b) + /// return a + b + /// end + /// "#).eval()?; + /// + /// let bound_a = sum.bind(1)?; + /// assert_eq!(bound_a.call::<_, u32>(2)?, 1 + 2); + /// + /// let bound_a_and_b = sum.bind(13)?.bind(57)?; + /// assert_eq!(bound_a_and_b.call::<_, u32>(())?, 13 + 57); + /// + /// # Ok(()) + /// # } + /// ``` + pub fn bind>(&self, args: A) -> Result> { + unsafe extern "C" fn bind_call_impl(state: *mut ffi::lua_State) -> c_int { + let nargs = ffi::lua_gettop(state); + let nbinds = ffi::lua_tointeger(state, ffi::lua_upvalueindex(2)) as c_int; + ffi::luaL_checkstack(state, nbinds + 2, ptr::null()); + + ffi::lua_settop(state, nargs + nbinds + 1); + ffi::lua_rotate(state, -(nargs + nbinds + 1), nbinds + 1); + + ffi::lua_pushvalue(state, ffi::lua_upvalueindex(1)); + ffi::lua_replace(state, 1); + + for i in 0..nbinds { + ffi::lua_pushvalue(state, ffi::lua_upvalueindex(i + 3)); + ffi::lua_replace(state, i + 2); + } + + ffi::lua_call(state, nargs + nbinds, ffi::LUA_MULTRET); + ffi::lua_gettop(state) + } + + let lua = self.0.lua; + + let args = args.to_lua_multi(lua)?; + let nargs = args.len() as c_int; + + if nargs + 2 > ffi::LUA_MAX_UPVALUES { + return Err(Error::BindError); + } + + unsafe { + let _sg = StackGuard::new(lua.state); + check_stack(lua.state, nargs + 5)?; + lua.push_ref(&self.0); + ffi::lua_pushinteger(lua.state, nargs as ffi::lua_Integer); + for arg in args { + lua.push_value(arg)?; + } + + protect_lua_closure(lua.state, nargs + 2, 1, |state| { + ffi::lua_pushcclosure(state, bind_call_impl, nargs + 2); + })?; + + Ok(Function(lua.pop_ref())) + } + } + + /// Dumps the function as a binary chunk. + /// + /// If `strip` is true, the binary representation may not include all debug information + /// about the function, to save space. + pub fn dump(&self, strip: bool) -> Result> { + unsafe extern "C" fn writer( + _state: *mut ffi::lua_State, + buf: *const c_void, + buf_len: usize, + data: *mut c_void, + ) -> c_int { + let data = &mut *(data as *mut Vec); + let buf = slice::from_raw_parts(buf as *const u8, buf_len); + data.extend_from_slice(buf); + 0 + } + + let lua = self.0.lua; + let mut data: Vec = Vec::new(); + unsafe { + let _sg = StackGuard::new(lua.state); + assert_stack(lua.state, 1); + lua.push_ref(&self.0); + let strip = if strip { 1 } else { 0 }; + ffi::lua_dump( + lua.state, + writer, + &mut data as *mut Vec as *mut c_void, + strip, + ); + ffi::lua_pop(lua.state, 1); + } + + Ok(data) + } +} + +impl<'lua> PartialEq for Function<'lua> { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/src/hook.rs b/third_party/cargo/vendor/mlua-0.5.3/src/hook.rs new file mode 100644 index 0000000..f00e09b --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/src/hook.rs @@ -0,0 +1,195 @@ +use std::ffi::CStr; +use std::marker::PhantomData; +use std::os::raw::{c_char, c_int}; + +use crate::ffi::{self, lua_Debug, lua_State}; +use crate::lua::Lua; +use crate::util::callback_error; + +/// Contains information about currently executing Lua code. +/// +/// The `Debug` structure is provided as a parameter to the hook function set with +/// [`Lua::set_hook`]. You may call the methods on this structure to retrieve information about the +/// Lua code executing at the time that the hook function was called. Further information can be +/// found in the [Lua 5.3 documentaton][lua_doc]. +/// +/// [lua_doc]: https://www.lua.org/manual/5.3/manual.html#lua_Debug +/// [`Lua::set_hook`]: struct.Lua.html#method.set_hook +#[derive(Clone)] +pub struct Debug<'a> { + ar: *mut lua_Debug, + state: *mut lua_State, + _phantom: PhantomData<&'a ()>, +} + +impl<'a> Debug<'a> { + /// Corresponds to the `n` what mask. + pub fn names(&self) -> DebugNames<'a> { + unsafe { + mlua_assert!( + ffi::lua_getinfo(self.state, cstr!("n"), self.ar) != 0, + "lua_getinfo failed with `n`" + ); + DebugNames { + name: ptr_to_str((*self.ar).name), + name_what: ptr_to_str((*self.ar).namewhat), + } + } + } + + /// Corresponds to the `S` what mask. + pub fn source(&self) -> DebugSource<'a> { + unsafe { + mlua_assert!( + ffi::lua_getinfo(self.state, cstr!("S"), self.ar) != 0, + "lua_getinfo failed with `S`" + ); + DebugSource { + source: ptr_to_str((*self.ar).source), + short_src: ptr_to_str((*self.ar).short_src.as_ptr()), + line_defined: (*self.ar).linedefined as i32, + last_line_defined: (*self.ar).lastlinedefined as i32, + what: ptr_to_str((*self.ar).what), + } + } + } + + /// Corresponds to the `l` what mask. Returns the current line. + pub fn curr_line(&self) -> i32 { + unsafe { + mlua_assert!( + ffi::lua_getinfo(self.state, cstr!("l"), self.ar) != 0, + "lua_getinfo failed with `l`" + ); + (*self.ar).currentline as i32 + } + } + + /// Corresponds to the `t` what mask. Returns true if the hook is in a function tail call, false + /// otherwise. + pub fn is_tail_call(&self) -> bool { + unsafe { + mlua_assert!( + ffi::lua_getinfo(self.state, cstr!("t"), self.ar) != 0, + "lua_getinfo failed with `t`" + ); + (*self.ar).currentline != 0 + } + } + + /// Corresponds to the `u` what mask. + pub fn stack(&self) -> DebugStack { + unsafe { + mlua_assert!( + ffi::lua_getinfo(self.state, cstr!("u"), self.ar) != 0, + "lua_getinfo failed with `u`" + ); + DebugStack { + num_ups: (*self.ar).nups as i32, + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + num_params: (*self.ar).nparams as i32, + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + is_vararg: (*self.ar).isvararg != 0, + } + } + } +} + +#[derive(Clone, Debug)] +pub struct DebugNames<'a> { + pub name: Option<&'a [u8]>, + pub name_what: Option<&'a [u8]>, +} + +#[derive(Clone, Debug)] +pub struct DebugSource<'a> { + pub source: Option<&'a [u8]>, + pub short_src: Option<&'a [u8]>, + pub line_defined: i32, + pub last_line_defined: i32, + pub what: Option<&'a [u8]>, +} + +#[derive(Copy, Clone, Debug)] +pub struct DebugStack { + pub num_ups: i32, + /// Requires `feature = "lua54/lua53/lua52"` + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52", doc))] + pub num_params: i32, + /// Requires `feature = "lua54/lua53/lua52"` + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52", doc))] + pub is_vararg: bool, +} + +/// Determines when a hook function will be called by Lua. +#[derive(Clone, Copy, Debug, Default)] +pub struct HookTriggers { + /// Before a function call. + pub on_calls: bool, + /// When Lua returns from a function. + pub on_returns: bool, + /// Before executing a new line, or returning from a function call. + pub every_line: bool, + /// After a certain number of VM instructions have been executed. When set to `Some(count)`, + /// `count` is the number of VM instructions to execute before calling the hook. + /// + /// # Performance + /// + /// Setting this option to a low value can incur a very high overhead. + pub every_nth_instruction: Option, +} + +impl HookTriggers { + // Compute the mask to pass to `lua_sethook`. + pub(crate) fn mask(&self) -> c_int { + let mut mask: c_int = 0; + if self.on_calls { + mask |= ffi::LUA_MASKCALL + } + if self.on_returns { + mask |= ffi::LUA_MASKRET + } + if self.every_line { + mask |= ffi::LUA_MASKLINE + } + if self.every_nth_instruction.is_some() { + mask |= ffi::LUA_MASKCOUNT + } + mask + } + + // Returns the `count` parameter to pass to `lua_sethook`, if applicable. Otherwise, zero is + // returned. + pub(crate) fn count(&self) -> c_int { + self.every_nth_instruction.unwrap_or(0) as c_int + } +} + +pub(crate) unsafe extern "C" fn hook_proc(state: *mut lua_State, ar: *mut lua_Debug) { + callback_error(state, |_| { + let debug = Debug { + ar, + state, + _phantom: PhantomData, + }; + + let lua = Lua::make_from_ptr(state); + let hook_cb = mlua_expect!(lua.hook_callback(), "no hook callback set in hook_proc"); + + #[allow(clippy::match_wild_err_arm)] + match hook_cb.try_borrow_mut() { + Ok(mut b) => (&mut *b)(&lua, debug), + Err(_) => mlua_panic!("Lua should not allow hooks to be called within another hook"), + }?; + + Ok(()) + }); +} + +unsafe fn ptr_to_str<'a>(input: *const c_char) -> Option<&'a [u8]> { + if input.is_null() { + None + } else { + Some(CStr::from_ptr(input).to_bytes()) + } +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/src/lib.rs b/third_party/cargo/vendor/mlua-0.5.3/src/lib.rs new file mode 100644 index 0000000..1fcbf3c --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/src/lib.rs @@ -0,0 +1,133 @@ +//! # High-level bindings to Lua +//! +//! The `mlua` crate provides safe high-level bindings to the [Lua programming language]. +//! +//! # The `Lua` object +//! +//! The main type exported by this library is the [`Lua`] struct. In addition to methods for +//! [executing] Lua chunks or [evaluating] Lua expressions, it provides methods for creating Lua +//! values and accessing the table of [globals]. +//! +//! # Converting data +//! +//! The [`ToLua`] and [`FromLua`] traits allow conversion from Rust types to Lua values and vice +//! versa. They are implemented for many data structures found in Rust's standard library. +//! +//! For more general conversions, the [`ToLuaMulti`] and [`FromLuaMulti`] traits allow converting +//! between Rust types and *any number* of Lua values. +//! +//! Most code in `mlua` is generic over implementors of those traits, so in most places the normal +//! Rust data structures are accepted without having to write any boilerplate. +//! +//! # Custom Userdata +//! +//! The [`UserData`] trait can be implemented by user-defined types to make them available to Lua. +//! Methods and operators to be used from Lua can be added using the [`UserDataMethods`] API. +//! +//! # Serde support +//! +//! The [`LuaSerdeExt`] trait implemented for [`Lua`] allows conversion from Rust types to Lua values +//! and vice versa using serde. Any user defined data type that implements [`serde::Serialize`] or +//! [`serde::Deserialize`] can be converted. +//! For convenience, additional functionality to handle `NULL` values and arrays is provided. +//! +//! The [`Value`] enum implements [`serde::Serialize`] trait to support serializing Lua values +//! (including [`UserData`]) into Rust values. +//! +//! Requires `feature = "serialize"`. +//! +//! # Async/await support +//! +//! The [`create_async_function`] allows creating non-blocking functions that returns [`Future`]. +//! Lua code with async capabilities can be executed by [`call_async`] family of functions or polling +//! [`AsyncThread`] using any runtime (eg. Tokio). +//! +//! Requires `feature = "async"`. +//! +//! # `Send` requirement +//! By default `mlua` is `!Send`. This can be changed by enabling `feature = "send"` that adds `Send` requirement +//! to [`Function`]s and [`UserData`]. +//! +//! [Lua programming language]: https://www.lua.org/ +//! [`Lua`]: struct.Lua.html +//! [executing]: struct.Lua.html#method.exec +//! [evaluating]: struct.Lua.html#method.eval +//! [globals]: struct.Lua.html#method.globals +//! [`ToLua`]: trait.ToLua.html +//! [`FromLua`]: trait.FromLua.html +//! [`ToLuaMulti`]: trait.ToLuaMulti.html +//! [`FromLuaMulti`]: trait.FromLuaMulti.html +//! [`Function`]: struct.Function.html +//! [`UserData`]: trait.UserData.html +//! [`UserDataMethods`]: trait.UserDataMethods.html +//! [`LuaSerdeExt`]: serde/trait.LuaSerdeExt.html +//! [`Value`]: enum.Value.html +//! [`create_async_function`]: struct.Lua.html#method.create_async_function +//! [`call_async`]: struct.Function.html#method.call_async +//! [`AsyncThread`]: struct.AsyncThread.html +//! [`Future`]: ../futures_core/future/trait.Future.html +//! [`serde::Serialize`]: https://docs.serde.rs/serde/ser/trait.Serialize.html +//! [`serde::Deserialize`]: https://docs.serde.rs/serde/de/trait.Deserialize.html + +// mlua types in rustdoc of other crates get linked to here. +#![doc(html_root_url = "https://docs.rs/mlua/0.5.3")] +// Deny warnings inside doc tests / examples. When this isn't present, rustdoc doesn't show *any* +// warnings at all. +#![doc(test(attr(deny(warnings))))] +#![cfg_attr(docsrs, feature(doc_cfg))] + +#[macro_use] +mod macros; + +mod conversion; +mod error; +mod ffi; +mod function; +mod hook; +mod lua; +mod multi; +mod scope; +mod stdlib; +mod string; +mod table; +mod thread; +mod types; +mod userdata; +mod util; +mod value; + +pub use crate::ffi::lua_State; + +pub use crate::error::{Error, ExternalError, ExternalResult, Result}; +pub use crate::function::Function; +pub use crate::hook::{Debug, DebugNames, DebugSource, DebugStack, HookTriggers}; +pub use crate::lua::{Chunk, ChunkMode, GCMode, Lua}; +pub use crate::multi::Variadic; +pub use crate::scope::Scope; +pub use crate::stdlib::StdLib; +pub use crate::string::String; +pub use crate::table::{Table, TableExt, TablePairs, TableSequence}; +pub use crate::thread::{Thread, ThreadStatus}; +pub use crate::types::{Integer, LightUserData, Number, RegistryKey}; +pub use crate::userdata::{AnyUserData, MetaMethod, UserData, UserDataMethods}; +pub use crate::value::{FromLua, FromLuaMulti, MultiValue, Nil, ToLua, ToLuaMulti, Value}; + +#[cfg(feature = "async")] +pub use crate::thread::AsyncThread; + +#[cfg(feature = "serialize")] +pub use crate::serde::LuaSerdeExt; + +pub mod prelude; +#[cfg(feature = "serialize")] +#[cfg_attr(docsrs, doc(cfg(feature = "serialize")))] +pub mod serde; + +// Re-export #[mlua_derive::lua_module]. +#[cfg(feature = "mlua_derive")] +#[allow(unused_imports)] +#[macro_use] +extern crate mlua_derive; +#[cfg(feature = "mlua_derive")] +#[doc(hidden)] +pub use mlua_derive::*; diff --git a/third_party/cargo/vendor/mlua-0.5.3/src/lua.rs b/third_party/cargo/vendor/mlua-0.5.3/src/lua.rs new file mode 100644 index 0000000..9e94e19 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/src/lua.rs @@ -0,0 +1,2445 @@ +use std::any::TypeId; +use std::cell::{RefCell, UnsafeCell}; +use std::collections::HashMap; +use std::ffi::CString; +use std::marker::PhantomData; +use std::os::raw::{c_char, c_int, c_void}; +use std::sync::{Arc, Mutex, Weak}; +use std::{mem, ptr, str}; + +use crate::error::{Error, Result}; +use crate::ffi; +use crate::function::Function; +use crate::hook::{hook_proc, Debug, HookTriggers}; +use crate::scope::Scope; +use crate::stdlib::StdLib; +use crate::string::String; +use crate::table::Table; +use crate::thread::Thread; +use crate::types::{ + Callback, HookCallback, Integer, LightUserData, LuaRef, MaybeSend, Number, RegistryKey, + UserDataCell, +}; +use crate::userdata::{AnyUserData, MetaMethod, UserData, UserDataMethods, UserDataWrapped}; +use crate::util::{ + assert_stack, callback_error, check_stack, get_gc_userdata, get_main_state, get_userdata, + get_wrapped_error, init_error_registry, init_gc_metatable_for, init_userdata_metatable, + pop_error, protect_lua, protect_lua_closure, push_gc_userdata, push_meta_gc_userdata, + push_string, push_userdata, push_wrapped_error, StackGuard, +}; +use crate::value::{FromLua, FromLuaMulti, MultiValue, Nil, ToLua, ToLuaMulti, Value}; + +#[cfg(feature = "async")] +use { + crate::types::AsyncCallback, + futures_core::{ + future::{Future, LocalBoxFuture}, + task::{Context, Poll, Waker}, + }, + futures_task::noop_waker, + futures_util::future::{self, TryFutureExt}, +}; + +#[cfg(feature = "serialize")] +use {crate::util::get_destructed_userdata_metatable, serde::Serialize}; + +/// Top level Lua struct which holds the Lua state itself. +pub struct Lua { + pub(crate) state: *mut ffi::lua_State, + main_state: Option<*mut ffi::lua_State>, + extra: Arc>, + ephemeral: bool, + safe: bool, + // Lua has lots of interior mutability, should not be RefUnwindSafe + _no_ref_unwind_safe: PhantomData>, +} + +// Data associated with the lua_State. +struct ExtraData { + registered_userdata: HashMap, + registry_unref_list: Arc>>>, + + libs: StdLib, + mem_info: *mut MemoryInfo, + + ref_thread: *mut ffi::lua_State, + ref_stack_size: c_int, + ref_stack_max: c_int, + ref_free: Vec, + + hook_callback: Option, +} + +#[cfg_attr(any(feature = "lua51", feature = "luajit"), allow(dead_code))] +struct MemoryInfo { + used_memory: isize, + memory_limit: isize, +} + +/// Mode of the Lua garbage collector (GC). +/// +/// In Lua 5.4 GC can work in two modes: incremental and generational. +/// Previous Lua versions support only incremental GC. +/// +/// More information can be found in the Lua 5.x [documentation][lua_doc]. +/// +/// [lua_doc]: https://www.lua.org/manual/5.4/manual.html#2.5 +pub enum GCMode { + Incremental, + /// Requires `feature = "lua54"` + #[cfg(any(feature = "lua54", doc))] + Generational, +} + +#[cfg(feature = "async")] +pub(crate) struct AsyncPollPending; +#[cfg(feature = "async")] +pub(crate) static WAKER_REGISTRY_KEY: u8 = 0; +pub(crate) static EXTRA_REGISTRY_KEY: u8 = 0; + +/// Requires `feature = "send"` +#[cfg(feature = "send")] +#[cfg_attr(docsrs, doc(cfg(feature = "send")))] +unsafe impl Send for Lua {} + +impl Drop for Lua { + fn drop(&mut self) { + unsafe { + if !self.ephemeral { + let extra = mlua_expect!(self.extra.lock(), "extra is poisoned"); + mlua_debug_assert!( + ffi::lua_gettop(extra.ref_thread) == extra.ref_stack_max + && extra.ref_stack_max as usize == extra.ref_free.len(), + "reference leak detected" + ); + let mut unref_list = + mlua_expect!(extra.registry_unref_list.lock(), "unref list poisoned"); + *unref_list = None; + ffi::lua_close(self.main_state.expect("main_state is null")); + if !extra.mem_info.is_null() { + Box::from_raw(extra.mem_info); + } + } + } + } +} + +impl Lua { + /// Creates a new Lua state and loads the safe subset of the standard libraries. + /// + /// # Safety + /// The created Lua state would have _some_ safety guarantees and would not allow to load unsafe + /// standard libraries or C modules. + #[allow(clippy::new_without_default)] + pub fn new() -> Lua { + mlua_expect!( + Self::new_with(StdLib::ALL_SAFE), + "can't create new safe Lua state" + ) + } + + /// Creates a new Lua state and loads all the standard libraries. + /// + /// # Safety + /// The created Lua state would not have safety guarantees and would allow to load C modules. + pub unsafe fn unsafe_new() -> Lua { + Self::unsafe_new_with(StdLib::ALL) + } + + /// Creates a new Lua state and loads the specified safe subset of the standard libraries. + /// + /// Use the [`StdLib`] flags to specifiy the libraries you want to load. + /// + /// # Safety + /// The created Lua state would have _some_ safety guarantees and would not allow to load unsafe + /// standard libraries or C modules. + /// + /// [`StdLib`]: struct.StdLib.html + pub fn new_with(libs: StdLib) -> Result { + if libs.contains(StdLib::DEBUG) { + return Err(Error::SafetyError( + "the unsafe `debug` module can't be loaded using safe `new_with`".to_string(), + )); + } + #[cfg(feature = "luajit")] + { + if libs.contains(StdLib::FFI) { + return Err(Error::SafetyError( + "the unsafe `ffi` module can't be loaded using safe `new_with`".to_string(), + )); + } + } + + let mut lua = unsafe { Self::unsafe_new_with(libs) }; + + if libs.contains(StdLib::PACKAGE) { + mlua_expect!(lua.disable_c_modules(), "Error during disabling C modules"); + } + lua.safe = true; + + Ok(lua) + } + + /// Creates a new Lua state and loads the specified subset of the standard libraries. + /// + /// Use the [`StdLib`] flags to specifiy the libraries you want to load. + /// + /// # Safety + /// The created Lua state would not have safety guarantees and would allow to load C modules. + /// + /// [`StdLib`]: struct.StdLib.html + pub unsafe fn unsafe_new_with(libs: StdLib) -> Lua { + #[cfg_attr(any(feature = "lua51", feature = "luajit"), allow(dead_code))] + unsafe extern "C" fn allocator( + extra_data: *mut c_void, + ptr: *mut c_void, + osize: usize, + nsize: usize, + ) -> *mut c_void { + use std::alloc; + + let mem_info = &mut *(extra_data as *mut MemoryInfo); + + if nsize == 0 { + // Free memory + if !ptr.is_null() { + let layout = + alloc::Layout::from_size_align_unchecked(osize, ffi::SYS_MIN_ALIGN); + alloc::dealloc(ptr as *mut u8, layout); + mem_info.used_memory -= osize as isize; + } + return ptr::null_mut(); + } + + // Are we fit to the memory limits? + let mut mem_diff = nsize as isize; + if !ptr.is_null() { + mem_diff -= osize as isize; + } + let new_used_memory = mem_info.used_memory + mem_diff; + if mem_info.memory_limit > 0 && new_used_memory > mem_info.memory_limit { + return ptr::null_mut(); + } + + let new_layout = alloc::Layout::from_size_align_unchecked(nsize, ffi::SYS_MIN_ALIGN); + + if ptr.is_null() { + // Allocate new memory + let new_ptr = alloc::alloc(new_layout) as *mut c_void; + if !new_ptr.is_null() { + mem_info.used_memory += mem_diff; + } + return new_ptr; + } + + // Reallocate memory + let old_layout = alloc::Layout::from_size_align_unchecked(osize, ffi::SYS_MIN_ALIGN); + let new_ptr = alloc::realloc(ptr as *mut u8, old_layout, nsize) as *mut c_void; + + if !new_ptr.is_null() { + mem_info.used_memory += mem_diff; + } else if !ptr.is_null() && nsize < osize { + // Should not happend + alloc::handle_alloc_error(new_layout); + } + + new_ptr + } + + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + let mem_info = Box::into_raw(Box::new(MemoryInfo { + used_memory: 0, + memory_limit: 0, + })); + + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + let state = ffi::lua_newstate(allocator, mem_info as *mut c_void); + #[cfg(any(feature = "lua51", feature = "luajit"))] + let state = ffi::luaL_newstate(); + + ffi::luaL_requiref(state, cstr!("_G"), ffi::luaopen_base, 1); + ffi::lua_pop(state, 1); + + let mut lua = Lua::init_from_ptr(state); + lua.ephemeral = false; + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + { + mlua_expect!(lua.extra.lock(), "extra is poisoned").mem_info = mem_info; + } + + mlua_expect!( + protect_lua_closure(lua.main_state.expect("main_state is null"), 0, 0, |state| { + load_from_std_lib(state, libs); + }), + "Error during loading standard libraries" + ); + mlua_expect!(lua.extra.lock(), "extra is poisoned").libs |= libs; + + lua + } + + /// Constructs a new Lua instance from an existing raw state. + #[allow(clippy::missing_safety_doc)] + pub unsafe fn init_from_ptr(state: *mut ffi::lua_State) -> Lua { + let maybe_main_state = get_main_state(state); + let main_state = maybe_main_state.unwrap_or(state); + let main_state_top = ffi::lua_gettop(main_state); + + let ref_thread = mlua_expect!( + protect_lua_closure(main_state, 0, 0, |state| { + init_error_registry(state); + + // Create the internal metatables and place them in the registry + // to prevent them from being garbage collected. + + init_gc_metatable_for::(state, None); + init_gc_metatable_for::(state, None); + init_gc_metatable_for::>>(state, None); + #[cfg(feature = "async")] + { + init_gc_metatable_for::(state, None); + init_gc_metatable_for::>>(state, None); + init_gc_metatable_for::(state, None); + init_gc_metatable_for::(state, None); + } + + // Init serde metatables + #[cfg(feature = "serialize")] + crate::serde::init_metatables(state); + + // Create ref stack thread and place it in the registry to prevent it from being garbage + // collected. + + let _ref_thread = ffi::lua_newthread(state); + ffi::luaL_ref(state, ffi::LUA_REGISTRYINDEX); + _ref_thread + }), + "Error during Lua construction", + ); + + // Create ExtraData + + let extra = Arc::new(Mutex::new(ExtraData { + registered_userdata: HashMap::new(), + registry_unref_list: Arc::new(Mutex::new(Some(Vec::new()))), + ref_thread, + libs: StdLib::NONE, + mem_info: ptr::null_mut(), + // We need 1 extra stack space to move values in and out of the ref stack. + ref_stack_size: ffi::LUA_MINSTACK - 1, + ref_stack_max: 0, + ref_free: Vec::new(), + hook_callback: None, + })); + + mlua_expect!( + push_gc_userdata(main_state, Arc::downgrade(&extra)), + "Error while storing extra data", + ); + mlua_expect!( + protect_lua_closure(main_state, 1, 0, |state| { + ffi::lua_rawsetp( + state, + ffi::LUA_REGISTRYINDEX, + &EXTRA_REGISTRY_KEY as *const u8 as *mut c_void, + ); + }), + "Error while storing extra data" + ); + + mlua_debug_assert!( + ffi::lua_gettop(main_state) == main_state_top, + "stack leak during creation" + ); + assert_stack(main_state, ffi::LUA_MINSTACK); + + Lua { + state, + main_state: maybe_main_state, + extra, + ephemeral: true, + safe: false, + _no_ref_unwind_safe: PhantomData, + } + } + + /// Loads the specified subset of the standard libraries into an existing Lua state. + /// + /// Use the [`StdLib`] flags to specifiy the libraries you want to load. + /// + /// [`StdLib`]: struct.StdLib.html + pub fn load_from_std_lib(&self, libs: StdLib) -> Result<()> { + if self.safe && libs.contains(StdLib::DEBUG) { + return Err(Error::SafetyError( + "the unsafe `debug` module can't be loaded in safe mode".to_string(), + )); + } + #[cfg(feature = "luajit")] + { + if self.safe && libs.contains(StdLib::FFI) { + return Err(Error::SafetyError( + "the unsafe `ffi` module can't be loaded in safe mode".to_string(), + )); + } + } + + let state = self.main_state.unwrap_or(self.state); + let res = unsafe { + protect_lua_closure(state, 0, 0, |state| { + load_from_std_lib(state, libs); + }) + }; + + // If `package` library loaded into a safe lua state then disable C modules + let curr_libs = mlua_expect!(self.extra.lock(), "extra is poisoned").libs; + if self.safe && (curr_libs ^ (curr_libs | libs)).contains(StdLib::PACKAGE) { + mlua_expect!(self.disable_c_modules(), "Error during disabling C modules"); + } + mlua_expect!(self.extra.lock(), "extra is poisoned").libs |= libs; + + res + } + + /// Consumes and leaks `Lua` object, returning a static reference `&'static Lua`. + /// + /// This function is useful when the `Lua` object is supposed to live for the remainder + /// of the program's life. + /// In particular in asynchronous context this will allow to spawn Lua tasks to execute + /// in background. + /// + /// Dropping the returned reference will cause a memory leak. If this is not acceptable, + /// the reference should first be wrapped with the [`Lua::from_static`] function producing a `Lua`. + /// This `Lua` object can then be dropped which will properly release the allocated memory. + /// + /// [`Lua::from_static`]: #method.from_static + pub fn into_static(self) -> &'static Self { + Box::leak(Box::new(self)) + } + + /// Constructs a `Lua` from a static reference to it. + /// + /// # Safety + /// This function is unsafe because improper use may lead to memory problems or undefined behavior. + pub unsafe fn from_static(lua: &'static Lua) -> Self { + *Box::from_raw(lua as *const Lua as *mut Lua) + } + + // Executes module entrypoint function, which returns only one Value. + // The returned value then pushed to the Lua stack. + #[doc(hidden)] + pub fn entrypoint1<'lua, 'callback, R, F>(&'lua self, func: F) -> Result + where + 'lua: 'callback, + R: ToLua<'callback>, + F: 'static + MaybeSend + Fn(&'callback Lua) -> Result, + { + let cb = self.create_callback(Box::new(move |lua, _| func(lua)?.to_lua_multi(lua)))?; + unsafe { self.push_value(cb.call(())?).map(|_| 1) } + } + + /// Sets a 'hook' function that will periodically be called as Lua code executes. + /// + /// When exactly the hook function is called depends on the contents of the `triggers` + /// parameter, see [`HookTriggers`] for more details. + /// + /// The provided hook function can error, and this error will be propagated through the Lua code + /// that was executing at the time the hook was triggered. This can be used to implement a + /// limited form of execution limits by setting [`HookTriggers.every_nth_instruction`] and + /// erroring once an instruction limit has been reached. + /// + /// # Example + /// + /// Shows each line number of code being executed by the Lua interpreter. + /// + /// ``` + /// # use mlua::{Lua, HookTriggers, Result}; + /// # fn main() -> Result<()> { + /// let lua = Lua::new(); + /// lua.set_hook(HookTriggers { + /// every_line: true, ..Default::default() + /// }, |_lua, debug| { + /// println!("line {}", debug.curr_line()); + /// Ok(()) + /// })?; + /// + /// lua.load(r#" + /// local x = 2 + 3 + /// local y = x * 63 + /// local z = string.len(x..", "..y) + /// "#).exec() + /// # } + /// ``` + /// + /// [`HookTriggers`]: struct.HookTriggers.html + /// [`HookTriggers.every_nth_instruction`]: struct.HookTriggers.html#field.every_nth_instruction + pub fn set_hook(&self, triggers: HookTriggers, callback: F) -> Result<()> + where + F: 'static + MaybeSend + FnMut(&Lua, Debug) -> Result<()>, + { + let state = self.main_state.ok_or(Error::MainThreadNotAvailable)?; + unsafe { + let mut extra = mlua_expect!(self.extra.lock(), "extra is poisoned"); + extra.hook_callback = Some(Arc::new(RefCell::new(callback))); + ffi::lua_sethook(state, Some(hook_proc), triggers.mask(), triggers.count()); + } + Ok(()) + } + + /// Remove any hook previously set by `set_hook`. This function has no effect if a hook was not + /// previously set. + pub fn remove_hook(&self) { + // If main_state is not available, then sethook wasn't called. + let state = match self.main_state { + Some(state) => state, + None => return, + }; + let mut extra = mlua_expect!(self.extra.lock(), "extra is poisoned"); + unsafe { + extra.hook_callback = None; + ffi::lua_sethook(state, None, 0, 0); + } + } + + /// Returns the amount of memory (in bytes) currently used inside this Lua state. + pub fn used_memory(&self) -> usize { + let extra = mlua_expect!(self.extra.lock(), "extra is poisoned"); + let state = self.main_state.unwrap_or(self.state); + if extra.mem_info.is_null() { + // Get data from the Lua GC + unsafe { + let used_kbytes = ffi::lua_gc(state, ffi::LUA_GCCOUNT, 0); + let used_kbytes_rem = ffi::lua_gc(state, ffi::LUA_GCCOUNTB, 0); + return (used_kbytes as usize) * 1024 + (used_kbytes_rem as usize); + } + } + unsafe { (*extra.mem_info).used_memory as usize } + } + + /// Sets a memory limit (in bytes) on this Lua state. + /// + /// Once an allocation occurs that would pass this memory limit, + /// a `Error::MemoryError` is generated instead. + /// Returns previous limit (zero means no limit). + /// + /// Does not work on module mode where Lua state is managed externally. + /// + /// Requires `feature = "lua54/lua53/lua52"` + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52", doc))] + pub fn set_memory_limit(&self, memory_limit: usize) -> Result { + let mut extra = mlua_expect!(self.extra.lock(), "extra is poisoned"); + if extra.mem_info.is_null() { + return Err(Error::MemoryLimitNotAvailable); + } + unsafe { + let prev_limit = (*extra.mem_info).memory_limit as usize; + (*extra.mem_info).memory_limit = memory_limit as isize; + Ok(prev_limit) + } + } + + /// Returns true if the garbage collector is currently running automatically. + /// + /// Requires `feature = "lua54/lua53/lua52"` + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52", doc))] + pub fn gc_is_running(&self) -> bool { + let state = self.main_state.unwrap_or(self.state); + unsafe { ffi::lua_gc(state, ffi::LUA_GCISRUNNING, 0) != 0 } + } + + /// Stop the Lua GC from running + pub fn gc_stop(&self) { + let state = self.main_state.unwrap_or(self.state); + unsafe { ffi::lua_gc(state, ffi::LUA_GCSTOP, 0) }; + } + + /// Restarts the Lua GC if it is not running + pub fn gc_restart(&self) { + let state = self.main_state.unwrap_or(self.state); + unsafe { ffi::lua_gc(state, ffi::LUA_GCRESTART, 0) }; + } + + /// Perform a full garbage-collection cycle. + /// + /// It may be necessary to call this function twice to collect all currently unreachable + /// objects. Once to finish the current gc cycle, and once to start and finish the next cycle. + pub fn gc_collect(&self) -> Result<()> { + let state = self.main_state.unwrap_or(self.state); + unsafe { + protect_lua_closure(state, 0, 0, |state| { + ffi::lua_gc(state, ffi::LUA_GCCOLLECT, 0); + }) + } + } + + /// Steps the garbage collector one indivisible step. + /// + /// Returns true if this has finished a collection cycle. + pub fn gc_step(&self) -> Result { + self.gc_step_kbytes(0) + } + + /// Steps the garbage collector as though memory had been allocated. + /// + /// if `kbytes` is 0, then this is the same as calling `gc_step`. Returns true if this step has + /// finished a collection cycle. + pub fn gc_step_kbytes(&self, kbytes: c_int) -> Result { + let state = self.main_state.unwrap_or(self.state); + unsafe { + protect_lua_closure(state, 0, 0, |state| { + ffi::lua_gc(state, ffi::LUA_GCSTEP, kbytes) != 0 + }) + } + } + + /// Sets the 'pause' value of the collector. + /// + /// Returns the previous value of 'pause'. More information can be found in the [Lua 5.3 + /// documentation][lua_doc]. + /// + /// [lua_doc]: https://www.lua.org/manual/5.3/manual.html#2.5 + pub fn gc_set_pause(&self, pause: c_int) -> c_int { + let state = self.main_state.unwrap_or(self.state); + unsafe { ffi::lua_gc(state, ffi::LUA_GCSETPAUSE, pause) } + } + + /// Sets the 'step multiplier' value of the collector. + /// + /// Returns the previous value of the 'step multiplier'. More information can be found in the + /// Lua 5.x [documentation][lua_doc]. + /// + /// [lua_doc]: https://www.lua.org/manual/5.3/manual.html#2.5 + pub fn gc_set_step_multiplier(&self, step_multiplier: c_int) -> c_int { + let state = self.main_state.unwrap_or(self.state); + unsafe { ffi::lua_gc(state, ffi::LUA_GCSETSTEPMUL, step_multiplier) } + } + + /// Changes the collector to incremental mode with the given parameters. + /// + /// Returns the previous mode (always `GCMode::Incremental` in Lua < 5.4). + /// More information can be found in the Lua 5.x [documentation][lua_doc]. + /// + /// [lua_doc]: https://www.lua.org/manual/5.4/manual.html#2.5.1 + pub fn gc_inc(&self, pause: c_int, step_multiplier: c_int, step_size: c_int) -> GCMode { + let state = self.main_state.unwrap_or(self.state); + + #[cfg(any( + feature = "lua53", + feature = "lua52", + feature = "lua51", + feature = "luajit" + ))] + { + if pause > 0 { + unsafe { ffi::lua_gc(state, ffi::LUA_GCSETPAUSE, pause) }; + } + if step_multiplier > 0 { + unsafe { ffi::lua_gc(state, ffi::LUA_GCSETSTEPMUL, step_multiplier) }; + } + let _ = step_size; // Ignored + GCMode::Incremental + } + + #[cfg(feature = "lua54")] + let prev_mode = unsafe { + ffi::lua_gc( + state, + ffi::LUA_GCSETPAUSE, + pause, + step_multiplier, + step_size, + ) + }; + #[cfg(feature = "lua54")] + match prev_mode { + ffi::LUA_GCINC => GCMode::Incremental, + ffi::LUA_GCGEN => GCMode::Generational, + _ => unreachable!(), + } + } + + /// Changes the collector to generational mode with the given parameters. + /// + /// Returns the previous mode. More information about the generational GC + /// can be found in the Lua 5.4 [documentation][lua_doc]. + /// + /// Requires `feature = "lua54"` + /// + /// [lua_doc]: https://www.lua.org/manual/5.4/manual.html#2.5.2 + #[cfg(any(feature = "lua54", doc))] + pub fn gc_gen(&self, minor_multiplier: c_int, major_multiplier: c_int) -> GCMode { + let state = self.main_state.unwrap_or(self.state); + let prev_mode = + unsafe { ffi::lua_gc(state, ffi::LUA_GCGEN, minor_multiplier, major_multiplier) }; + match prev_mode { + ffi::LUA_GCGEN => GCMode::Generational, + ffi::LUA_GCINC => GCMode::Incremental, + _ => unreachable!(), + } + } + + /// Returns Lua source code as a `Chunk` builder type. + /// + /// In order to actually compile or run the resulting code, you must call [`Chunk::exec`] or + /// similar on the returned builder. Code is not even parsed until one of these methods is + /// called. + /// + /// If this `Lua` was created with `unsafe_new`, `load` will automatically detect and load + /// chunks of either text or binary type, as if passing `bt` mode to `luaL_loadbufferx`. + /// + /// [`Chunk::exec`]: struct.Chunk.html#method.exec + pub fn load<'lua, 'a, S>(&'lua self, source: &'a S) -> Chunk<'lua, 'a> + where + S: ?Sized + AsRef<[u8]>, + { + Chunk { + lua: self, + source: source.as_ref(), + name: None, + env: None, + mode: None, + } + } + + fn load_chunk<'lua>( + &'lua self, + source: &[u8], + name: Option<&CString>, + env: Option>, + mode: Option, + ) -> Result> { + unsafe { + let _sg = StackGuard::new(self.state); + assert_stack(self.state, 1); + + let mode_str = match mode { + Some(ChunkMode::Binary) if self.safe => { + return Err(Error::SafetyError( + "binary chunks are disabled in safe mode".to_string(), + )) + } + Some(ChunkMode::Binary) => cstr!("b"), + Some(ChunkMode::Text) => cstr!("t"), + None if source.starts_with(ffi::LUA_SIGNATURE) && self.safe => { + return Err(Error::SafetyError( + "binary chunks are disabled in safe mode".to_string(), + )) + } + None => cstr!("bt"), + }; + + match ffi::luaL_loadbufferx( + self.state, + source.as_ptr() as *const c_char, + source.len(), + name.map(|n| n.as_ptr()).unwrap_or_else(ptr::null), + mode_str, + ) { + ffi::LUA_OK => { + if let Some(env) = env { + self.push_value(env)?; + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + ffi::lua_setupvalue(self.state, -2, 1); + #[cfg(any(feature = "lua51", feature = "luajit"))] + ffi::lua_setfenv(self.state, -2); + } + Ok(Function(self.pop_ref())) + } + err => Err(pop_error(self.state, err)), + } + } + } + + /// Create and return an interned Lua string. Lua strings can be arbitrary [u8] data including + /// embedded nulls, so in addition to `&str` and `&String`, you can also pass plain `&[u8]` + /// here. + pub fn create_string(&self, s: &S) -> Result + where + S: ?Sized + AsRef<[u8]>, + { + unsafe { + let _sg = StackGuard::new(self.state); + assert_stack(self.state, 4); + push_string(self.state, s)?; + Ok(String(self.pop_ref())) + } + } + + /// Creates and returns a new empty table. + pub fn create_table(&self) -> Result
{ + unsafe { + let _sg = StackGuard::new(self.state); + assert_stack(self.state, 3); + unsafe extern "C" fn new_table(state: *mut ffi::lua_State) -> c_int { + ffi::lua_newtable(state); + 1 + } + protect_lua(self.state, 0, new_table)?; + Ok(Table(self.pop_ref())) + } + } + + /// Creates and returns a new empty table, with the specified capacity. + /// `narr` is a hint for how many elements the table will have as a sequence; + /// `nrec` is a hint for how many other elements the table will have. + /// Lua may use these hints to preallocate memory for the new table. + pub fn create_table_with_capacity(&self, narr: c_int, nrec: c_int) -> Result
{ + unsafe { + let _sg = StackGuard::new(self.state); + assert_stack(self.state, 4); + protect_lua_closure(self.state, 0, 1, |state| { + ffi::lua_createtable(state, narr, nrec) + })?; + Ok(Table(self.pop_ref())) + } + } + + /// Creates a table and fills it with values from an iterator. + pub fn create_table_from<'lua, K, V, I>(&'lua self, cont: I) -> Result> + where + K: ToLua<'lua>, + V: ToLua<'lua>, + I: IntoIterator, + { + unsafe { + let _sg = StackGuard::new(self.state); + // `Lua` instance assumes that on any callback, the Lua stack has at least LUA_MINSTACK + // slots available to avoid panics. + check_stack(self.state, 5 + ffi::LUA_MINSTACK)?; + + unsafe extern "C" fn new_table(state: *mut ffi::lua_State) -> c_int { + ffi::lua_newtable(state); + 1 + } + protect_lua(self.state, 0, new_table)?; + + for (k, v) in cont { + self.push_value(k.to_lua(self)?)?; + self.push_value(v.to_lua(self)?)?; + unsafe extern "C" fn raw_set(state: *mut ffi::lua_State) -> c_int { + ffi::lua_rawset(state, -3); + 1 + } + protect_lua(self.state, 3, raw_set)?; + } + Ok(Table(self.pop_ref())) + } + } + + /// Creates a table from an iterator of values, using `1..` as the keys. + pub fn create_sequence_from<'lua, T, I>(&'lua self, cont: I) -> Result> + where + T: ToLua<'lua>, + I: IntoIterator, + { + self.create_table_from(cont.into_iter().enumerate().map(|(k, v)| (k + 1, v))) + } + + /// Wraps a Rust function or closure, creating a callable Lua function handle to it. + /// + /// The function's return value is always a `Result`: If the function returns `Err`, the error + /// is raised as a Lua error, which can be caught using `(x)pcall` or bubble up to the Rust code + /// that invoked the Lua code. This allows using the `?` operator to propagate errors through + /// intermediate Lua code. + /// + /// If the function returns `Ok`, the contained value will be converted to one or more Lua + /// values. For details on Rust-to-Lua conversions, refer to the [`ToLua`] and [`ToLuaMulti`] + /// traits. + /// + /// # Examples + /// + /// Create a function which prints its argument: + /// + /// ``` + /// # use mlua::{Lua, Result}; + /// # fn main() -> Result<()> { + /// # let lua = Lua::new(); + /// let greet = lua.create_function(|_, name: String| { + /// println!("Hello, {}!", name); + /// Ok(()) + /// }); + /// # let _ = greet; // used + /// # Ok(()) + /// # } + /// ``` + /// + /// Use tuples to accept multiple arguments: + /// + /// ``` + /// # use mlua::{Lua, Result}; + /// # fn main() -> Result<()> { + /// # let lua = Lua::new(); + /// let print_person = lua.create_function(|_, (name, age): (String, u8)| { + /// println!("{} is {} years old!", name, age); + /// Ok(()) + /// }); + /// # let _ = print_person; // used + /// # Ok(()) + /// # } + /// ``` + /// + /// [`ToLua`]: trait.ToLua.html + /// [`ToLuaMulti`]: trait.ToLuaMulti.html + pub fn create_function<'lua, 'callback, A, R, F>(&'lua self, func: F) -> Result> + where + 'lua: 'callback, + A: FromLuaMulti<'callback>, + R: ToLuaMulti<'callback>, + F: 'static + MaybeSend + Fn(&'callback Lua, A) -> Result, + { + self.create_callback(Box::new(move |lua, args| { + func(lua, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua) + })) + } + + /// Wraps a Rust mutable closure, creating a callable Lua function handle to it. + /// + /// This is a version of [`create_function`] that accepts a FnMut argument. Refer to + /// [`create_function`] for more information about the implementation. + /// + /// [`create_function`]: #method.create_function + pub fn create_function_mut<'lua, 'callback, A, R, F>( + &'lua self, + func: F, + ) -> Result> + where + 'lua: 'callback, + A: FromLuaMulti<'callback>, + R: ToLuaMulti<'callback>, + F: 'static + MaybeSend + FnMut(&'callback Lua, A) -> Result, + { + let func = RefCell::new(func); + self.create_function(move |lua, args| { + (&mut *func + .try_borrow_mut() + .map_err(|_| Error::RecursiveMutCallback)?)(lua, args) + }) + } + + /// Wraps a Rust async function or closure, creating a callable Lua function handle to it. + /// + /// While executing the function Rust will poll Future and if the result is not ready, call + /// `yield()` passing internal representation of a `Poll::Pending` value. + /// + /// The function must be called inside Lua coroutine ([`Thread`]) to be able to suspend its execution. + /// An executor should be used to poll [`AsyncThread`] and mlua will take a provided Waker + /// in that case. Otherwise noop waker will be used if try to call the function outside of Rust + /// executors. + /// + /// The family of `call_async()` functions takes care about creating [`Thread`]. + /// + /// Requires `feature = "async"` + /// + /// # Examples + /// + /// Non blocking sleep: + /// + /// ``` + /// use std::time::Duration; + /// use futures_timer::Delay; + /// use mlua::{Lua, Result}; + /// + /// async fn sleep(_lua: &Lua, n: u64) -> Result<&'static str> { + /// Delay::new(Duration::from_millis(n)).await; + /// Ok("done") + /// } + /// + /// #[tokio::main] + /// async fn main() -> Result<()> { + /// let lua = Lua::new(); + /// lua.globals().set("sleep", lua.create_async_function(sleep)?)?; + /// let res: String = lua.load("return sleep(...)").call_async(100).await?; // Sleep 100ms + /// assert_eq!(res, "done"); + /// Ok(()) + /// } + /// ``` + /// + /// [`Thread`]: struct.Thread.html + /// [`AsyncThread`]: struct.AsyncThread.html + #[cfg(feature = "async")] + #[cfg_attr(docsrs, doc(cfg(feature = "async")))] + pub fn create_async_function<'lua, 'callback, A, R, F, FR>( + &'lua self, + func: F, + ) -> Result> + where + 'lua: 'callback, + A: FromLuaMulti<'callback>, + R: ToLuaMulti<'callback>, + F: 'static + MaybeSend + Fn(&'callback Lua, A) -> FR, + FR: 'lua + Future>, + { + self.create_async_callback(Box::new(move |lua, args| { + let args = match A::from_lua_multi(args, lua) { + Ok(args) => args, + Err(e) => return Box::pin(future::err(e)), + }; + Box::pin(func(lua, args).and_then(move |ret| future::ready(ret.to_lua_multi(lua)))) + })) + } + + /// Wraps a Lua function into a new thread (or coroutine). + /// + /// Equivalent to `coroutine.create`. + pub fn create_thread<'lua>(&'lua self, func: Function<'lua>) -> Result> { + unsafe { + let _sg = StackGuard::new(self.state); + assert_stack(self.state, 2); + + let thread_state = + protect_lua_closure(self.state, 0, 1, |state| ffi::lua_newthread(state))?; + self.push_ref(&func.0); + ffi::lua_xmove(self.state, thread_state, 1); + + Ok(Thread(self.pop_ref())) + } + } + + /// Create a Lua userdata object from a custom userdata type. + pub fn create_userdata(&self, data: T) -> Result + where + T: 'static + MaybeSend + UserData, + { + unsafe { self.make_userdata(UserDataWrapped::new(data)) } + } + + /// Create a Lua userdata object from a custom serializable userdata type. + /// + /// Requires `feature = "serialize"` + #[cfg(feature = "serialize")] + #[cfg_attr(docsrs, doc(cfg(feature = "serialize")))] + pub fn create_ser_userdata(&self, data: T) -> Result + where + T: 'static + MaybeSend + UserData + Serialize, + { + unsafe { self.make_userdata(UserDataWrapped::new_ser(data)) } + } + + /// Returns a handle to the global environment. + pub fn globals(&self) -> Table { + unsafe { + let _sg = StackGuard::new(self.state); + assert_stack(self.state, 2); + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + ffi::lua_rawgeti(self.state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_GLOBALS); + #[cfg(any(feature = "lua51", feature = "luajit"))] + ffi::lua_pushvalue(self.state, ffi::LUA_GLOBALSINDEX); + Table(self.pop_ref()) + } + } + + /// Returns a handle to the active `Thread`. For calls to `Lua` this will be the main Lua thread, + /// for parameters given to a callback, this will be whatever Lua thread called the callback. + pub fn current_thread(&self) -> Thread { + unsafe { + ffi::lua_pushthread(self.state); + Thread(self.pop_ref()) + } + } + + /// Calls the given function with a `Scope` parameter, giving the function the ability to create + /// userdata and callbacks from rust types that are !Send or non-'static. + /// + /// The lifetime of any function or userdata created through `Scope` lasts only until the + /// completion of this method call, on completion all such created values are automatically + /// dropped and Lua references to them are invalidated. If a script accesses a value created + /// through `Scope` outside of this method, a Lua error will result. Since we can ensure the + /// lifetime of values created through `Scope`, and we know that `Lua` cannot be sent to another + /// thread while `Scope` is live, it is safe to allow !Send datatypes and whose lifetimes only + /// outlive the scope lifetime. + /// + /// Inside the scope callback, all handles created through Scope will share the same unique 'lua + /// lifetime of the parent `Lua`. This allows scoped and non-scoped values to be mixed in + /// API calls, which is very useful (e.g. passing a scoped userdata to a non-scoped function). + /// However, this also enables handles to scoped values to be trivially leaked from the given + /// callback. This is not dangerous, though! After the callback returns, all scoped values are + /// invalidated, which means that though references may exist, the Rust types backing them have + /// dropped. `Function` types will error when called, and `AnyUserData` will be typeless. It + /// would be impossible to prevent handles to scoped values from escaping anyway, since you + /// would always be able to smuggle them through Lua state. + pub fn scope<'lua, 'scope, R, F>(&'lua self, f: F) -> Result + where + 'lua: 'scope, + R: 'static, + F: FnOnce(&Scope<'lua, 'scope>) -> Result, + { + f(&Scope::new(self)) + } + + /// An asynchronous version of [`scope`] that allows to create scoped async functions and + /// execute them. + /// + /// Requires `feature = "async"` + /// + /// [`scope`]: #method.scope + #[cfg(feature = "async")] + #[cfg_attr(docsrs, doc(cfg(feature = "async")))] + pub fn async_scope<'lua, 'scope, R, F, FR>( + &'lua self, + f: F, + ) -> LocalBoxFuture<'scope, Result> + where + 'lua: 'scope, + R: 'static, + F: FnOnce(Scope<'lua, 'scope>) -> FR, + FR: 'scope + Future>, + { + Box::pin(f(Scope::new(self))) + } + + /// Attempts to coerce a Lua value into a String in a manner consistent with Lua's internal + /// behavior. + /// + /// To succeed, the value must be a string (in which case this is a no-op), an integer, or a + /// number. + pub fn coerce_string<'lua>(&'lua self, v: Value<'lua>) -> Result>> { + Ok(match v { + Value::String(s) => Some(s), + v => unsafe { + let _sg = StackGuard::new(self.state); + assert_stack(self.state, 4); + + self.push_value(v)?; + let ok = protect_lua_closure(self.state, 1, 1, |state| { + !ffi::lua_tostring(state, -1).is_null() + })?; + if ok { + Some(String(self.pop_ref())) + } else { + None + } + }, + }) + } + + /// Attempts to coerce a Lua value into an integer in a manner consistent with Lua's internal + /// behavior. + /// + /// To succeed, the value must be an integer, a floating point number that has an exact + /// representation as an integer, or a string that can be converted to an integer. Refer to the + /// Lua manual for details. + pub fn coerce_integer(&self, v: Value) -> Result> { + Ok(match v { + Value::Integer(i) => Some(i), + v => unsafe { + let _sg = StackGuard::new(self.state); + assert_stack(self.state, 2); + + self.push_value(v)?; + let mut isint = 0; + let i = ffi::lua_tointegerx(self.state, -1, &mut isint); + if isint == 0 { + None + } else { + Some(i) + } + }, + }) + } + + /// Attempts to coerce a Lua value into a Number in a manner consistent with Lua's internal + /// behavior. + /// + /// To succeed, the value must be a number or a string that can be converted to a number. Refer + /// to the Lua manual for details. + pub fn coerce_number(&self, v: Value) -> Result> { + Ok(match v { + Value::Number(n) => Some(n), + v => unsafe { + let _sg = StackGuard::new(self.state); + assert_stack(self.state, 2); + + self.push_value(v)?; + let mut isnum = 0; + let n = ffi::lua_tonumberx(self.state, -1, &mut isnum); + if isnum == 0 { + None + } else { + Some(n) + } + }, + }) + } + + /// Converts a value that implements `ToLua` into a `Value` instance. + pub fn pack<'lua, T: ToLua<'lua>>(&'lua self, t: T) -> Result> { + t.to_lua(self) + } + + /// Converts a `Value` instance into a value that implements `FromLua`. + pub fn unpack<'lua, T: FromLua<'lua>>(&'lua self, value: Value<'lua>) -> Result { + T::from_lua(value, self) + } + + /// Converts a value that implements `ToLuaMulti` into a `MultiValue` instance. + pub fn pack_multi<'lua, T: ToLuaMulti<'lua>>(&'lua self, t: T) -> Result> { + t.to_lua_multi(self) + } + + /// Converts a `MultiValue` instance into a value that implements `FromLuaMulti`. + pub fn unpack_multi<'lua, T: FromLuaMulti<'lua>>( + &'lua self, + value: MultiValue<'lua>, + ) -> Result { + T::from_lua_multi(value, self) + } + + /// Set a value in the Lua registry based on a string name. + /// + /// This value will be available to rust from all `Lua` instances which share the same main + /// state. + pub fn set_named_registry_value<'lua, S, T>(&'lua self, name: &S, t: T) -> Result<()> + where + S: ?Sized + AsRef<[u8]>, + T: ToLua<'lua>, + { + let t = t.to_lua(self)?; + unsafe { + let _sg = StackGuard::new(self.state); + assert_stack(self.state, 5); + + push_string(self.state, name)?; + self.push_value(t)?; + + unsafe extern "C" fn set_registry(state: *mut ffi::lua_State) -> c_int { + ffi::lua_rawset(state, ffi::LUA_REGISTRYINDEX); + 0 + } + protect_lua(self.state, 2, set_registry) + } + } + + /// Get a value from the Lua registry based on a string name. + /// + /// Any Lua instance which shares the underlying main state may call this method to + /// get a value previously set by [`set_named_registry_value`]. + /// + /// [`set_named_registry_value`]: #method.set_named_registry_value + pub fn named_registry_value<'lua, S, T>(&'lua self, name: &S) -> Result + where + S: ?Sized + AsRef<[u8]>, + T: FromLua<'lua>, + { + let value = unsafe { + let _sg = StackGuard::new(self.state); + assert_stack(self.state, 4); + + push_string(self.state, name)?; + unsafe extern "C" fn get_registry(state: *mut ffi::lua_State) -> c_int { + ffi::lua_rawget(state, ffi::LUA_REGISTRYINDEX); + 1 + } + protect_lua(self.state, 1, get_registry)?; + + self.pop_value() + }; + T::from_lua(value, self) + } + + /// Removes a named value in the Lua registry. + /// + /// Equivalent to calling [`set_named_registry_value`] with a value of Nil. + /// + /// [`set_named_registry_value`]: #method.set_named_registry_value + pub fn unset_named_registry_value(&self, name: &S) -> Result<()> + where + S: ?Sized + AsRef<[u8]>, + { + self.set_named_registry_value(name, Nil) + } + + /// Place a value in the Lua registry with an auto-generated key. + /// + /// This value will be available to rust from all `Lua` instances which share the same main + /// state. + /// + /// Be warned, garbage collection of values held inside the registry is not automatic, see + /// [`RegistryKey`] for more details. + /// + /// [`RegistryKey`]: struct.RegistryKey.html + pub fn create_registry_value<'lua, T: ToLua<'lua>>(&'lua self, t: T) -> Result { + let t = t.to_lua(self)?; + unsafe { + let _sg = StackGuard::new(self.state); + assert_stack(self.state, 2); + + self.push_value(t)?; + let registry_id = protect_lua_closure(self.state, 1, 0, |state| { + ffi::luaL_ref(state, ffi::LUA_REGISTRYINDEX) + })?; + + let extra = mlua_expect!(self.extra.lock(), "extra is poisoned"); + + Ok(RegistryKey { + registry_id, + unref_list: extra.registry_unref_list.clone(), + }) + } + } + + /// Get a value from the Lua registry by its `RegistryKey` + /// + /// Any Lua instance which shares the underlying main state may call this method to get a value + /// previously placed by [`create_registry_value`]. + /// + /// [`create_registry_value`]: #method.create_registry_value + pub fn registry_value<'lua, T: FromLua<'lua>>(&'lua self, key: &RegistryKey) -> Result { + let value = unsafe { + if !self.owns_registry_value(key) { + return Err(Error::MismatchedRegistryKey); + } + + let _sg = StackGuard::new(self.state); + assert_stack(self.state, 2); + + ffi::lua_rawgeti( + self.state, + ffi::LUA_REGISTRYINDEX, + key.registry_id as ffi::lua_Integer, + ); + self.pop_value() + }; + T::from_lua(value, self) + } + + /// Removes a value from the Lua registry. + /// + /// You may call this function to manually remove a value placed in the registry with + /// [`create_registry_value`]. In addition to manual `RegistryKey` removal, you can also call + /// [`expire_registry_values`] to automatically remove values from the registry whose + /// `RegistryKey`s have been dropped. + /// + /// [`create_registry_value`]: #method.create_registry_value + /// [`expire_registry_values`]: #method.expire_registry_values + pub fn remove_registry_value(&self, key: RegistryKey) -> Result<()> { + unsafe { + if !self.owns_registry_value(&key) { + return Err(Error::MismatchedRegistryKey); + } + + ffi::luaL_unref(self.state, ffi::LUA_REGISTRYINDEX, key.take()); + Ok(()) + } + } + + /// Returns true if the given `RegistryKey` was created by a `Lua` which shares the underlying + /// main state with this `Lua` instance. + /// + /// Other than this, methods that accept a `RegistryKey` will return + /// `Error::MismatchedRegistryKey` if passed a `RegistryKey` that was not created with a + /// matching `Lua` state. + pub fn owns_registry_value(&self, key: &RegistryKey) -> bool { + let extra = mlua_expect!(self.extra.lock(), "extra is poisoned"); + Arc::ptr_eq(&key.unref_list, &extra.registry_unref_list) + } + + /// Remove any registry values whose `RegistryKey`s have all been dropped. + /// + /// Unlike normal handle values, `RegistryKey`s do not automatically remove themselves on Drop, + /// but you can call this method to remove any unreachable registry values not manually removed + /// by `Lua::remove_registry_value`. + pub fn expire_registry_values(&self) { + unsafe { + let extra = mlua_expect!(self.extra.lock(), "extra is poisoned"); + let mut unref_list = + mlua_expect!(extra.registry_unref_list.lock(), "unref list poisoned"); + let unref_list = mem::replace(&mut *unref_list, Some(Vec::new())); + for id in mlua_expect!(unref_list, "unref list not set") { + ffi::luaL_unref(self.state, ffi::LUA_REGISTRYINDEX, id); + } + } + } + + // Uses 2 stack spaces, does not call checkstack + pub(crate) unsafe fn push_value(&self, value: Value) -> Result<()> { + match value { + Value::Nil => { + ffi::lua_pushnil(self.state); + } + + Value::Boolean(b) => { + ffi::lua_pushboolean(self.state, if b { 1 } else { 0 }); + } + + Value::LightUserData(ud) => { + ffi::lua_pushlightuserdata(self.state, ud.0); + } + + Value::Integer(i) => { + ffi::lua_pushinteger(self.state, i); + } + + Value::Number(n) => { + ffi::lua_pushnumber(self.state, n); + } + + Value::String(s) => { + self.push_ref(&s.0); + } + + Value::Table(t) => { + self.push_ref(&t.0); + } + + Value::Function(f) => { + self.push_ref(&f.0); + } + + Value::Thread(t) => { + self.push_ref(&t.0); + } + + Value::UserData(ud) => { + self.push_ref(&ud.0); + } + + Value::Error(e) => { + push_wrapped_error(self.state, e)?; + } + } + + Ok(()) + } + + // Uses 2 stack spaces, does not call checkstack + pub(crate) unsafe fn pop_value(&self) -> Value { + match ffi::lua_type(self.state, -1) { + ffi::LUA_TNIL => { + ffi::lua_pop(self.state, 1); + Nil + } + + ffi::LUA_TBOOLEAN => { + let b = Value::Boolean(ffi::lua_toboolean(self.state, -1) != 0); + ffi::lua_pop(self.state, 1); + b + } + + ffi::LUA_TLIGHTUSERDATA => { + let ud = Value::LightUserData(LightUserData(ffi::lua_touserdata(self.state, -1))); + ffi::lua_pop(self.state, 1); + ud + } + + ffi::LUA_TNUMBER => { + if ffi::lua_isinteger(self.state, -1) != 0 { + let i = Value::Integer(ffi::lua_tointeger(self.state, -1)); + ffi::lua_pop(self.state, 1); + i + } else { + let n = Value::Number(ffi::lua_tonumber(self.state, -1)); + ffi::lua_pop(self.state, 1); + n + } + } + + ffi::LUA_TSTRING => Value::String(String(self.pop_ref())), + + ffi::LUA_TTABLE => Value::Table(Table(self.pop_ref())), + + ffi::LUA_TFUNCTION => Value::Function(Function(self.pop_ref())), + + ffi::LUA_TUSERDATA => { + // It should not be possible to interact with userdata types other than custom + // UserData types OR a WrappedError. WrappedPanic should not be here. + if let Some(err) = get_wrapped_error(self.state, -1).as_ref() { + let err = err.clone(); + ffi::lua_pop(self.state, 1); + Value::Error(err) + } else { + Value::UserData(AnyUserData(self.pop_ref())) + } + } + + ffi::LUA_TTHREAD => Value::Thread(Thread(self.pop_ref())), + + _ => mlua_panic!("LUA_TNONE in pop_value"), + } + } + + // Pushes a LuaRef value onto the stack, uses 1 stack space, does not call checkstack + pub(crate) unsafe fn push_ref<'lua>(&'lua self, lref: &LuaRef<'lua>) { + assert!( + Arc::ptr_eq(&lref.lua.extra, &self.extra), + "Lua instance passed Value created from a different main Lua state" + ); + let extra = mlua_expect!(self.extra.lock(), "extra is poisoned"); + ffi::lua_pushvalue(extra.ref_thread, lref.index); + ffi::lua_xmove(extra.ref_thread, self.state, 1); + } + + // Pops the topmost element of the stack and stores a reference to it. This pins the object, + // preventing garbage collection until the returned `LuaRef` is dropped. + // + // References are stored in the stack of a specially created auxiliary thread that exists only + // to store reference values. This is much faster than storing these in the registry, and also + // much more flexible and requires less bookkeeping than storing them directly in the currently + // used stack. The implementation is somewhat biased towards the use case of a relatively small + // number of short term references being created, and `RegistryKey` being used for long term + // references. + pub(crate) unsafe fn pop_ref(&self) -> LuaRef { + let mut extra = mlua_expect!(self.extra.lock(), "extra is poisoned"); + ffi::lua_xmove(self.state, extra.ref_thread, 1); + let index = ref_stack_pop(&mut extra); + LuaRef { lua: self, index } + } + + pub(crate) fn clone_ref<'lua>(&'lua self, lref: &LuaRef<'lua>) -> LuaRef<'lua> { + unsafe { + let mut extra = mlua_expect!(self.extra.lock(), "extra is poisoned"); + ffi::lua_pushvalue(extra.ref_thread, lref.index); + let index = ref_stack_pop(&mut extra); + LuaRef { lua: self, index } + } + } + + pub(crate) fn drop_ref<'lua>(&'lua self, lref: &mut LuaRef<'lua>) { + unsafe { + let mut extra = mlua_expect!(self.extra.lock(), "extra is poisoned"); + ffi::lua_pushnil(extra.ref_thread); + ffi::lua_replace(extra.ref_thread, lref.index); + extra.ref_free.push(lref.index); + } + } + + pub(crate) unsafe fn userdata_metatable(&self) -> Result { + let type_id = TypeId::of::(); + if let Some(table_id) = mlua_expect!(self.extra.lock(), "extra is poisoned") + .registered_userdata + .get(&type_id) + { + return Ok(*table_id); + } + + let _sg = StackGuard::new(self.state); + assert_stack(self.state, 8); + + let mut methods = StaticUserDataMethods::default(); + T::add_methods(&mut methods); + + protect_lua_closure(self.state, 0, 1, |state| { + ffi::lua_newtable(state); + })?; + for (k, m) in methods.meta_methods { + push_string(self.state, k.name())?; + self.push_value(Value::Function(self.create_callback(m)?))?; + + protect_lua_closure(self.state, 3, 1, |state| { + ffi::lua_rawset(state, -3); + })?; + } + + #[cfg(feature = "async")] + let no_methods = methods.methods.is_empty() && methods.async_methods.is_empty(); + #[cfg(not(feature = "async"))] + let no_methods = methods.methods.is_empty(); + + if no_methods { + init_userdata_metatable::>(self.state, -1, None)?; + } else { + protect_lua_closure(self.state, 0, 1, |state| { + ffi::lua_newtable(state); + })?; + for (k, m) in methods.methods { + push_string(self.state, &k)?; + self.push_value(Value::Function(self.create_callback(m)?))?; + protect_lua_closure(self.state, 3, 1, |state| { + ffi::lua_rawset(state, -3); + })?; + } + #[cfg(feature = "async")] + for (k, m) in methods.async_methods { + push_string(self.state, &k)?; + self.push_value(Value::Function(self.create_async_callback(m)?))?; + protect_lua_closure(self.state, 3, 1, |state| { + ffi::lua_rawset(state, -3); + })?; + } + + init_userdata_metatable::>(self.state, -2, Some(-1))?; + ffi::lua_pop(self.state, 1); + } + + let id = protect_lua_closure(self.state, 1, 0, |state| { + ffi::luaL_ref(state, ffi::LUA_REGISTRYINDEX) + })?; + + let mut extra = mlua_expect!(self.extra.lock(), "extra is poisoned"); + extra.registered_userdata.insert(type_id, id); + + Ok(id) + } + + // Pushes a LuaRef value onto the stack, checking that it's not destructed + // Uses 2 stack spaces, does not call checkstack + #[cfg(feature = "serialize")] + pub(crate) unsafe fn push_userdata_ref(&self, lref: &LuaRef) -> Result<()> { + self.push_ref(lref); + if ffi::lua_getmetatable(self.state, -1) == 0 { + Err(Error::UserDataTypeMismatch) + } else { + // Check that userdata is not destructed + get_destructed_userdata_metatable(self.state); + let eq = ffi::lua_rawequal(self.state, -1, -2) == 1; + ffi::lua_pop(self.state, 2); + if eq { + Err(Error::UserDataDestructed) + } else { + Ok(()) + } + } + } + + // Creates a Function out of a Callback containing a 'static Fn. This is safe ONLY because the + // Fn is 'static, otherwise it could capture 'callback arguments improperly. Without ATCs, we + // cannot easily deal with the "correct" callback type of: + // + // Box Fn(&'lua Lua, MultiValue<'lua>) -> Result>)> + // + // So we instead use a caller provided lifetime, which without the 'static requirement would be + // unsafe. + pub(crate) fn create_callback<'lua, 'callback>( + &'lua self, + func: Callback<'callback, 'static>, + ) -> Result> + where + 'lua: 'callback, + { + unsafe extern "C" fn call_callback(state: *mut ffi::lua_State) -> c_int { + callback_error(state, |nargs| { + if ffi::lua_type(state, ffi::lua_upvalueindex(1)) == ffi::LUA_TNIL + || ffi::lua_type(state, ffi::lua_upvalueindex(2)) == ffi::LUA_TNIL + { + return Err(Error::CallbackDestructed); + } + let func = get_userdata::(state, ffi::lua_upvalueindex(1)); + let lua = get_userdata::(state, ffi::lua_upvalueindex(2)); + + if nargs < ffi::LUA_MINSTACK { + check_stack(state, ffi::LUA_MINSTACK - nargs)?; + } + + let lua = &mut *lua; + lua.state = state; + + let mut args = MultiValue::new(); + args.reserve(nargs as usize); + for _ in 0..nargs { + args.push_front(lua.pop_value()); + } + + let results = (*func)(lua, args)?; + let nresults = results.len() as c_int; + + check_stack(state, nresults)?; + for r in results { + lua.push_value(r)?; + } + + Ok(nresults) + }) + } + + unsafe { + let _sg = StackGuard::new(self.state); + assert_stack(self.state, 6); + + push_meta_gc_userdata::(self.state, func)?; + push_gc_userdata(self.state, self.clone())?; + + protect_lua_closure(self.state, 2, 1, |state| { + ffi::lua_pushcclosure(state, call_callback, 2); + })?; + + Ok(Function(self.pop_ref())) + } + } + + #[cfg(feature = "async")] + pub(crate) fn create_async_callback<'lua, 'callback>( + &'lua self, + func: AsyncCallback<'callback, 'static>, + ) -> Result> + where + 'lua: 'callback, + { + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + { + let libs = mlua_expect!(self.extra.lock(), "extra is poisoned").libs; + if !libs.contains(StdLib::COROUTINE) { + self.load_from_std_lib(StdLib::COROUTINE)?; + } + } + + unsafe extern "C" fn call_callback(state: *mut ffi::lua_State) -> c_int { + callback_error(state, |nargs| { + if ffi::lua_type(state, ffi::lua_upvalueindex(1)) == ffi::LUA_TNIL + || ffi::lua_type(state, ffi::lua_upvalueindex(2)) == ffi::LUA_TNIL + { + return Err(Error::CallbackDestructed); + } + let func = get_userdata::(state, ffi::lua_upvalueindex(1)); + let lua = get_userdata::(state, ffi::lua_upvalueindex(2)); + + if nargs < ffi::LUA_MINSTACK { + check_stack(state, ffi::LUA_MINSTACK - nargs)?; + } + + let lua = &mut *lua; + lua.state = state; + + let mut args = MultiValue::new(); + args.reserve(nargs as usize); + for _ in 0..nargs { + args.push_front(lua.pop_value()); + } + + let fut = (*func)(lua, args); + push_gc_userdata(state, fut)?; + push_gc_userdata(state, lua.clone())?; + + ffi::lua_pushcclosure(state, poll_future, 2); + + Ok(1) + }) + } + + unsafe extern "C" fn poll_future(state: *mut ffi::lua_State) -> c_int { + callback_error(state, |nargs| { + if ffi::lua_type(state, ffi::lua_upvalueindex(1)) == ffi::LUA_TNIL + || ffi::lua_type(state, ffi::lua_upvalueindex(2)) == ffi::LUA_TNIL + { + return Err(Error::CallbackDestructed); + } + let fut = get_userdata::>>( + state, + ffi::lua_upvalueindex(1), + ); + let lua = get_userdata::(state, ffi::lua_upvalueindex(2)); + + if nargs < ffi::LUA_MINSTACK { + check_stack(state, ffi::LUA_MINSTACK - nargs)?; + } + + let lua = &mut *lua; + let mut waker = noop_waker(); + + // Try to get an outer poll waker + ffi::lua_pushlightuserdata(state, &WAKER_REGISTRY_KEY as *const u8 as *mut c_void); + ffi::lua_rawget(state, ffi::LUA_REGISTRYINDEX); + if let Some(w) = get_gc_userdata::(state, -1).as_ref() { + waker = (*w).clone(); + } + ffi::lua_pop(state, 1); + + let mut ctx = Context::from_waker(&waker); + + match (*fut).as_mut().poll(&mut ctx) { + Poll::Pending => { + check_stack(state, 1)?; + ffi::lua_pushboolean(state, 0); + Ok(1) + } + Poll::Ready(results) => { + let results = results?; + let nresults = results.len() as Integer; + let results = lua.create_sequence_from(results)?; + check_stack(state, 3)?; + ffi::lua_pushboolean(state, 1); + lua.push_value(Value::Table(results))?; + lua.push_value(Value::Integer(nresults))?; + Ok(3) + } + } + }) + } + + let get_poll = unsafe { + let _sg = StackGuard::new(self.state); + assert_stack(self.state, 6); + + push_meta_gc_userdata::(self.state, func)?; + push_gc_userdata(self.state, self.clone())?; + + protect_lua_closure(self.state, 2, 1, |state| { + ffi::lua_pushcclosure(state, call_callback, 2); + })?; + + Function(self.pop_ref()) + }; + + let coroutine = self.globals().get::<_, Table>("coroutine")?; + + let env = self.create_table()?; + env.set("get_poll", get_poll)?; + env.set("yield", coroutine.get::<_, Function>("yield")?)?; + env.set( + "unpack", + self.create_function(|_, (tbl, len): (Table, Integer)| { + Ok(MultiValue::from_vec( + tbl.raw_sequence_values_by_len(Some(len)) + .collect::>>()?, + )) + })?, + )?; + env.set("pending", unsafe { + let _sg = StackGuard::new(self.state); + check_stack(self.state, 5)?; + push_gc_userdata(self.state, AsyncPollPending)?; + self.pop_value() + })?; + + // We set `poll` variable in the env table to be able to destroy upvalues + self.load( + r#" + poll = get_poll(...) + local poll, pending, yield, unpack = poll, pending, yield, unpack + while true do + local ready, res, nres = poll() + if ready then + return unpack(res, nres) + end + yield(pending) + end + "#, + ) + .set_name("_mlua_async_poll")? + .set_environment(env)? + .into_function() + } + + pub(crate) unsafe fn make_userdata(&self, data: UserDataWrapped) -> Result + where + T: 'static + UserData, + { + let _sg = StackGuard::new(self.state); + assert_stack(self.state, 4); + + let ud_index = self.userdata_metatable::()?; + push_userdata::>(self.state, RefCell::new(data))?; + + ffi::lua_rawgeti( + self.state, + ffi::LUA_REGISTRYINDEX, + ud_index as ffi::lua_Integer, + ); + ffi::lua_setmetatable(self.state, -2); + + Ok(AnyUserData(self.pop_ref())) + } + + pub(crate) fn clone(&self) -> Self { + Lua { + state: self.state, + main_state: self.main_state, + extra: self.extra.clone(), + ephemeral: true, + safe: self.safe, + _no_ref_unwind_safe: PhantomData, + } + } + + fn disable_c_modules(&self) -> Result<()> { + let package: Table = self.globals().get("package")?; + + package.set( + "loadlib", + self.create_function(|_, ()| -> Result<()> { + Err(Error::SafetyError( + "package.loadlib is disabled in safe mode".to_string(), + )) + })?, + )?; + + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + let searchers: Table = package.get("searchers")?; + #[cfg(any(feature = "lua51", feature = "luajit"))] + let searchers: Table = package.get("loaders")?; + + let loader = self.create_function(|_, ()| Ok("\n\tcan't load C modules in safe mode"))?; + + // The third and fourth searchers looks for a loader as a C library + searchers.raw_set(3, loader.clone())?; + searchers.raw_remove(4)?; + + Ok(()) + } + + pub(crate) unsafe fn make_from_ptr(state: *mut ffi::lua_State) -> Self { + let _sg = StackGuard::new(state); + assert_stack(state, 3); + + ffi::lua_rawgetp( + state, + ffi::LUA_REGISTRYINDEX, + &EXTRA_REGISTRY_KEY as *const u8 as *mut c_void, + ); + let extra = mlua_expect!( + (*get_gc_userdata::>>(state, -1)).upgrade(), + "extra is destroyed" + ); + ffi::lua_pop(state, 1); + + Lua { + state, + main_state: get_main_state(state), + extra, + ephemeral: true, + safe: true, // TODO: Inherit the attribute + _no_ref_unwind_safe: PhantomData, + } + } + + pub(crate) unsafe fn hook_callback(&self) -> Option { + let extra = mlua_expect!(self.extra.lock(), "extra is poisoned"); + extra.hook_callback.clone() + } +} + +/// Returned from [`Lua::load`] and is used to finalize loading and executing Lua main chunks. +/// +/// [`Lua::load`]: struct.Lua.html#method.load +#[must_use = "`Chunk`s do nothing unless one of `exec`, `eval`, `call`, or `into_function` are called on them"] +pub struct Chunk<'lua, 'a> { + lua: &'lua Lua, + source: &'a [u8], + name: Option, + env: Option>, + mode: Option, +} + +/// Represents chunk mode (text or binary). +#[derive(Clone, Copy)] +pub enum ChunkMode { + Text, + Binary, +} + +impl<'lua, 'a> Chunk<'lua, 'a> { + /// Sets the name of this chunk, which results in more informative error traces. + pub fn set_name>(mut self, name: &S) -> Result> { + let name = + CString::new(name.as_ref().to_vec()).map_err(|e| Error::ToLuaConversionError { + from: "&str", + to: "string", + message: Some(e.to_string()), + })?; + self.name = Some(name); + Ok(self) + } + + /// Sets the first upvalue (`_ENV`) of the loaded chunk to the given value. + /// + /// Lua main chunks always have exactly one upvalue, and this upvalue is used as the `_ENV` + /// variable inside the chunk. By default this value is set to the global environment. + /// + /// Calling this method changes the `_ENV` upvalue to the value provided, and variables inside + /// the chunk will refer to the given environment rather than the global one. + /// + /// All global variables (including the standard library!) are looked up in `_ENV`, so it may be + /// necessary to populate the environment in order for scripts using custom environments to be + /// useful. + pub fn set_environment>(mut self, env: V) -> Result> { + self.env = Some(env.to_lua(self.lua)?); + Ok(self) + } + + /// Sets whether the chunk is text or binary (autodetected by default). + /// + /// Lua does not check the consistency of binary chunks, therefore this mode is allowed only + /// for instances created with [`Lua::unsafe_new`]. + /// + /// [`Lua::unsafe_new`]: struct.Lua.html#method.unsafe_new + pub fn set_mode(mut self, mode: ChunkMode) -> Chunk<'lua, 'a> { + self.mode = Some(mode); + self + } + + /// Execute this chunk of code. + /// + /// This is equivalent to calling the chunk function with no arguments and no return values. + pub fn exec(self) -> Result<()> { + self.call(())?; + Ok(()) + } + + /// Asynchronously execute this chunk of code. + /// + /// See [`Chunk::exec`] for more details. + /// + /// Requires `feature = "async"` + /// + /// [`Chunk::exec`]: struct.Chunk.html#method.exec + #[cfg(feature = "async")] + #[cfg_attr(docsrs, doc(cfg(feature = "async")))] + pub fn exec_async<'fut>(self) -> LocalBoxFuture<'fut, Result<()>> + where + 'lua: 'fut, + { + self.call_async(()) + } + + /// Evaluate the chunk as either an expression or block. + /// + /// If the chunk can be parsed as an expression, this loads and executes the chunk and returns + /// the value that it evaluates to. Otherwise, the chunk is interpreted as a block as normal, + /// and this is equivalent to calling `exec`. + pub fn eval>(self) -> Result { + // Bytecode is always interpreted as a statement. + // For source code, first try interpreting the lua as an expression by adding + // "return", then as a statement. This is the same thing the + // actual lua repl does. + if self.source.starts_with(ffi::LUA_SIGNATURE) { + self.call(()) + } else if let Ok(function) = self.lua.load_chunk( + &self.expression_source(), + self.name.as_ref(), + self.env.clone(), + self.mode, + ) { + function.call(()) + } else { + self.call(()) + } + } + + /// Asynchronously evaluate the chunk as either an expression or block. + /// + /// See [`Chunk::eval`] for more details. + /// + /// Requires `feature = "async"` + /// + /// [`Chunk::eval`]: struct.Chunk.html#method.eval + #[cfg(feature = "async")] + #[cfg_attr(docsrs, doc(cfg(feature = "async")))] + pub fn eval_async<'fut, R>(self) -> LocalBoxFuture<'fut, Result> + where + 'lua: 'fut, + R: FromLuaMulti<'lua> + 'fut, + { + if self.source.starts_with(ffi::LUA_SIGNATURE) { + self.call_async(()) + } else if let Ok(function) = self.lua.load_chunk( + &self.expression_source(), + self.name.as_ref(), + self.env.clone(), + self.mode, + ) { + function.call_async(()) + } else { + self.call_async(()) + } + } + + /// Load the chunk function and call it with the given arguemnts. + /// + /// This is equivalent to `into_function` and calling the resulting function. + pub fn call, R: FromLuaMulti<'lua>>(self, args: A) -> Result { + self.into_function()?.call(args) + } + + /// Load the chunk function and asynchronously call it with the given arguemnts. + /// + /// See [`Chunk::call`] for more details. + /// + /// Requires `feature = "async"` + /// + /// [`Chunk::call`]: struct.Chunk.html#method.call + #[cfg(feature = "async")] + #[cfg_attr(docsrs, doc(cfg(feature = "async")))] + pub fn call_async<'fut, A, R>(self, args: A) -> LocalBoxFuture<'fut, Result> + where + 'lua: 'fut, + A: ToLuaMulti<'lua>, + R: FromLuaMulti<'lua> + 'fut, + { + match self.into_function() { + Ok(func) => func.call_async(args), + Err(e) => Box::pin(future::err(e)), + } + } + + /// Load this chunk into a regular `Function`. + /// + /// This simply compiles the chunk without actually executing it. + pub fn into_function(self) -> Result> { + self.lua + .load_chunk(self.source, self.name.as_ref(), self.env, self.mode) + } + + fn expression_source(&self) -> Vec { + let mut buf = Vec::with_capacity(b"return ".len() + self.source.len()); + buf.extend(b"return "); + buf.extend(self.source); + buf + } +} + +unsafe fn load_from_std_lib(state: *mut ffi::lua_State, libs: StdLib) { + #[cfg(feature = "luajit")] + // Stop collector during library initialization + ffi::lua_gc(state, ffi::LUA_GCSTOP, 0); + + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + { + if libs.contains(StdLib::COROUTINE) { + let colib_name = CString::new(ffi::LUA_COLIBNAME).unwrap(); + ffi::luaL_requiref(state, colib_name.as_ptr(), ffi::luaopen_coroutine, 1); + ffi::lua_pop(state, 1); + } + } + + if libs.contains(StdLib::TABLE) { + let tablib_name = CString::new(ffi::LUA_TABLIBNAME).unwrap(); + ffi::luaL_requiref(state, tablib_name.as_ptr(), ffi::luaopen_table, 1); + ffi::lua_pop(state, 1); + } + + if libs.contains(StdLib::IO) { + let iolib_name = CString::new(ffi::LUA_IOLIBNAME).unwrap(); + ffi::luaL_requiref(state, iolib_name.as_ptr(), ffi::luaopen_io, 1); + ffi::lua_pop(state, 1); + } + + if libs.contains(StdLib::OS) { + let oslib_name = CString::new(ffi::LUA_OSLIBNAME).unwrap(); + ffi::luaL_requiref(state, oslib_name.as_ptr(), ffi::luaopen_os, 1); + ffi::lua_pop(state, 1); + } + + if libs.contains(StdLib::STRING) { + let strlib_name = CString::new(ffi::LUA_STRLIBNAME).unwrap(); + ffi::luaL_requiref(state, strlib_name.as_ptr(), ffi::luaopen_string, 1); + ffi::lua_pop(state, 1); + } + + #[cfg(any(feature = "lua54", feature = "lua53"))] + { + if libs.contains(StdLib::UTF8) { + let utf8lib_name = CString::new(ffi::LUA_UTF8LIBNAME).unwrap(); + ffi::luaL_requiref(state, utf8lib_name.as_ptr(), ffi::luaopen_utf8, 1); + ffi::lua_pop(state, 1); + } + } + + #[cfg(feature = "lua52")] + { + if libs.contains(StdLib::BIT) { + let bitlib_name = CString::new(ffi::LUA_BITLIBNAME).unwrap(); + ffi::luaL_requiref(state, bitlib_name.as_ptr(), ffi::luaopen_bit32, 1); + ffi::lua_pop(state, 1); + } + } + + #[cfg(feature = "luajit")] + { + if libs.contains(StdLib::BIT) { + let bitlib_name = CString::new(ffi::LUA_BITLIBNAME).unwrap(); + ffi::luaL_requiref(state, bitlib_name.as_ptr(), ffi::luaopen_bit, 1); + ffi::lua_pop(state, 1); + } + } + + if libs.contains(StdLib::MATH) { + let mathlib_name = CString::new(ffi::LUA_MATHLIBNAME).unwrap(); + ffi::luaL_requiref(state, mathlib_name.as_ptr(), ffi::luaopen_math, 1); + ffi::lua_pop(state, 1); + } + + if libs.contains(StdLib::DEBUG) { + let dblib_name = CString::new(ffi::LUA_DBLIBNAME).unwrap(); + ffi::luaL_requiref(state, dblib_name.as_ptr(), ffi::luaopen_debug, 1); + ffi::lua_pop(state, 1); + } + + if libs.contains(StdLib::PACKAGE) { + let loadlib_name = CString::new(ffi::LUA_LOADLIBNAME).unwrap(); + ffi::luaL_requiref(state, loadlib_name.as_ptr(), ffi::luaopen_package, 1); + ffi::lua_pop(state, 1); + } + + #[cfg(feature = "luajit")] + { + if libs.contains(StdLib::JIT) { + let jitlib_name = CString::new(ffi::LUA_JITLIBNAME).unwrap(); + ffi::luaL_requiref(state, jitlib_name.as_ptr(), ffi::luaopen_jit, 1); + ffi::lua_pop(state, 1); + } + + if libs.contains(StdLib::FFI) { + let ffilib_name = CString::new(ffi::LUA_FFILIBNAME).unwrap(); + ffi::luaL_requiref(state, ffilib_name.as_ptr(), ffi::luaopen_ffi, 1); + ffi::lua_pop(state, 1); + } + } + + #[cfg(feature = "luajit")] + ffi::lua_gc(state, ffi::LUA_GCRESTART, -1); +} + +unsafe fn ref_stack_pop(extra: &mut ExtraData) -> c_int { + if let Some(free) = extra.ref_free.pop() { + ffi::lua_replace(extra.ref_thread, free); + free + } else { + if extra.ref_stack_max >= extra.ref_stack_size { + // It is a user error to create enough references to exhaust the Lua max stack size for + // the ref thread. + if ffi::lua_checkstack(extra.ref_thread, extra.ref_stack_size) == 0 { + mlua_panic!("cannot create a Lua reference, out of auxiliary stack space"); + } + extra.ref_stack_size *= 2; + } + extra.ref_stack_max += 1; + extra.ref_stack_max + } +} + +struct StaticUserDataMethods<'lua, T: 'static + UserData> { + methods: Vec<(Vec, Callback<'lua, 'static>)>, + #[cfg(feature = "async")] + async_methods: Vec<(Vec, AsyncCallback<'lua, 'static>)>, + meta_methods: Vec<(MetaMethod, Callback<'lua, 'static>)>, + _type: PhantomData, +} + +impl<'lua, T: 'static + UserData> Default for StaticUserDataMethods<'lua, T> { + fn default() -> StaticUserDataMethods<'lua, T> { + StaticUserDataMethods { + methods: Vec::new(), + #[cfg(feature = "async")] + async_methods: Vec::new(), + meta_methods: Vec::new(), + _type: PhantomData, + } + } +} + +impl<'lua, T: 'static + UserData> UserDataMethods<'lua, T> for StaticUserDataMethods<'lua, T> { + fn add_method(&mut self, name: &S, method: M) + where + S: AsRef<[u8]> + ?Sized, + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result, + { + self.methods + .push((name.as_ref().to_vec(), Self::box_method(method))); + } + + fn add_method_mut(&mut self, name: &S, method: M) + where + S: AsRef<[u8]> + ?Sized, + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result, + { + self.methods + .push((name.as_ref().to_vec(), Self::box_method_mut(method))); + } + + #[cfg(feature = "async")] + fn add_async_method(&mut self, name: &S, method: M) + where + T: Clone, + S: AsRef<[u8]> + ?Sized, + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + M: 'static + MaybeSend + Fn(&'lua Lua, T, A) -> MR, + MR: 'lua + Future>, + { + self.async_methods + .push((name.as_ref().to_vec(), Self::box_async_method(method))); + } + + fn add_function(&mut self, name: &S, function: F) + where + S: AsRef<[u8]> + ?Sized, + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result, + { + self.methods + .push((name.as_ref().to_vec(), Self::box_function(function))); + } + + fn add_function_mut(&mut self, name: &S, function: F) + where + S: AsRef<[u8]> + ?Sized, + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result, + { + self.methods + .push((name.as_ref().to_vec(), Self::box_function_mut(function))); + } + + #[cfg(feature = "async")] + fn add_async_function(&mut self, name: &S, function: F) + where + T: Clone, + S: AsRef<[u8]> + ?Sized, + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + F: 'static + MaybeSend + Fn(&'lua Lua, A) -> FR, + FR: 'lua + Future>, + { + self.async_methods + .push((name.as_ref().to_vec(), Self::box_async_function(function))); + } + + fn add_meta_method(&mut self, meta: MetaMethod, method: M) + where + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result, + { + self.meta_methods.push((meta, Self::box_method(method))); + } + + fn add_meta_method_mut(&mut self, meta: MetaMethod, method: M) + where + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result, + { + self.meta_methods.push((meta, Self::box_method_mut(method))); + } + + fn add_meta_function(&mut self, meta: MetaMethod, function: F) + where + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result, + { + self.meta_methods.push((meta, Self::box_function(function))); + } + + fn add_meta_function_mut(&mut self, meta: MetaMethod, function: F) + where + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result, + { + self.meta_methods + .push((meta, Self::box_function_mut(function))); + } +} + +impl<'lua, T: 'static + UserData> StaticUserDataMethods<'lua, T> { + fn box_method(method: M) -> Callback<'lua, 'static> + where + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result, + { + Box::new(move |lua, mut args| { + if let Some(front) = args.pop_front() { + let userdata = AnyUserData::from_lua(front, lua)?; + let userdata = userdata.borrow::()?; + method(lua, &userdata, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua) + } else { + Err(Error::FromLuaConversionError { + from: "missing argument", + to: "userdata", + message: None, + }) + } + }) + } + + fn box_method_mut(method: M) -> Callback<'lua, 'static> + where + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result, + { + let method = RefCell::new(method); + Box::new(move |lua, mut args| { + if let Some(front) = args.pop_front() { + let userdata = AnyUserData::from_lua(front, lua)?; + let mut userdata = userdata.borrow_mut::()?; + let mut method = method + .try_borrow_mut() + .map_err(|_| Error::RecursiveMutCallback)?; + (&mut *method)(lua, &mut userdata, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua) + } else { + Err(Error::FromLuaConversionError { + from: "missing argument", + to: "userdata", + message: None, + }) + } + }) + } + + #[cfg(feature = "async")] + fn box_async_method(method: M) -> AsyncCallback<'lua, 'static> + where + T: Clone, + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + M: 'static + MaybeSend + Fn(&'lua Lua, T, A) -> MR, + MR: 'lua + Future>, + { + Box::new(move |lua, mut args| { + let fut_res = || { + if let Some(front) = args.pop_front() { + let userdata = AnyUserData::from_lua(front, lua)?; + let userdata = userdata.borrow::()?.clone(); + Ok(method(lua, userdata, A::from_lua_multi(args, lua)?)) + } else { + Err(Error::FromLuaConversionError { + from: "missing argument", + to: "userdata", + message: None, + }) + } + }; + match fut_res() { + Ok(fut) => Box::pin(fut.and_then(move |ret| future::ready(ret.to_lua_multi(lua)))), + Err(e) => Box::pin(future::err(e)), + } + }) + } + + fn box_function(function: F) -> Callback<'lua, 'static> + where + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result, + { + Box::new(move |lua, args| function(lua, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)) + } + + fn box_function_mut(function: F) -> Callback<'lua, 'static> + where + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result, + { + let function = RefCell::new(function); + Box::new(move |lua, args| { + let function = &mut *function + .try_borrow_mut() + .map_err(|_| Error::RecursiveMutCallback)?; + function(lua, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua) + }) + } + + #[cfg(feature = "async")] + fn box_async_function(function: F) -> AsyncCallback<'lua, 'static> + where + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + F: 'static + MaybeSend + Fn(&'lua Lua, A) -> FR, + FR: 'lua + Future>, + { + Box::new(move |lua, args| { + let args = match A::from_lua_multi(args, lua) { + Ok(args) => args, + Err(e) => return Box::pin(future::err(e)), + }; + Box::pin(function(lua, args).and_then(move |ret| future::ready(ret.to_lua_multi(lua)))) + }) + } +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/src/macros.rs b/third_party/cargo/vendor/mlua-0.5.3/src/macros.rs new file mode 100644 index 0000000..89f54da --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/src/macros.rs @@ -0,0 +1,96 @@ +macro_rules! bug_msg { + ($arg:expr) => { + concat!( + "mlua internal error: ", + $arg, + " (this is a bug, please file an issue)" + ) + }; +} + +macro_rules! cstr { + ($s:expr) => { + concat!($s, "\0") as *const str as *const [::std::os::raw::c_char] + as *const ::std::os::raw::c_char + }; +} + +macro_rules! mlua_panic { + ($msg:expr) => { + panic!(bug_msg!($msg)); + }; + + ($msg:expr,) => { + mlua_panic!($msg); + }; + + ($msg:expr, $($arg:expr),+) => { + panic!(bug_msg!($msg), $($arg),+); + }; + + ($msg:expr, $($arg:expr),+,) => { + mlua_panic!($msg, $($arg),+); + }; +} + +macro_rules! mlua_assert { + ($cond:expr, $msg:expr) => { + assert!($cond, bug_msg!($msg)); + }; + + ($cond:expr, $msg:expr,) => { + mlua_assert!($cond, $msg); + }; + + ($cond:expr, $msg:expr, $($arg:expr),+) => { + assert!($cond, bug_msg!($msg), $($arg),+); + }; + + ($cond:expr, $msg:expr, $($arg:expr),+,) => { + mlua_assert!($cond, $msg, $($arg),+); + }; +} + +macro_rules! mlua_debug_assert { + ($cond:expr, $msg:expr) => { + debug_assert!($cond, bug_msg!($msg)); + }; + + ($cond:expr, $msg:expr,) => { + mlua_debug_assert!($cond, $msg); + }; + + ($cond:expr, $msg:expr, $($arg:expr),+) => { + debug_assert!($cond, bug_msg!($msg), $($arg),+); + }; + + ($cond:expr, $msg:expr, $($arg:expr),+,) => { + mlua_debug_assert!($cond, $msg, $($arg),+); + }; +} + +macro_rules! mlua_expect { + ($res:expr, $msg:expr) => { + $res.expect(bug_msg!($msg)) + }; + + ($res:expr, $msg:expr,) => { + mlua_expect!($res, $msg) + }; +} + +#[cfg(feature = "module")] +#[doc(hidden)] +#[macro_export] +macro_rules! require_module_feature { + () => {}; +} + +#[cfg(not(feature = "module"))] +#[doc(hidden)] +#[macro_export] +macro_rules! require_module_feature { + () => { + compile_error!("Feature `module` must be enabled in the `mlua` crate"); + }; +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/src/multi.rs b/third_party/cargo/vendor/mlua-0.5.3/src/multi.rs new file mode 100644 index 0000000..128122d --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/src/multi.rs @@ -0,0 +1,215 @@ +use std::iter::FromIterator; +use std::ops::{Deref, DerefMut}; +use std::result::Result as StdResult; + +use crate::error::Result; +use crate::lua::Lua; +use crate::value::{FromLua, FromLuaMulti, MultiValue, Nil, ToLua, ToLuaMulti}; + +/// Result is convertible to `MultiValue` following the common Lua idiom of returning the result +/// on success, or in the case of an error, returning `nil` and an error message. +impl<'lua, T: ToLua<'lua>, E: ToLua<'lua>> ToLuaMulti<'lua> for StdResult { + fn to_lua_multi(self, lua: &'lua Lua) -> Result> { + let mut result = MultiValue::new(); + + match self { + Ok(v) => result.push_front(v.to_lua(lua)?), + Err(e) => { + result.push_front(e.to_lua(lua)?); + result.push_front(Nil); + } + } + + Ok(result) + } +} + +impl<'lua, T: ToLua<'lua>> ToLuaMulti<'lua> for T { + fn to_lua_multi(self, lua: &'lua Lua) -> Result> { + let mut v = MultiValue::new(); + v.push_front(self.to_lua(lua)?); + Ok(v) + } +} + +impl<'lua, T: FromLua<'lua>> FromLuaMulti<'lua> for T { + fn from_lua_multi(mut values: MultiValue<'lua>, lua: &'lua Lua) -> Result { + T::from_lua(values.pop_front().unwrap_or(Nil), lua) + } +} + +impl<'lua> ToLuaMulti<'lua> for MultiValue<'lua> { + fn to_lua_multi(self, _: &'lua Lua) -> Result> { + Ok(self) + } +} + +impl<'lua> FromLuaMulti<'lua> for MultiValue<'lua> { + fn from_lua_multi(values: MultiValue<'lua>, _: &'lua Lua) -> Result { + Ok(values) + } +} + +/// Wraps a variable number of `T`s. +/// +/// Can be used to work with variadic functions more easily. Using this type as the last argument of +/// a Rust callback will accept any number of arguments from Lua and convert them to the type `T` +/// using [`FromLua`]. `Variadic` can also be returned from a callback, returning a variable +/// number of values to Lua. +/// +/// The [`MultiValue`] type is equivalent to `Variadic`. +/// +/// # Examples +/// +/// ``` +/// # use mlua::{Lua, Result, Variadic}; +/// # fn main() -> Result<()> { +/// # let lua = Lua::new(); +/// let add = lua.create_function(|_, vals: Variadic| -> Result { +/// Ok(vals.iter().sum()) +/// })?; +/// lua.globals().set("add", add)?; +/// assert_eq!(lua.load("add(3, 2, 5)").eval::()?, 10.0); +/// # Ok(()) +/// # } +/// ``` +/// +/// [`FromLua`]: trait.FromLua.html +/// [`MultiValue`]: struct.MultiValue.html +#[derive(Debug, Clone)] +pub struct Variadic(Vec); + +impl Variadic { + /// Creates an empty `Variadic` wrapper containing no values. + pub fn new() -> Variadic { + Variadic(Vec::new()) + } +} + +impl Default for Variadic { + fn default() -> Variadic { + Variadic::new() + } +} + +impl FromIterator for Variadic { + fn from_iter>(iter: I) -> Self { + Variadic(Vec::from_iter(iter)) + } +} + +impl IntoIterator for Variadic { + type Item = T; + type IntoIter = as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + +impl Deref for Variadic { + type Target = Vec; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for Variadic { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl<'lua, T: ToLua<'lua>> ToLuaMulti<'lua> for Variadic { + fn to_lua_multi(self, lua: &'lua Lua) -> Result> { + self.0.into_iter().map(|e| e.to_lua(lua)).collect() + } +} + +impl<'lua, T: FromLua<'lua>> FromLuaMulti<'lua> for Variadic { + fn from_lua_multi(values: MultiValue<'lua>, lua: &'lua Lua) -> Result { + values + .into_iter() + .map(|e| T::from_lua(e, lua)) + .collect::>>() + .map(Variadic) + } +} + +macro_rules! impl_tuple { + () => ( + impl<'lua> ToLuaMulti<'lua> for () { + fn to_lua_multi(self, _: &'lua Lua) -> Result> { + Ok(MultiValue::new()) + } + } + + impl<'lua> FromLuaMulti<'lua> for () { + fn from_lua_multi(_: MultiValue<'lua>, _: &'lua Lua) -> Result { + Ok(()) + } + } + ); + + ($last:ident $($name:ident)*) => ( + impl<'lua, $($name,)* $last> ToLuaMulti<'lua> for ($($name,)* $last,) + where $($name: ToLua<'lua>,)* + $last: ToLuaMulti<'lua> + { + #[allow(unused_mut)] + #[allow(non_snake_case)] + fn to_lua_multi(self, lua: &'lua Lua) -> Result> { + let ($($name,)* $last,) = self; + + let mut results = $last.to_lua_multi(lua)?; + push_reverse!(results, $($name.to_lua(lua)?,)*); + Ok(results) + } + } + + impl<'lua, $($name,)* $last> FromLuaMulti<'lua> for ($($name,)* $last,) + where $($name: FromLua<'lua>,)* + $last: FromLuaMulti<'lua> + { + #[allow(unused_mut)] + #[allow(non_snake_case)] + fn from_lua_multi(mut values: MultiValue<'lua>, lua: &'lua Lua) -> Result { + $(let $name = values.pop_front().unwrap_or(Nil);)* + let $last = FromLuaMulti::from_lua_multi(values, lua)?; + Ok(($(FromLua::from_lua($name, lua)?,)* $last,)) + } + } + ); +} + +macro_rules! push_reverse { + ($multi_value:expr, $first:expr, $($rest:expr,)*) => ( + push_reverse!($multi_value, $($rest,)*); + $multi_value.push_front($first); + ); + + ($multi_value:expr, $first:expr) => ( + $multi_value.push_front($first); + ); + + ($multi_value:expr,) => (); +} + +impl_tuple!(); +impl_tuple!(A); +impl_tuple!(A B); +impl_tuple!(A B C); +impl_tuple!(A B C D); +impl_tuple!(A B C D E); +impl_tuple!(A B C D E F); +impl_tuple!(A B C D E F G); +impl_tuple!(A B C D E F G H); +impl_tuple!(A B C D E F G H I); +impl_tuple!(A B C D E F G H I J); +impl_tuple!(A B C D E F G H I J K); +impl_tuple!(A B C D E F G H I J K L); +impl_tuple!(A B C D E F G H I J K L M); +impl_tuple!(A B C D E F G H I J K L M N); +impl_tuple!(A B C D E F G H I J K L M N O); +impl_tuple!(A B C D E F G H I J K L M N O P); diff --git a/third_party/cargo/vendor/mlua-0.5.3/src/prelude.rs b/third_party/cargo/vendor/mlua-0.5.3/src/prelude.rs new file mode 100644 index 0000000..bce044f --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/src/prelude.rs @@ -0,0 +1,16 @@ +//! Re-exports most types with an extra `Lua*` prefix to prevent name clashes. + +pub use crate::{ + AnyUserData as LuaAnyUserData, Chunk as LuaChunk, Error as LuaError, + ExternalError as LuaExternalError, ExternalResult as LuaExternalResult, FromLua, FromLuaMulti, + Function as LuaFunction, GCMode as LuaGCMode, Integer as LuaInteger, + LightUserData as LuaLightUserData, Lua, MetaMethod as LuaMetaMethod, + MultiValue as LuaMultiValue, Nil as LuaNil, Number as LuaNumber, RegistryKey as LuaRegistryKey, + Result as LuaResult, String as LuaString, Table as LuaTable, TableExt as LuaTableExt, + TablePairs as LuaTablePairs, TableSequence as LuaTableSequence, Thread as LuaThread, + ThreadStatus as LuaThreadStatus, ToLua, ToLuaMulti, UserData as LuaUserData, + UserDataMethods as LuaUserDataMethods, Value as LuaValue, +}; + +#[cfg(feature = "async")] +pub use crate::AsyncThread as LuaAsyncThread; diff --git a/third_party/cargo/vendor/mlua-0.5.3/src/scope.rs b/third_party/cargo/vendor/mlua-0.5.3/src/scope.rs new file mode 100644 index 0000000..fe2cb0f --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/src/scope.rs @@ -0,0 +1,648 @@ +use std::any::Any; +use std::cell::{Cell, Ref, RefCell, RefMut}; +use std::marker::PhantomData; +use std::mem; +use std::os::raw::c_void; +use std::rc::Rc; + +#[cfg(feature = "serialize")] +use serde::Serialize; + +use crate::error::{Error, Result}; +use crate::ffi; +use crate::function::Function; +use crate::lua::Lua; +use crate::types::{Callback, LuaRef, MaybeSend, UserDataCell}; +use crate::userdata::{AnyUserData, MetaMethod, UserData, UserDataMethods, UserDataWrapped}; +use crate::util::{ + assert_stack, init_userdata_metatable, protect_lua_closure, push_string, push_userdata, + take_userdata, StackGuard, +}; +use crate::value::{FromLuaMulti, MultiValue, ToLuaMulti, Value}; + +#[cfg(feature = "async")] +use { + crate::types::AsyncCallback, + futures_core::future::{Future, LocalBoxFuture}, + futures_util::future::{self, TryFutureExt}, +}; + +/// Constructed by the [`Lua::scope`] method, allows temporarily creating Lua userdata and +/// callbacks that are not required to be Send or 'static. +/// +/// See [`Lua::scope`] for more details. +/// +/// [`Lua::scope`]: struct.Lua.html#method.scope +#[allow(clippy::type_complexity)] +pub struct Scope<'lua, 'scope> { + lua: &'lua Lua, + destructors: RefCell, fn(LuaRef<'lua>) -> Vec>)>>, + _scope_invariant: PhantomData>, +} + +impl<'lua, 'scope> Scope<'lua, 'scope> { + pub(crate) fn new(lua: &'lua Lua) -> Scope<'lua, 'scope> { + Scope { + lua, + destructors: RefCell::new(Vec::new()), + _scope_invariant: PhantomData, + } + } + + /// Wraps a Rust function or closure, creating a callable Lua function handle to it. + /// + /// This is a version of [`Lua::create_function`] that creates a callback which expires on + /// scope drop. See [`Lua::scope`] for more details. + /// + /// [`Lua::create_function`]: struct.Lua.html#method.create_function + /// [`Lua::scope`]: struct.Lua.html#method.scope + pub fn create_function<'callback, A, R, F>(&'callback self, func: F) -> Result> + where + A: FromLuaMulti<'callback>, + R: ToLuaMulti<'callback>, + F: 'scope + Fn(&'callback Lua, A) -> Result, + { + // Safe, because 'scope must outlive 'callback (due to Self containing 'scope), however the + // callback itself must be 'scope lifetime, so the function should not be able to capture + // anything of 'callback lifetime. 'scope can't be shortened due to being invariant, and + // the 'callback lifetime here can't be enlarged due to coming from a universal + // quantification in Lua::scope. + // + // I hope I got this explanation right, but in any case this is tested with compiletest_rs + // to make sure callbacks can't capture handles with lifetime outside the scope, inside the + // scope, and owned inside the callback itself. + unsafe { + self.create_callback(Box::new(move |lua, args| { + func(lua, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua) + })) + } + } + + /// Wraps a Rust mutable closure, creating a callable Lua function handle to it. + /// + /// This is a version of [`Lua::create_function_mut`] that creates a callback which expires + /// on scope drop. See [`Lua::scope`] and [`Scope::create_function`] for more details. + /// + /// [`Lua::create_function_mut`]: struct.Lua.html#method.create_function_mut + /// [`Lua::scope`]: struct.Lua.html#method.scope + /// [`Scope::create_function`]: #method.create_function + pub fn create_function_mut<'callback, A, R, F>( + &'callback self, + func: F, + ) -> Result> + where + A: FromLuaMulti<'callback>, + R: ToLuaMulti<'callback>, + F: 'scope + FnMut(&'callback Lua, A) -> Result, + { + let func = RefCell::new(func); + self.create_function(move |lua, args| { + (&mut *func + .try_borrow_mut() + .map_err(|_| Error::RecursiveMutCallback)?)(lua, args) + }) + } + + /// Wraps a Rust async function or closure, creating a callable Lua function handle to it. + /// + /// This is a version of [`Lua::create_async_function`] that creates a callback which expires on + /// scope drop. See [`Lua::scope`] and [`Lua::async_scope`] for more details. + /// + /// Requires `feature = "async"` + /// + /// [`Lua::create_async_function`]: struct.Lua.html#method.create_async_function + /// [`Lua::scope`]: struct.Lua.html#method.scope + /// [`Lua::async_scope`]: struct.Lua.html#method.async_scope + #[cfg(feature = "async")] + #[cfg_attr(docsrs, doc(cfg(feature = "async")))] + pub fn create_async_function<'callback, A, R, F, FR>( + &'callback self, + func: F, + ) -> Result> + where + A: FromLuaMulti<'callback>, + R: ToLuaMulti<'callback>, + F: 'scope + Fn(&'callback Lua, A) -> FR, + FR: 'callback + Future>, + { + unsafe { + self.create_async_callback(Box::new(move |lua, args| { + let args = match A::from_lua_multi(args, lua) { + Ok(args) => args, + Err(e) => return Box::pin(future::err(e)), + }; + Box::pin(func(lua, args).and_then(move |ret| future::ready(ret.to_lua_multi(lua)))) + })) + } + } + + /// Create a Lua userdata object from a custom userdata type. + /// + /// This is a version of [`Lua::create_userdata`] that creates a userdata which expires on + /// scope drop, and does not require that the userdata type be Send (but still requires that the + /// UserData be 'static). + /// See [`Lua::scope`] for more details. + /// + /// [`Lua::create_userdata`]: struct.Lua.html#method.create_userdata + /// [`Lua::scope`]: struct.Lua.html#method.scope + pub fn create_userdata(&self, data: T) -> Result> + where + T: 'static + UserData, + { + self.create_userdata_inner(UserDataWrapped::new(data)) + } + + /// Create a Lua userdata object from a custom serializable userdata type. + /// + /// This is a version of [`Lua::create_ser_userdata`] that creates a userdata which expires on + /// scope drop, and does not require that the userdata type be Send (but still requires that the + /// UserData be 'static). + /// See [`Lua::scope`] for more details. + /// + /// Requires `feature = "serialize"` + /// + /// [`Lua::create_ser_userdata`]: struct.Lua.html#method.create_ser_userdata + /// [`Lua::scope`]: struct.Lua.html#method.scope + #[cfg(feature = "serialize")] + #[cfg_attr(docsrs, doc(cfg(feature = "serialize")))] + pub fn create_ser_userdata(&self, data: T) -> Result> + where + T: 'static + UserData + Serialize, + { + self.create_userdata_inner(UserDataWrapped::new_ser(data)) + } + + fn create_userdata_inner(&self, data: UserDataWrapped) -> Result> + where + T: 'static + UserData, + { + // Safe even though T may not be Send, because the parent Lua cannot be sent to another + // thread while the Scope is alive (or the returned AnyUserData handle even). + unsafe { + let u = self.lua.make_userdata(data)?; + self.destructors.borrow_mut().push((u.0.clone(), |u| { + let state = u.lua.state; + assert_stack(state, 2); + u.lua.push_ref(&u); + // We know the destructor has not run yet because we hold a reference to the + // userdata. + vec![Box::new(take_userdata::>(state))] + })); + Ok(u) + } + } + + /// Create a Lua userdata object from a custom userdata type. + /// + /// This is a version of [`Lua::create_userdata`] that creates a userdata which expires on + /// scope drop, and does not require that the userdata type be Send or 'static. See + /// [`Lua::scope`] for more details. + /// + /// Lifting the requirement that the UserData type be 'static comes with some important + /// limitations, so if you only need to eliminate the Send requirement, it is probably better to + /// use [`Scope::create_userdata`] instead. + /// + /// The main limitation that comes from using non-'static userdata is that the produced userdata + /// will no longer have a `TypeId` associated with it, becuase `TypeId` can only work for + /// 'static types. This means that it is impossible, once the userdata is created, to get a + /// reference to it back *out* of an `AnyUserData` handle. This also implies that the + /// "function" type methods that can be added via [`UserDataMethods`] (the ones that accept + /// `AnyUserData` as a first parameter) are vastly less useful. Also, there is no way to re-use + /// a single metatable for multiple non-'static types, so there is a higher cost associated with + /// creating the userdata metatable each time a new userdata is created. + /// + /// [`Scope::create_userdata`]: #method.create_userdata + /// [`Lua::create_userdata`]: struct.Lua.html#method.create_userdata + /// [`Lua::scope`]: struct.Lua.html#method.scope + /// [`UserDataMethods`]: trait.UserDataMethods.html + pub fn create_nonstatic_userdata(&self, data: T) -> Result> + where + T: 'scope + UserData, + { + let data = Rc::new(RefCell::new(UserDataWrapped::new(data))); + + // 'callback outliving 'scope is a lie to make the types work out, required due to the + // inability to work with the more correct callback type that is universally quantified over + // 'lua. This is safe though, because `UserData::add_methods` does not get to pick the 'lua + // lifetime, so none of the static methods UserData types can add can possibly capture + // parameters. + fn wrap_method<'scope, 'lua, 'callback: 'scope, T: 'scope>( + scope: &Scope<'lua, 'scope>, + data: Rc>, + method: NonStaticMethod<'callback, T>, + ) -> Result> { + // On methods that actually receive the userdata, we fake a type check on the passed in + // userdata, where we pretend there is a unique type per call to + // `Scope::create_nonstatic_userdata`. You can grab a method from a userdata and call + // it on a mismatched userdata type, which when using normal 'static userdata will fail + // with a type mismatch, but here without this check would proceed as though you had + // called the method on the original value (since we otherwise completely ignore the + // first argument). + let check_data = data.clone(); + let check_ud_type = move |lua: &'callback Lua, value| { + if let Some(Value::UserData(ud)) = value { + unsafe { + assert_stack(lua.state, 1); + lua.push_ref(&ud.0); + ffi::lua_getuservalue(lua.state, -1); + #[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))] + { + ffi::lua_rawgeti(lua.state, -1, 1); + ffi::lua_remove(lua.state, -2); + } + return ffi::lua_touserdata(lua.state, -1) + == check_data.as_ptr() as *mut c_void; + } + } + + false + }; + + match method { + NonStaticMethod::Method(method) => { + let f = Box::new(move |lua, mut args: MultiValue<'callback>| { + if !check_ud_type(lua, args.pop_front()) { + return Err(Error::UserDataTypeMismatch); + } + let data = data + .try_borrow() + .map(|cell| Ref::map(cell, AsRef::as_ref)) + .map_err(|_| Error::UserDataBorrowError)?; + method(lua, &*data, args) + }); + unsafe { scope.create_callback(f) } + } + NonStaticMethod::MethodMut(method) => { + let method = RefCell::new(method); + let f = Box::new(move |lua, mut args: MultiValue<'callback>| { + if !check_ud_type(lua, args.pop_front()) { + return Err(Error::UserDataTypeMismatch); + } + let mut method = method + .try_borrow_mut() + .map_err(|_| Error::RecursiveMutCallback)?; + let mut data = data + .try_borrow_mut() + .map(|cell| RefMut::map(cell, AsMut::as_mut)) + .map_err(|_| Error::UserDataBorrowMutError)?; + (&mut *method)(lua, &mut *data, args) + }); + unsafe { scope.create_callback(f) } + } + NonStaticMethod::Function(function) => unsafe { scope.create_callback(function) }, + NonStaticMethod::FunctionMut(function) => { + let function = RefCell::new(function); + let f = Box::new(move |lua, args| { + (&mut *function + .try_borrow_mut() + .map_err(|_| Error::RecursiveMutCallback)?)( + lua, args + ) + }); + unsafe { scope.create_callback(f) } + } + } + } + + let mut ud_methods = NonStaticUserDataMethods::default(); + T::add_methods(&mut ud_methods); + + unsafe { + let lua = self.lua; + let _sg = StackGuard::new(lua.state); + assert_stack(lua.state, 6); + + push_userdata(lua.state, ())?; + #[cfg(any(feature = "lua54", feature = "lua53"))] + ffi::lua_pushlightuserdata(lua.state, data.as_ptr() as *mut c_void); + #[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))] + protect_lua_closure(lua.state, 0, 1, |state| { + // Lua 5.2/5.1 allows to store only table. Then we will wrap the value. + ffi::lua_createtable(state, 1, 0); + ffi::lua_pushlightuserdata(state, data.as_ptr() as *mut c_void); + ffi::lua_rawseti(state, -2, 1); + })?; + ffi::lua_setuservalue(lua.state, -2); + + protect_lua_closure(lua.state, 0, 1, move |state| { + ffi::lua_newtable(state); + })?; + + for (k, m) in ud_methods.meta_methods { + push_string(lua.state, k.name())?; + lua.push_value(Value::Function(wrap_method(self, data.clone(), m)?))?; + + protect_lua_closure(lua.state, 3, 1, |state| { + ffi::lua_rawset(state, -3); + })?; + } + + if ud_methods.methods.is_empty() { + init_userdata_metatable::<()>(lua.state, -1, None)?; + } else { + protect_lua_closure(lua.state, 0, 1, |state| { + ffi::lua_newtable(state); + })?; + for (k, m) in ud_methods.methods { + push_string(lua.state, &k)?; + lua.push_value(Value::Function(wrap_method(self, data.clone(), m)?))?; + protect_lua_closure(lua.state, 3, 1, |state| { + ffi::lua_rawset(state, -3); + })?; + } + + init_userdata_metatable::<()>(lua.state, -2, Some(-1))?; + ffi::lua_pop(lua.state, 1); + } + + ffi::lua_setmetatable(lua.state, -2); + + Ok(AnyUserData(lua.pop_ref())) + } + } + + // Unsafe, because the callback can improperly capture any value with 'callback scope, such as + // improperly capturing an argument. Since the 'callback lifetime is chosen by the user and the + // lifetime of the callback itself is 'scope (non-'static), the borrow checker will happily pick + // a 'callback that outlives 'scope to allow this. In order for this to be safe, the callback + // must NOT capture any parameters. + unsafe fn create_callback<'callback>( + &self, + f: Callback<'callback, 'scope>, + ) -> Result> { + let f = mem::transmute::, Callback<'lua, 'static>>(f); + let f = self.lua.create_callback(f)?; + + let mut destructors = self.destructors.borrow_mut(); + destructors.push((f.0.clone(), |f| { + let state = f.lua.state; + assert_stack(state, 3); + f.lua.push_ref(&f); + + // We know the destructor has not run yet because we hold a reference to the callback. + + ffi::lua_getupvalue(state, -1, 1); + let ud1 = take_userdata::(state); + ffi::lua_pushnil(state); + ffi::lua_setupvalue(state, -2, 1); + + ffi::lua_getupvalue(state, -1, 2); + let ud2 = take_userdata::(state); + ffi::lua_pushnil(state); + ffi::lua_setupvalue(state, -2, 2); + + ffi::lua_pop(state, 1); + vec![Box::new(ud1), Box::new(ud2)] + })); + Ok(f) + } + + #[cfg(feature = "async")] + unsafe fn create_async_callback<'callback>( + &self, + f: AsyncCallback<'callback, 'scope>, + ) -> Result> { + let f = mem::transmute::, AsyncCallback<'lua, 'static>>(f); + let f = self.lua.create_async_callback(f)?; + + let mut destructors = self.destructors.borrow_mut(); + destructors.push((f.0.clone(), |f| { + let state = f.lua.state; + assert_stack(state, 4); + f.lua.push_ref(&f); + + // We know the destructor has not run yet because we hold a reference to the callback. + + // First, get the environment table + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + ffi::lua_getupvalue(state, -1, 1); + #[cfg(any(feature = "lua51", feature = "luajit"))] + ffi::lua_getfenv(state, -1); + + // Second, get the `get_poll()` closure using the corresponding key + ffi::lua_pushstring(state, cstr!("get_poll")); + ffi::lua_rawget(state, -2); + + // Destroy all upvalues + ffi::lua_getupvalue(state, -1, 1); + let ud1 = take_userdata::(state); + ffi::lua_pushnil(state); + ffi::lua_setupvalue(state, -2, 1); + + ffi::lua_getupvalue(state, -1, 2); + let ud2 = take_userdata::(state); + ffi::lua_pushnil(state); + ffi::lua_setupvalue(state, -2, 2); + + ffi::lua_pop(state, 1); + let mut data: Vec> = vec![Box::new(ud1), Box::new(ud2)]; + + // Finally, get polled future and destroy it + ffi::lua_pushstring(state, cstr!("poll")); + if ffi::lua_rawget(state, -2) == ffi::LUA_TFUNCTION { + ffi::lua_getupvalue(state, -1, 1); + let ud3 = take_userdata::>>(state); + ffi::lua_pushnil(state); + ffi::lua_setupvalue(state, -2, 1); + data.push(Box::new(ud3)); + + ffi::lua_getupvalue(state, -1, 2); + let ud4 = take_userdata::(state); + ffi::lua_pushnil(state); + ffi::lua_setupvalue(state, -2, 2); + data.push(Box::new(ud4)); + } + + data + })); + + Ok(f) + } +} + +impl<'lua, 'scope> Drop for Scope<'lua, 'scope> { + fn drop(&mut self) { + // We separate the action of invalidating the userdata in Lua and actually dropping the + // userdata type into two phases. This is so that, in the event a userdata drop panics, we + // can be sure that all of the userdata in Lua is actually invalidated. + + // All destructors are non-panicking, so this is fine + let to_drop = self + .destructors + .get_mut() + .drain(..) + .flat_map(|(r, dest)| dest(r)) + .collect::>(); + + drop(to_drop); + } +} + +enum NonStaticMethod<'lua, T> { + Method(Box) -> Result>>), + MethodMut(Box) -> Result>>), + Function(Box) -> Result>>), + FunctionMut(Box) -> Result>>), +} + +struct NonStaticUserDataMethods<'lua, T: UserData> { + methods: Vec<(Vec, NonStaticMethod<'lua, T>)>, + meta_methods: Vec<(MetaMethod, NonStaticMethod<'lua, T>)>, +} + +impl<'lua, T: UserData> Default for NonStaticUserDataMethods<'lua, T> { + fn default() -> NonStaticUserDataMethods<'lua, T> { + NonStaticUserDataMethods { + methods: Vec::new(), + meta_methods: Vec::new(), + } + } +} + +impl<'lua, T: UserData> UserDataMethods<'lua, T> for NonStaticUserDataMethods<'lua, T> { + fn add_method(&mut self, name: &S, method: M) + where + S: AsRef<[u8]> + ?Sized, + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result, + { + self.methods.push(( + name.as_ref().to_vec(), + NonStaticMethod::Method(Box::new(move |lua, ud, args| { + method(lua, ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua) + })), + )); + } + + fn add_method_mut(&mut self, name: &S, mut method: M) + where + S: AsRef<[u8]> + ?Sized, + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result, + { + self.methods.push(( + name.as_ref().to_vec(), + NonStaticMethod::MethodMut(Box::new(move |lua, ud, args| { + method(lua, ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua) + })), + )); + } + + #[cfg(feature = "async")] + fn add_async_method(&mut self, _name: &S, _method: M) + where + T: Clone, + S: AsRef<[u8]> + ?Sized, + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + M: 'static + MaybeSend + Fn(&'lua Lua, T, A) -> MR, + MR: 'lua + Future>, + { + // The panic should never happen as async non-static code wouldn't compile + // Non-static lifetime must be bounded to 'lua lifetime + mlua_panic!("asynchronous methods are not supported for non-static userdata") + } + + fn add_function(&mut self, name: &S, function: F) + where + S: AsRef<[u8]> + ?Sized, + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result, + { + self.methods.push(( + name.as_ref().to_vec(), + NonStaticMethod::Function(Box::new(move |lua, args| { + function(lua, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua) + })), + )); + } + + fn add_function_mut(&mut self, name: &S, mut function: F) + where + S: AsRef<[u8]> + ?Sized, + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result, + { + self.methods.push(( + name.as_ref().to_vec(), + NonStaticMethod::FunctionMut(Box::new(move |lua, args| { + function(lua, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua) + })), + )); + } + + #[cfg(feature = "async")] + fn add_async_function(&mut self, _name: &S, _function: F) + where + T: Clone, + S: AsRef<[u8]> + ?Sized, + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + F: 'static + MaybeSend + Fn(&'lua Lua, A) -> FR, + FR: 'lua + Future>, + { + // The panic should never happen as async non-static code wouldn't compile + // Non-static lifetime must be bounded to 'lua lifetime + mlua_panic!("asynchronous functions are not supported for non-static userdata") + } + + fn add_meta_method(&mut self, meta: MetaMethod, method: M) + where + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result, + { + self.meta_methods.push(( + meta, + NonStaticMethod::Method(Box::new(move |lua, ud, args| { + method(lua, ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua) + })), + )); + } + + fn add_meta_method_mut(&mut self, meta: MetaMethod, mut method: M) + where + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result, + { + self.meta_methods.push(( + meta, + NonStaticMethod::MethodMut(Box::new(move |lua, ud, args| { + method(lua, ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua) + })), + )); + } + + fn add_meta_function(&mut self, meta: MetaMethod, function: F) + where + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result, + { + self.meta_methods.push(( + meta, + NonStaticMethod::Function(Box::new(move |lua, args| { + function(lua, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua) + })), + )); + } + + fn add_meta_function_mut(&mut self, meta: MetaMethod, mut function: F) + where + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result, + { + self.meta_methods.push(( + meta, + NonStaticMethod::FunctionMut(Box::new(move |lua, args| { + function(lua, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua) + })), + )); + } +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/src/serde/de.rs b/third_party/cargo/vendor/mlua-0.5.3/src/serde/de.rs new file mode 100644 index 0000000..0da0b20 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/src/serde/de.rs @@ -0,0 +1,329 @@ +use std::string::String as StdString; + +use serde::de::{self, IntoDeserializer}; + +use crate::error::{Error, Result}; +use crate::table::{TablePairs, TableSequence}; +use crate::value::Value; + +/// A struct for deserializing Lua values into Rust values. +pub struct Deserializer<'lua>(pub Value<'lua>); + +impl<'lua, 'de> serde::Deserializer<'de> for Deserializer<'lua> { + type Error = Error; + + #[inline] + fn deserialize_any(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self.0 { + Value::Nil => visitor.visit_unit(), + Value::Boolean(b) => visitor.visit_bool(b), + #[allow(clippy::useless_conversion)] + Value::Integer(i) => visitor.visit_i64(i.into()), + #[allow(clippy::useless_conversion)] + Value::Number(n) => visitor.visit_f64(n.into()), + Value::String(s) => match s.to_str() { + Ok(s) => visitor.visit_str(s), + Err(_) => visitor.visit_bytes(s.as_bytes()), + }, + Value::Table(ref t) if t.raw_len() > 0 || t.is_array() => self.deserialize_seq(visitor), + Value::Table(_) => self.deserialize_map(visitor), + Value::LightUserData(ud) if ud.0.is_null() => visitor.visit_none(), + Value::Function(_) + | Value::Thread(_) + | Value::UserData(_) + | Value::LightUserData(_) + | Value::Error(_) => Err(de::Error::custom("invalid value type")), + } + } + + #[inline] + fn deserialize_option(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self.0 { + Value::Nil => visitor.visit_none(), + Value::LightUserData(ud) if ud.0.is_null() => visitor.visit_none(), + _ => visitor.visit_some(self), + } + } + + #[inline] + fn deserialize_enum( + self, + _name: &str, + _variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + let (variant, value) = match self.0 { + Value::Table(value) => { + let mut iter = value.pairs::(); + let (variant, value) = match iter.next() { + Some(v) => v?, + None => { + return Err(de::Error::invalid_value( + de::Unexpected::Map, + &"map with a single key", + )) + } + }; + + if iter.next().is_some() { + return Err(de::Error::invalid_value( + de::Unexpected::Map, + &"map with a single key", + )); + } + (variant, Some(value)) + } + Value::String(variant) => (variant.to_str()?.to_owned(), None), + _ => return Err(de::Error::custom("bad enum value")), + }; + + visitor.visit_enum(EnumDeserializer { variant, value }) + } + + #[inline] + fn deserialize_seq(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self.0 { + Value::Table(t) => { + let len = t.raw_len() as usize; + let mut deserializer = SeqDeserializer(t.raw_sequence_values()); + let seq = visitor.visit_seq(&mut deserializer)?; + if deserializer.0.count() == 0 { + Ok(seq) + } else { + Err(de::Error::invalid_length( + len, + &"fewer elements in the table", + )) + } + } + _ => Err(de::Error::custom("invalid value type")), + } + } + + #[inline] + fn deserialize_tuple(self, _len: usize, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + self.deserialize_seq(visitor) + } + + #[inline] + fn deserialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + self.deserialize_seq(visitor) + } + + #[inline] + fn deserialize_map(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self.0 { + Value::Table(t) => { + let mut deserializer = MapDeserializer::new(t.pairs()); + let map = visitor.visit_map(&mut deserializer)?; + let count = deserializer.pairs.count(); + if count == 0 { + Ok(map) + } else { + Err(de::Error::invalid_length( + deserializer.processed + count, + &"fewer elements in the table", + )) + } + } + _ => Err(de::Error::custom("invalid value type")), + } + } + + #[inline] + fn deserialize_struct( + self, + _name: &'static str, + _fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + self.deserialize_map(visitor) + } + + serde::forward_to_deserialize_any! { + bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes + byte_buf unit unit_struct newtype_struct + identifier ignored_any + } +} + +struct SeqDeserializer<'lua>(TableSequence<'lua, Value<'lua>>); + +impl<'lua, 'de> de::SeqAccess<'de> for SeqDeserializer<'lua> { + type Error = Error; + + fn next_element_seed(&mut self, seed: T) -> Result> + where + T: de::DeserializeSeed<'de>, + { + match self.0.next() { + Some(value) => seed.deserialize(Deserializer(value?)).map(Some), + None => Ok(None), + } + } + + fn size_hint(&self) -> Option { + match self.0.size_hint() { + (lower, Some(upper)) if lower == upper => Some(upper), + _ => None, + } + } +} + +struct MapDeserializer<'lua> { + pairs: TablePairs<'lua, Value<'lua>, Value<'lua>>, + value: Option>, + processed: usize, +} + +impl<'lua> MapDeserializer<'lua> { + fn new(pairs: TablePairs<'lua, Value<'lua>, Value<'lua>>) -> Self { + MapDeserializer { + pairs, + value: None, + processed: 0, + } + } +} + +impl<'lua, 'de> de::MapAccess<'de> for MapDeserializer<'lua> { + type Error = Error; + + fn next_key_seed(&mut self, seed: T) -> Result> + where + T: de::DeserializeSeed<'de>, + { + match self.pairs.next() { + Some(item) => { + let (key, value) = item?; + self.processed += 1; + self.value = Some(value); + let key_de = Deserializer(key); + seed.deserialize(key_de).map(Some) + } + None => Ok(None), + } + } + + fn next_value_seed(&mut self, seed: T) -> Result + where + T: de::DeserializeSeed<'de>, + { + match self.value.take() { + Some(value) => seed.deserialize(Deserializer(value)), + None => Err(de::Error::custom("value is missing")), + } + } + + fn size_hint(&self) -> Option { + match self.pairs.size_hint() { + (lower, Some(upper)) if lower == upper => Some(upper), + _ => None, + } + } +} + +struct EnumDeserializer<'lua> { + variant: StdString, + value: Option>, +} + +impl<'lua, 'de> de::EnumAccess<'de> for EnumDeserializer<'lua> { + type Error = Error; + type Variant = VariantDeserializer<'lua>; + + fn variant_seed(self, seed: T) -> Result<(T::Value, Self::Variant)> + where + T: de::DeserializeSeed<'de>, + { + let variant = self.variant.into_deserializer(); + let variant_access = VariantDeserializer { value: self.value }; + seed.deserialize(variant).map(|v| (v, variant_access)) + } +} + +struct VariantDeserializer<'lua> { + value: Option>, +} + +impl<'lua, 'de> de::VariantAccess<'de> for VariantDeserializer<'lua> { + type Error = Error; + + fn unit_variant(self) -> Result<()> { + match self.value { + Some(_) => Err(de::Error::invalid_type( + de::Unexpected::NewtypeVariant, + &"unit variant", + )), + None => Ok(()), + } + } + + fn newtype_variant_seed(self, seed: T) -> Result + where + T: de::DeserializeSeed<'de>, + { + match self.value { + Some(value) => seed.deserialize(Deserializer(value)), + None => Err(de::Error::invalid_type( + de::Unexpected::UnitVariant, + &"newtype variant", + )), + } + } + + fn tuple_variant(self, _len: usize, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self.value { + Some(value) => serde::Deserializer::deserialize_seq(Deserializer(value), visitor), + None => Err(de::Error::invalid_type( + de::Unexpected::UnitVariant, + &"tuple variant", + )), + } + } + + fn struct_variant(self, _fields: &'static [&'static str], visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self.value { + Some(value) => serde::Deserializer::deserialize_map(Deserializer(value), visitor), + None => Err(de::Error::invalid_type( + de::Unexpected::UnitVariant, + &"struct variant", + )), + } + } +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/src/serde/mod.rs b/third_party/cargo/vendor/mlua-0.5.3/src/serde/mod.rs new file mode 100644 index 0000000..3163d3d --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/src/serde/mod.rs @@ -0,0 +1,200 @@ +//! (De)Serialization support using serde. + +use std::os::raw::{c_int, c_void}; +use std::ptr; + +use serde::{Deserialize, Serialize}; + +use crate::error::Result; +use crate::ffi; +use crate::lua::Lua; +use crate::table::Table; +use crate::util::{assert_stack, protect_lua, StackGuard}; +use crate::value::Value; + +pub trait LuaSerdeExt<'lua> { + /// A special value (lightuserdata) to encode/decode optional (none) values. + /// + /// Requires `feature = "serialize"` + /// + /// # Example + /// + /// ``` + /// use std::collections::HashMap; + /// use mlua::{Lua, Result, LuaSerdeExt}; + /// + /// fn main() -> Result<()> { + /// let lua = Lua::new(); + /// lua.globals().set("null", lua.null()?)?; + /// + /// let val = lua.load(r#"{a = null}"#).eval()?; + /// let map: HashMap> = lua.from_value(val)?; + /// assert_eq!(map["a"], None); + /// + /// Ok(()) + /// } + /// ``` + fn null(&'lua self) -> Result>; + + /// A metatable attachable to a Lua table to systematically encode it as Array (instead of Map). + /// As result, encoded Array will contain only sequence part of the table, with the same length + /// as the `#` operator on that table. + /// + /// Requires `feature = "serialize"` + /// + /// # Example + /// + /// ``` + /// use mlua::{Lua, Result, LuaSerdeExt}; + /// use serde_json::Value as JsonValue; + /// + /// fn main() -> Result<()> { + /// let lua = Lua::new(); + /// lua.globals().set("array_mt", lua.array_metatable()?)?; + /// + /// // Encode as an empty array (no sequence part in the lua table) + /// let val = lua.load("setmetatable({a = 5}, array_mt)").eval()?; + /// let j: JsonValue = lua.from_value(val)?; + /// assert_eq!(j.to_string(), "[]"); + /// + /// // Encode as object + /// let val = lua.load("{a = 5}").eval()?; + /// let j: JsonValue = lua.from_value(val)?; + /// assert_eq!(j.to_string(), r#"{"a":5}"#); + /// + /// Ok(()) + /// } + /// ``` + fn array_metatable(&'lua self) -> Result>; + + /// Converts `T` into a `Value` instance. + /// + /// Requires `feature = "serialize"` + /// + /// [`Value`]: enum.Value.html + /// + /// # Example + /// + /// ``` + /// use mlua::{Lua, Result, LuaSerdeExt}; + /// use serde::Serialize; + /// + /// #[derive(Serialize)] + /// struct User { + /// name: String, + /// age: u8, + /// } + /// + /// fn main() -> Result<()> { + /// let lua = Lua::new(); + /// let u = User { + /// name: "John Smith".into(), + /// age: 20, + /// }; + /// lua.globals().set("user", lua.to_value(&u)?)?; + /// lua.load(r#" + /// assert(user["name"] == "John Smith") + /// assert(user["age"] == 20) + /// "#).exec() + /// } + /// ``` + fn to_value(&'lua self, t: &T) -> Result>; + + /// Deserializes a `Value` into any serde deserializable object. + /// + /// Requires `feature = "serialize"` + /// + /// [`Value`]: enum.Value.html + /// + /// # Example + /// + /// ``` + /// use mlua::{Lua, Result, LuaSerdeExt}; + /// use serde::Deserialize; + /// + /// #[derive(Deserialize, Debug, PartialEq)] + /// struct User { + /// name: String, + /// age: u8, + /// } + /// + /// fn main() -> Result<()> { + /// let lua = Lua::new(); + /// let val = lua.load(r#"{name = "John Smith", age = 20}"#).eval()?; + /// let u: User = lua.from_value(val)?; + /// + /// assert_eq!(u, User { name: "John Smith".into(), age: 20 }); + /// + /// Ok(()) + /// } + /// ``` + fn from_value>(&'lua self, value: Value<'lua>) -> Result; +} + +impl<'lua> LuaSerdeExt<'lua> for Lua { + fn null(&'lua self) -> Result> { + unsafe { + let _sg = StackGuard::new(self.state); + assert_stack(self.state, 3); + + unsafe extern "C" fn push_null(state: *mut ffi::lua_State) -> c_int { + ffi::lua_pushlightuserdata(state, ptr::null_mut()); + 1 + } + protect_lua(self.state, 0, push_null)?; + Ok(self.pop_value()) + } + } + + fn array_metatable(&'lua self) -> Result> { + unsafe { + let _sg = StackGuard::new(self.state); + assert_stack(self.state, 3); + + unsafe extern "C" fn get_array_mt(state: *mut ffi::lua_State) -> c_int { + push_array_metatable(state); + 1 + } + protect_lua(self.state, 0, get_array_mt)?; + Ok(Table(self.pop_ref())) + } + } + + fn to_value(&'lua self, t: &T) -> Result> + where + T: Serialize + ?Sized, + { + t.serialize(ser::Serializer(self)) + } + + fn from_value(&'lua self, value: Value<'lua>) -> Result + where + T: Deserialize<'lua>, + { + T::deserialize(de::Deserializer(value)) + } +} + +pub(crate) unsafe fn init_metatables(state: *mut ffi::lua_State) { + ffi::lua_pushlightuserdata( + state, + &ARRAY_METATABLE_REGISTRY_KEY as *const u8 as *mut c_void, + ); + ffi::lua_newtable(state); + + ffi::lua_pushstring(state, cstr!("__metatable")); + ffi::lua_pushboolean(state, 0); + ffi::lua_rawset(state, -3); + + ffi::lua_rawset(state, ffi::LUA_REGISTRYINDEX); +} + +pub(crate) unsafe fn push_array_metatable(state: *mut ffi::lua_State) { + let key = &ARRAY_METATABLE_REGISTRY_KEY as *const u8 as *mut c_void; + ffi::lua_rawgetp(state, ffi::LUA_REGISTRYINDEX, key); +} + +static ARRAY_METATABLE_REGISTRY_KEY: u8 = 0; + +pub mod de; +pub mod ser; diff --git a/third_party/cargo/vendor/mlua-0.5.3/src/serde/ser.rs b/third_party/cargo/vendor/mlua-0.5.3/src/serde/ser.rs new file mode 100644 index 0000000..e6f619c --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/src/serde/ser.rs @@ -0,0 +1,366 @@ +use std::os::raw::c_int; + +use serde::{ser, Serialize}; + +use super::LuaSerdeExt; +use crate::error::{Error, Result}; +use crate::ffi; +use crate::lua::Lua; +use crate::string::String; +use crate::table::Table; +use crate::types::Integer; +use crate::util::{assert_stack, protect_lua, StackGuard}; +use crate::value::{ToLua, Value}; + +/// A struct for serializing Rust values into Lua values. +pub struct Serializer<'lua>(pub &'lua Lua); + +macro_rules! lua_serialize_number { + ($name:ident, $t:ty) => { + #[inline] + fn $name(self, value: $t) -> Result> { + value.to_lua(self.0) + } + }; +} + +impl<'lua> ser::Serializer for Serializer<'lua> { + type Ok = Value<'lua>; + type Error = Error; + + // Associated types for keeping track of additional state while serializing + // compound data structures like sequences and maps. + type SerializeSeq = SerializeVec<'lua>; + type SerializeTuple = SerializeVec<'lua>; + type SerializeTupleStruct = SerializeVec<'lua>; + type SerializeTupleVariant = SerializeTupleVariant<'lua>; + type SerializeMap = SerializeMap<'lua>; + type SerializeStruct = SerializeMap<'lua>; + type SerializeStructVariant = SerializeStructVariant<'lua>; + + #[inline] + fn serialize_bool(self, value: bool) -> Result> { + Ok(Value::Boolean(value)) + } + + lua_serialize_number!(serialize_i8, i8); + lua_serialize_number!(serialize_u8, u8); + lua_serialize_number!(serialize_i16, i16); + lua_serialize_number!(serialize_u16, u16); + lua_serialize_number!(serialize_i32, i32); + lua_serialize_number!(serialize_u32, u32); + lua_serialize_number!(serialize_i64, i64); + lua_serialize_number!(serialize_u64, u64); + + lua_serialize_number!(serialize_f32, f32); + lua_serialize_number!(serialize_f64, f64); + + #[inline] + fn serialize_char(self, value: char) -> Result> { + self.serialize_str(&value.to_string()) + } + + #[inline] + fn serialize_str(self, value: &str) -> Result> { + self.0.create_string(value).map(Value::String) + } + + #[inline] + fn serialize_bytes(self, value: &[u8]) -> Result> { + self.0.create_string(value).map(Value::String) + } + + #[inline] + fn serialize_none(self) -> Result> { + self.0.null() + } + + #[inline] + fn serialize_some(self, value: &T) -> Result> + where + T: ?Sized + Serialize, + { + value.serialize(self) + } + + #[inline] + fn serialize_unit(self) -> Result> { + self.0.null() + } + + #[inline] + fn serialize_unit_struct(self, _name: &'static str) -> Result> { + self.0.null() + } + + #[inline] + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + ) -> Result> { + self.serialize_str(variant) + } + + #[inline] + fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> Result> + where + T: ?Sized + Serialize, + { + value.serialize(self) + } + + #[inline] + fn serialize_newtype_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + value: &T, + ) -> Result> + where + T: ?Sized + Serialize, + { + let table = self.0.create_table()?; + let variant = self.0.create_string(variant)?; + let value = self.0.to_value(value)?; + table.raw_set(variant, value)?; + Ok(Value::Table(table)) + } + + #[inline] + fn serialize_seq(self, len: Option) -> Result { + let len = len.unwrap_or(0) as c_int; + let table = self.0.create_table_with_capacity(len, 0)?; + table.set_metatable(Some(self.0.array_metatable()?)); + Ok(SerializeVec { table }) + } + + #[inline] + fn serialize_tuple(self, len: usize) -> Result { + self.serialize_seq(Some(len)) + } + + #[inline] + fn serialize_tuple_struct( + self, + _name: &'static str, + len: usize, + ) -> Result { + self.serialize_seq(Some(len)) + } + + #[inline] + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + _len: usize, + ) -> Result { + let name = self.0.create_string(variant)?; + let table = self.0.create_table()?; + Ok(SerializeTupleVariant { name, table }) + } + + #[inline] + fn serialize_map(self, len: Option) -> Result { + let len = len.unwrap_or(0) as c_int; + Ok(SerializeMap { + key: None, + table: self.0.create_table_with_capacity(0, len)?, + }) + } + + #[inline] + fn serialize_struct(self, _name: &'static str, len: usize) -> Result { + self.serialize_map(Some(len)) + } + + #[inline] + fn serialize_struct_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result { + let name = self.0.create_string(variant)?; + let table = self.0.create_table_with_capacity(0, len as c_int)?; + Ok(SerializeStructVariant { name, table }) + } +} + +pub struct SerializeVec<'lua> { + table: Table<'lua>, +} + +impl<'lua> ser::SerializeSeq for SerializeVec<'lua> { + type Ok = Value<'lua>; + type Error = Error; + + fn serialize_element(&mut self, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + let lua = self.table.0.lua; + let value = lua.to_value(value)?; + unsafe { + let _sg = StackGuard::new(lua.state); + assert_stack(lua.state, 4); + + lua.push_ref(&self.table.0); + lua.push_value(value)?; + + unsafe extern "C" fn push_to_table(state: *mut ffi::lua_State) -> c_int { + let len = ffi::lua_rawlen(state, -2) as Integer; + ffi::lua_rawseti(state, -2, len + 1); + 1 + } + + protect_lua(lua.state, 2, push_to_table) + } + } + + fn end(self) -> Result> { + Ok(Value::Table(self.table)) + } +} + +impl<'lua> ser::SerializeTuple for SerializeVec<'lua> { + type Ok = Value<'lua>; + type Error = Error; + + fn serialize_element(&mut self, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + ser::SerializeSeq::serialize_element(self, value) + } + + fn end(self) -> Result> { + ser::SerializeSeq::end(self) + } +} + +impl<'lua> ser::SerializeTupleStruct for SerializeVec<'lua> { + type Ok = Value<'lua>; + type Error = Error; + + fn serialize_field(&mut self, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + ser::SerializeSeq::serialize_element(self, value) + } + + fn end(self) -> Result> { + ser::SerializeSeq::end(self) + } +} + +pub struct SerializeTupleVariant<'lua> { + name: String<'lua>, + table: Table<'lua>, +} + +impl<'lua> ser::SerializeTupleVariant for SerializeTupleVariant<'lua> { + type Ok = Value<'lua>; + type Error = Error; + + fn serialize_field(&mut self, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + let lua = self.table.0.lua; + let idx = self.table.raw_len() + 1; + self.table.raw_insert(idx, lua.to_value(value)?) + } + + fn end(self) -> Result> { + let lua = self.table.0.lua; + let table = lua.create_table()?; + table.raw_set(self.name, self.table)?; + Ok(Value::Table(table)) + } +} + +pub struct SerializeMap<'lua> { + table: Table<'lua>, + key: Option>, +} + +impl<'lua> ser::SerializeMap for SerializeMap<'lua> { + type Ok = Value<'lua>; + type Error = Error; + + fn serialize_key(&mut self, key: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + let lua = self.table.0.lua; + self.key = Some(lua.to_value(key)?); + Ok(()) + } + + fn serialize_value(&mut self, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + let lua = self.table.0.lua; + let key = mlua_expect!( + self.key.take(), + "serialize_value called before serialize_key" + ); + let value = lua.to_value(value)?; + self.table.raw_set(key, value) + } + + fn end(self) -> Result> { + Ok(Value::Table(self.table)) + } +} + +impl<'lua> ser::SerializeStruct for SerializeMap<'lua> { + type Ok = Value<'lua>; + type Error = Error; + + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + ser::SerializeMap::serialize_key(self, key)?; + ser::SerializeMap::serialize_value(self, value) + } + + fn end(self) -> Result> { + ser::SerializeMap::end(self) + } +} + +pub struct SerializeStructVariant<'lua> { + name: String<'lua>, + table: Table<'lua>, +} + +impl<'lua> ser::SerializeStructVariant for SerializeStructVariant<'lua> { + type Ok = Value<'lua>; + type Error = Error; + + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + let lua = self.table.0.lua; + self.table.raw_set(key, lua.to_value(value)?)?; + Ok(()) + } + + fn end(self) -> Result> { + let lua = self.table.0.lua; + let table = lua.create_table()?; + table.raw_set(self.name, self.table)?; + Ok(Value::Table(table)) + } +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/src/stdlib.rs b/third_party/cargo/vendor/mlua-0.5.3/src/stdlib.rs new file mode 100644 index 0000000..9b20f4c --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/src/stdlib.rs @@ -0,0 +1,99 @@ +use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign}; +use std::u32; + +/// Flags describing the set of lua standard libraries to load. +#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] +pub struct StdLib(u32); + +impl StdLib { + /// [`coroutine`](https://www.lua.org/manual/5.3/manual.html#6.2) library + /// + /// Requires `feature = "lua54/lua53/lua52"` + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52", doc))] + pub const COROUTINE: StdLib = StdLib(1); + /// [`table`](https://www.lua.org/manual/5.3/manual.html#6.6) library + pub const TABLE: StdLib = StdLib(1 << 1); + /// [`io`](https://www.lua.org/manual/5.3/manual.html#6.8) library + pub const IO: StdLib = StdLib(1 << 2); + /// [`os`](https://www.lua.org/manual/5.3/manual.html#6.9) library + pub const OS: StdLib = StdLib(1 << 3); + /// [`string`](https://www.lua.org/manual/5.3/manual.html#6.4) library + pub const STRING: StdLib = StdLib(1 << 4); + /// [`utf8`](https://www.lua.org/manual/5.3/manual.html#6.5) library + /// + /// Requires `feature = "lua54/lua53"` + #[cfg(any(feature = "lua54", feature = "lua53", doc))] + pub const UTF8: StdLib = StdLib(1 << 5); + /// [`bit`](https://www.lua.org/manual/5.2/manual.html#6.7) library + /// + /// Requires `feature = "lua52/luajit"` + #[cfg(any(feature = "lua52", feature = "luajit", doc))] + pub const BIT: StdLib = StdLib(1 << 6); + /// [`math`](https://www.lua.org/manual/5.3/manual.html#6.7) library + pub const MATH: StdLib = StdLib(1 << 7); + /// [`package`](https://www.lua.org/manual/5.3/manual.html#6.3) library + pub const PACKAGE: StdLib = StdLib(1 << 8); + /// [`jit`](http://luajit.org/ext_jit.html) library + /// + /// Requires `feature = "luajit"` + #[cfg(any(feature = "luajit", doc))] + pub const JIT: StdLib = StdLib(1 << 9); + + /// (unsafe) [`ffi`](http://luajit.org/ext_ffi.html) library + /// + /// Requires `feature = "luajit"` + #[cfg(any(feature = "luajit", doc))] + pub const FFI: StdLib = StdLib(1 << 30); + /// (unsafe) [`debug`](https://www.lua.org/manual/5.3/manual.html#6.10) library + pub const DEBUG: StdLib = StdLib(1 << 31); + + /// No libraries + pub const NONE: StdLib = StdLib(0); + /// (unsafe) All standard libraries + pub const ALL: StdLib = StdLib(u32::MAX); + /// The safe subset of the standard libraries + pub const ALL_SAFE: StdLib = StdLib((1 << 30) - 1); + + pub fn contains(self, lib: Self) -> bool { + (self & lib).0 != 0 + } +} + +impl BitAnd for StdLib { + type Output = Self; + fn bitand(self, rhs: Self) -> Self::Output { + StdLib(self.0 & rhs.0) + } +} + +impl BitAndAssign for StdLib { + fn bitand_assign(&mut self, rhs: Self) { + *self = StdLib(self.0 & rhs.0) + } +} + +impl BitOr for StdLib { + type Output = Self; + fn bitor(self, rhs: Self) -> Self::Output { + StdLib(self.0 | rhs.0) + } +} + +impl BitOrAssign for StdLib { + fn bitor_assign(&mut self, rhs: Self) { + *self = StdLib(self.0 | rhs.0) + } +} + +impl BitXor for StdLib { + type Output = Self; + fn bitxor(self, rhs: Self) -> Self::Output { + StdLib(self.0 ^ rhs.0) + } +} + +impl BitXorAssign for StdLib { + fn bitxor_assign(&mut self, rhs: Self) { + *self = StdLib(self.0 ^ rhs.0) + } +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/src/string.rs b/third_party/cargo/vendor/mlua-0.5.3/src/string.rs new file mode 100644 index 0000000..37e0c3d --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/src/string.rs @@ -0,0 +1,126 @@ +use std::{slice, str}; + +#[cfg(feature = "serialize")] +use { + serde::ser::{Serialize, Serializer}, + std::result::Result as StdResult, +}; + +use crate::error::{Error, Result}; +use crate::ffi; +use crate::types::LuaRef; +use crate::util::{assert_stack, StackGuard}; + +/// Handle to an internal Lua string. +/// +/// Unlike Rust strings, Lua strings may not be valid UTF-8. +#[derive(Clone, Debug)] +pub struct String<'lua>(pub(crate) LuaRef<'lua>); + +impl<'lua> String<'lua> { + /// Get a `&str` slice if the Lua string is valid UTF-8. + /// + /// # Examples + /// + /// ``` + /// # use mlua::{Lua, Result, String}; + /// # fn main() -> Result<()> { + /// # let lua = Lua::new(); + /// let globals = lua.globals(); + /// + /// let version: String = globals.get("_VERSION")?; + /// assert!(version.to_str()?.contains("Lua")); + /// + /// let non_utf8: String = lua.load(r#" "test\255" "#).eval()?; + /// assert!(non_utf8.to_str().is_err()); + /// # Ok(()) + /// # } + /// ``` + pub fn to_str(&self) -> Result<&str> { + str::from_utf8(self.as_bytes()).map_err(|e| Error::FromLuaConversionError { + from: "string", + to: "&str", + message: Some(e.to_string()), + }) + } + + /// Get the bytes that make up this string. + /// + /// The returned slice will not contain the terminating nul byte, but will contain any nul + /// bytes embedded into the Lua string. + /// + /// # Examples + /// + /// ``` + /// # use mlua::{Lua, Result, String}; + /// # fn main() -> Result<()> { + /// # let lua = Lua::new(); + /// let non_utf8: String = lua.load(r#" "test\255" "#).eval()?; + /// assert!(non_utf8.to_str().is_err()); // oh no :( + /// assert_eq!(non_utf8.as_bytes(), &b"test\xff"[..]); + /// # Ok(()) + /// # } + /// ``` + pub fn as_bytes(&self) -> &[u8] { + let nulled = self.as_bytes_with_nul(); + &nulled[..nulled.len() - 1] + } + + /// Get the bytes that make up this string, including the trailing nul byte. + pub fn as_bytes_with_nul(&self) -> &[u8] { + let lua = self.0.lua; + unsafe { + let _sg = StackGuard::new(lua.state); + assert_stack(lua.state, 1); + + lua.push_ref(&self.0); + mlua_debug_assert!( + ffi::lua_type(lua.state, -1) == ffi::LUA_TSTRING, + "string ref is not string type" + ); + + let mut size = 0; + // This will not trigger a 'm' error, because the reference is guaranteed to be of + // string type + let data = ffi::lua_tolstring(lua.state, -1, &mut size); + + slice::from_raw_parts(data as *const u8, size + 1) + } + } +} + +impl<'lua> AsRef<[u8]> for String<'lua> { + fn as_ref(&self) -> &[u8] { + self.as_bytes() + } +} + +// Lua strings are basically &[u8] slices, so implement PartialEq for anything resembling that. +// +// This makes our `String` comparable with `Vec`, `[u8]`, `&str`, `String` and `mlua::String` +// itself. +// +// The only downside is that this disallows a comparison with `Cow`, as that only implements +// `AsRef`, which collides with this impl. Requiring `AsRef` would fix that, but limit us +// in other ways. +impl<'lua, T> PartialEq for String<'lua> +where + T: AsRef<[u8]>, +{ + fn eq(&self, other: &T) -> bool { + self.as_bytes() == other.as_ref() + } +} + +#[cfg(feature = "serialize")] +impl<'lua> Serialize for String<'lua> { + fn serialize(&self, serializer: S) -> StdResult + where + S: Serializer, + { + match self.to_str() { + Ok(s) => serializer.serialize_str(s), + Err(_) => serializer.serialize_bytes(self.as_bytes()), + } + } +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/src/table.rs b/third_party/cargo/vendor/mlua-0.5.3/src/table.rs new file mode 100644 index 0000000..9c57ca8 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/src/table.rs @@ -0,0 +1,778 @@ +use std::marker::PhantomData; +use std::os::raw::c_int; + +#[cfg(feature = "serialize")] +use { + serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer}, + std::result::Result as StdResult, +}; + +use crate::error::{Error, Result}; +use crate::ffi; +use crate::function::Function; +use crate::types::{Integer, LuaRef}; +use crate::util::{assert_stack, protect_lua, protect_lua_closure, StackGuard}; +use crate::value::{FromLua, FromLuaMulti, Nil, ToLua, ToLuaMulti, Value}; + +#[cfg(feature = "async")] +use {futures_core::future::LocalBoxFuture, futures_util::future}; + +/// Handle to an internal Lua table. +#[derive(Clone, Debug)] +pub struct Table<'lua>(pub(crate) LuaRef<'lua>); + +#[allow(clippy::len_without_is_empty)] +impl<'lua> Table<'lua> { + /// Sets a key-value pair in the table. + /// + /// If the value is `nil`, this will effectively remove the pair. + /// + /// This might invoke the `__newindex` metamethod. Use the [`raw_set`] method if that is not + /// desired. + /// + /// # Examples + /// + /// Export a value as a global to make it usable from Lua: + /// + /// ``` + /// # use mlua::{Lua, Result}; + /// # fn main() -> Result<()> { + /// # let lua = Lua::new(); + /// let globals = lua.globals(); + /// + /// globals.set("assertions", cfg!(debug_assertions))?; + /// + /// lua.load(r#" + /// if assertions == true then + /// -- ... + /// elseif assertions == false then + /// -- ... + /// else + /// error("assertions neither on nor off?") + /// end + /// "#).exec()?; + /// # Ok(()) + /// # } + /// ``` + /// + /// [`raw_set`]: #method.raw_set + pub fn set, V: ToLua<'lua>>(&self, key: K, value: V) -> Result<()> { + let lua = self.0.lua; + let key = key.to_lua(lua)?; + let value = value.to_lua(lua)?; + unsafe { + let _sg = StackGuard::new(lua.state); + assert_stack(lua.state, 6); + + lua.push_ref(&self.0); + lua.push_value(key)?; + lua.push_value(value)?; + + unsafe extern "C" fn set_table(state: *mut ffi::lua_State) -> c_int { + ffi::lua_settable(state, -3); + 1 + } + protect_lua(lua.state, 3, set_table) + } + } + + /// Gets the value associated to `key` from the table. + /// + /// If no value is associated to `key`, returns the `nil` value. + /// + /// This might invoke the `__index` metamethod. Use the [`raw_get`] method if that is not + /// desired. + /// + /// # Examples + /// + /// Query the version of the Lua interpreter: + /// + /// ``` + /// # use mlua::{Lua, Result}; + /// # fn main() -> Result<()> { + /// # let lua = Lua::new(); + /// let globals = lua.globals(); + /// + /// let version: String = globals.get("_VERSION")?; + /// println!("Lua version: {}", version); + /// # Ok(()) + /// # } + /// ``` + /// + /// [`raw_get`]: #method.raw_get + pub fn get, V: FromLua<'lua>>(&self, key: K) -> Result { + let lua = self.0.lua; + let key = key.to_lua(lua)?; + let value = unsafe { + let _sg = StackGuard::new(lua.state); + assert_stack(lua.state, 5); + + lua.push_ref(&self.0); + lua.push_value(key)?; + + unsafe extern "C" fn get_table(state: *mut ffi::lua_State) -> c_int { + ffi::lua_gettable(state, -2); + 1 + } + protect_lua(lua.state, 2, get_table)?; + lua.pop_value() + }; + V::from_lua(value, lua) + } + + /// Checks whether the table contains a non-nil value for `key`. + pub fn contains_key>(&self, key: K) -> Result { + let lua = self.0.lua; + let key = key.to_lua(lua)?; + + unsafe { + let _sg = StackGuard::new(lua.state); + assert_stack(lua.state, 5); + + lua.push_ref(&self.0); + lua.push_value(key)?; + + unsafe extern "C" fn get_table(state: *mut ffi::lua_State) -> c_int { + ffi::lua_gettable(state, -2); + 1 + } + protect_lua(lua.state, 2, get_table)?; + + let has = ffi::lua_isnil(lua.state, -1) == 0; + Ok(has) + } + } + + /// Compares two tables for equality. + /// + /// Tables are compared by reference first. + /// If they are not primitively equals, then mlua will try to invoke the `__eq` metamethod. + /// mlua will check `self` first for the metamethod, then `other` if not found. + /// + /// # Examples + /// + /// Compare two tables using `__eq` metamethod: + /// + /// ``` + /// # use mlua::{Lua, Result, Table}; + /// # fn main() -> Result<()> { + /// # let lua = Lua::new(); + /// let table1 = lua.create_table()?; + /// table1.set(1, "value")?; + /// + /// let table2 = lua.create_table()?; + /// table2.set(2, "value")?; + /// + /// let always_equals_mt = lua.create_table()?; + /// always_equals_mt.set("__eq", lua.create_function(|_, (_t1, _t2): (Table, Table)| Ok(true))?)?; + /// table2.set_metatable(Some(always_equals_mt)); + /// + /// assert!(table1.equals(&table1.clone())?); + /// assert!(table1.equals(&table2)?); + /// # Ok(()) + /// # } + /// ``` + pub fn equals>(&self, other: T) -> Result { + let other = other.as_ref(); + if self == other { + return Ok(true); + } + + // Compare using __eq metamethod if exists + // First, check the self for the metamethod. + // If self does not define it, then check the other table. + if let Some(mt) = self.get_metatable() { + if mt.contains_key("__eq")? { + return mt + .get::<_, Function>("__eq")? + .call((self.clone(), other.clone())); + } + } + if let Some(mt) = other.get_metatable() { + if mt.contains_key("__eq")? { + return mt + .get::<_, Function>("__eq")? + .call((self.clone(), other.clone())); + } + } + + Ok(false) + } + + /// Sets a key-value pair without invoking metamethods. + pub fn raw_set, V: ToLua<'lua>>(&self, key: K, value: V) -> Result<()> { + let lua = self.0.lua; + let key = key.to_lua(lua)?; + let value = value.to_lua(lua)?; + + unsafe { + let _sg = StackGuard::new(lua.state); + assert_stack(lua.state, 6); + + lua.push_ref(&self.0); + lua.push_value(key)?; + lua.push_value(value)?; + + unsafe extern "C" fn raw_set(state: *mut ffi::lua_State) -> c_int { + ffi::lua_rawset(state, -3); + 0 + } + protect_lua(lua.state, 3, raw_set)?; + + Ok(()) + } + } + + /// Gets the value associated to `key` without invoking metamethods. + pub fn raw_get, V: FromLua<'lua>>(&self, key: K) -> Result { + let lua = self.0.lua; + let key = key.to_lua(lua)?; + let value = unsafe { + let _sg = StackGuard::new(lua.state); + assert_stack(lua.state, 3); + + lua.push_ref(&self.0); + lua.push_value(key)?; + ffi::lua_rawget(lua.state, -2); + lua.pop_value() + }; + V::from_lua(value, lua) + } + + /// Inserts element value at position `idx` to the table, shifting up the elements from `table[idx]`. + /// The worst case complexity is O(n), where n is the table length. + pub fn raw_insert>(&self, idx: Integer, value: V) -> Result<()> { + let lua = self.0.lua; + let size = self.raw_len(); + if idx < 1 || idx > size + 1 { + return Err(Error::RuntimeError("index out of bounds".to_string())); + } + + let value = value.to_lua(lua)?; + unsafe { + let _sg = StackGuard::new(lua.state); + assert_stack(lua.state, 6); + + lua.push_ref(&self.0); + lua.push_value(value)?; + + protect_lua_closure(lua.state, 2, 0, |state| { + for i in (idx..size + 1).rev() { + // table[i+1] = table[i] + ffi::lua_rawgeti(state, -2, i); + ffi::lua_rawseti(state, -3, i + 1); + } + ffi::lua_rawseti(state, -2, idx); + }) + } + } + + /// Removes a key from the table. + /// + /// If `key` is an integer, mlua shifts down the elements from `table[key+1]`, + /// and erases element `table[key]`. The complexity is O(n) in worst case, + /// where n is the table length. + /// + /// For othey key types this is equivalent to setting `table[key] = nil`. + pub fn raw_remove>(&self, key: K) -> Result<()> { + let lua = self.0.lua; + let key = key.to_lua(lua)?; + match key { + Value::Integer(idx) => { + let size = self.raw_len(); + if idx < 1 || idx > size { + return Err(Error::RuntimeError("index out of bounds".to_string())); + } + unsafe { + let _sg = StackGuard::new(lua.state); + assert_stack(lua.state, 6); + + lua.push_ref(&self.0); + + protect_lua_closure(lua.state, 1, 0, |state| { + for i in idx..size { + ffi::lua_rawgeti(state, -1, i + 1); + ffi::lua_rawseti(state, -2, i); + } + ffi::lua_pushnil(state); + ffi::lua_rawseti(state, -2, size); + }) + } + } + _ => self.raw_set(key, Nil), + } + } + + /// Returns the result of the Lua `#` operator. + /// + /// This might invoke the `__len` metamethod. Use the [`raw_len`] method if that is not desired. + /// + /// [`raw_len`]: #method.raw_len + pub fn len(&self) -> Result { + let lua = self.0.lua; + unsafe { + let _sg = StackGuard::new(lua.state); + assert_stack(lua.state, 4); + lua.push_ref(&self.0); + protect_lua_closure(lua.state, 1, 0, |state| ffi::luaL_len(state, -1)) + } + } + + /// Returns the result of the Lua `#` operator, without invoking the `__len` metamethod. + pub fn raw_len(&self) -> Integer { + let lua = self.0.lua; + unsafe { + let _sg = StackGuard::new(lua.state); + assert_stack(lua.state, 1); + lua.push_ref(&self.0); + let len = ffi::lua_rawlen(lua.state, -1); + len as Integer + } + } + + /// Returns a reference to the metatable of this table, or `None` if no metatable is set. + /// + /// Unlike the `getmetatable` Lua function, this method ignores the `__metatable` field. + pub fn get_metatable(&self) -> Option> { + let lua = self.0.lua; + unsafe { + let _sg = StackGuard::new(lua.state); + assert_stack(lua.state, 1); + lua.push_ref(&self.0); + if ffi::lua_getmetatable(lua.state, -1) == 0 { + None + } else { + let table = Table(lua.pop_ref()); + Some(table) + } + } + } + + /// Sets or removes the metatable of this table. + /// + /// If `metatable` is `None`, the metatable is removed (if no metatable is set, this does + /// nothing). + pub fn set_metatable(&self, metatable: Option>) { + let lua = self.0.lua; + unsafe { + let _sg = StackGuard::new(lua.state); + assert_stack(lua.state, 1); + lua.push_ref(&self.0); + if let Some(metatable) = metatable { + lua.push_ref(&metatable.0); + } else { + ffi::lua_pushnil(lua.state); + } + ffi::lua_setmetatable(lua.state, -2); + } + } + + /// Consume this table and return an iterator over the pairs of the table. + /// + /// This works like the Lua `pairs` function, but does not invoke the `__pairs` metamethod. + /// + /// The pairs are wrapped in a [`Result`], since they are lazily converted to `K` and `V` types. + /// + /// # Note + /// + /// While this method consumes the `Table` object, it can not prevent code from mutating the + /// table while the iteration is in progress. Refer to the [Lua manual] for information about + /// the consequences of such mutation. + /// + /// # Examples + /// + /// Iterate over all globals: + /// + /// ``` + /// # use mlua::{Lua, Result, Value}; + /// # fn main() -> Result<()> { + /// # let lua = Lua::new(); + /// let globals = lua.globals(); + /// + /// for pair in globals.pairs::() { + /// let (key, value) = pair?; + /// # let _ = (key, value); // used + /// // ... + /// } + /// # Ok(()) + /// # } + /// ``` + /// + /// [`Result`]: type.Result.html + /// [Lua manual]: http://www.lua.org/manual/5.3/manual.html#pdf-next + pub fn pairs, V: FromLua<'lua>>(self) -> TablePairs<'lua, K, V> { + TablePairs { + table: self.0, + next_key: Some(Nil), + _phantom: PhantomData, + } + } + + /// Consume this table and return an iterator over all values in the sequence part of the table. + /// + /// The iterator will yield all values `t[1]`, `t[2]`, and so on, until a `nil` value is + /// encountered. This mirrors the behaviour of Lua's `ipairs` function and will invoke the + /// `__index` metamethod according to the usual rules. However, the deprecated `__ipairs` + /// metatable will not be called. + /// + /// Just like [`pairs`], the values are wrapped in a [`Result`]. + /// + /// # Note + /// + /// While this method consumes the `Table` object, it can not prevent code from mutating the + /// table while the iteration is in progress. Refer to the [Lua manual] for information about + /// the consequences of such mutation. + /// + /// # Examples + /// + /// ``` + /// # use mlua::{Lua, Result, Table}; + /// # fn main() -> Result<()> { + /// # let lua = Lua::new(); + /// let my_table: Table = lua.load(r#" + /// { + /// [1] = 4, + /// [2] = 5, + /// [4] = 7, + /// key = 2 + /// } + /// "#).eval()?; + /// + /// let expected = [4, 5]; + /// for (&expected, got) in expected.iter().zip(my_table.sequence_values::()) { + /// assert_eq!(expected, got?); + /// } + /// # Ok(()) + /// # } + /// ``` + /// + /// [`pairs`]: #method.pairs + /// [`Result`]: type.Result.html + /// [Lua manual]: http://www.lua.org/manual/5.3/manual.html#pdf-next + pub fn sequence_values>(self) -> TableSequence<'lua, V> { + TableSequence { + table: self.0, + index: Some(1), + len: None, + raw: false, + _phantom: PhantomData, + } + } + + /// Consume this table and return an iterator over all values in the sequence part of the table. + /// + /// Unlike the `sequence_values`, does not invoke `__index` metamethod when iterating. + /// + /// [`sequence_values`]: #method.sequence_values + pub fn raw_sequence_values>(self) -> TableSequence<'lua, V> { + TableSequence { + table: self.0, + index: Some(1), + len: None, + raw: true, + _phantom: PhantomData, + } + } + + pub(crate) fn raw_sequence_values_by_len>( + self, + len: Option, + ) -> TableSequence<'lua, V> { + let len = len.unwrap_or_else(|| self.raw_len()); + TableSequence { + table: self.0, + index: Some(1), + len: Some(len), + raw: true, + _phantom: PhantomData, + } + } + + #[cfg(feature = "serialize")] + pub(crate) fn is_array(&self) -> bool { + let lua = self.0.lua; + unsafe { + let _sg = StackGuard::new(lua.state); + assert_stack(lua.state, 3); + lua.push_ref(&self.0); + if ffi::lua_getmetatable(lua.state, -1) == 0 { + return false; + } + crate::serde::push_array_metatable(lua.state); + ffi::lua_rawequal(lua.state, -1, -2) != 0 + } + } +} + +impl<'lua> PartialEq for Table<'lua> { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} + +impl<'lua> AsRef> for Table<'lua> { + #[inline] + fn as_ref(&self) -> &Self { + self + } +} + +/// An extension trait for `Table`s that provides a variety of convenient functionality. +pub trait TableExt<'lua> { + /// Gets the function associated to `key` from the table and executes it, + /// passing the table itself along with `args` as function arguments. + /// + /// This is a shortcut for + /// `table.get::<_, Function>(key)?.call((table.clone(), arg1, ..., argN))` + /// + /// This might invoke the `__index` metamethod. + fn call_method(&self, key: K, args: A) -> Result + where + K: ToLua<'lua>, + A: ToLuaMulti<'lua>, + R: FromLuaMulti<'lua>; + + /// Gets the function associated to `key` from the table and executes it, + /// passing `args` as function arguments. + /// + /// This is a shortcut for + /// `table.get::<_, Function>(key)?.call(args)` + /// + /// This might invoke the `__index` metamethod. + fn call_function(&self, key: K, args: A) -> Result + where + K: ToLua<'lua>, + A: ToLuaMulti<'lua>, + R: FromLuaMulti<'lua>; + + /// Gets the function associated to `key` from the table and asynchronously executes it, + /// passing the table itself along with `args` as function arguments and returning Future. + /// + /// Requires `feature = "async"` + /// + /// This might invoke the `__index` metamethod. + #[cfg(feature = "async")] + #[cfg_attr(docsrs, doc(cfg(feature = "async")))] + fn call_async_method<'fut, K, A, R>(&self, key: K, args: A) -> LocalBoxFuture<'fut, Result> + where + 'lua: 'fut, + K: ToLua<'lua>, + A: ToLuaMulti<'lua>, + R: FromLuaMulti<'lua> + 'fut; + + /// Gets the function associated to `key` from the table and asynchronously executes it, + /// passing `args` as function arguments and returning Future. + /// + /// Requires `feature = "async"` + /// + /// This might invoke the `__index` metamethod. + #[cfg(feature = "async")] + #[cfg_attr(docsrs, doc(cfg(feature = "async")))] + fn call_async_function<'fut, K, A, R>( + &self, + key: K, + args: A, + ) -> LocalBoxFuture<'fut, Result> + where + 'lua: 'fut, + K: ToLua<'lua>, + A: ToLuaMulti<'lua>, + R: FromLuaMulti<'lua> + 'fut; +} + +impl<'lua> TableExt<'lua> for Table<'lua> { + fn call_method(&self, key: K, args: A) -> Result + where + K: ToLua<'lua>, + A: ToLuaMulti<'lua>, + R: FromLuaMulti<'lua>, + { + let lua = self.0.lua; + let mut args = args.to_lua_multi(lua)?; + args.push_front(Value::Table(self.clone())); + self.get::<_, Function>(key)?.call(args) + } + + fn call_function(&self, key: K, args: A) -> Result + where + K: ToLua<'lua>, + A: ToLuaMulti<'lua>, + R: FromLuaMulti<'lua>, + { + self.get::<_, Function>(key)?.call(args) + } + + #[cfg(feature = "async")] + fn call_async_method<'fut, K, A, R>(&self, key: K, args: A) -> LocalBoxFuture<'fut, Result> + where + 'lua: 'fut, + K: ToLua<'lua>, + A: ToLuaMulti<'lua>, + R: FromLuaMulti<'lua> + 'fut, + { + let lua = self.0.lua; + let mut args = match args.to_lua_multi(lua) { + Ok(args) => args, + Err(e) => return Box::pin(future::err(e)), + }; + args.push_front(Value::Table(self.clone())); + self.call_async_function(key, args) + } + + #[cfg(feature = "async")] + fn call_async_function<'fut, K, A, R>(&self, key: K, args: A) -> LocalBoxFuture<'fut, Result> + where + 'lua: 'fut, + K: ToLua<'lua>, + A: ToLuaMulti<'lua>, + R: FromLuaMulti<'lua> + 'fut, + { + match self.get::<_, Function>(key) { + Ok(func) => func.call_async(args), + Err(e) => Box::pin(future::err(e)), + } + } +} + +#[cfg(feature = "serialize")] +impl<'lua> Serialize for Table<'lua> { + fn serialize(&self, serializer: S) -> StdResult + where + S: Serializer, + { + let len = self.raw_len() as usize; + if len > 0 || self.is_array() { + let mut seq = serializer.serialize_seq(Some(len))?; + for v in self.clone().raw_sequence_values_by_len::(None) { + let v = v.map_err(serde::ser::Error::custom)?; + seq.serialize_element(&v)?; + } + return seq.end(); + } + + let mut map = serializer.serialize_map(None)?; + for kv in self.clone().pairs::() { + let (k, v) = kv.map_err(serde::ser::Error::custom)?; + map.serialize_entry(&k, &v)?; + } + map.end() + } +} + +/// An iterator over the pairs of a Lua table. +/// +/// This struct is created by the [`Table::pairs`] method. +/// +/// [`Table::pairs`]: struct.Table.html#method.pairs +pub struct TablePairs<'lua, K, V> { + table: LuaRef<'lua>, + next_key: Option>, + _phantom: PhantomData<(K, V)>, +} + +impl<'lua, K, V> Iterator for TablePairs<'lua, K, V> +where + K: FromLua<'lua>, + V: FromLua<'lua>, +{ + type Item = Result<(K, V)>; + + fn next(&mut self) -> Option { + if let Some(next_key) = self.next_key.take() { + let lua = self.table.lua; + + let res = (|| { + let res = unsafe { + let _sg = StackGuard::new(lua.state); + assert_stack(lua.state, 6); + + lua.push_ref(&self.table); + lua.push_value(next_key)?; + + let next = protect_lua_closure(lua.state, 2, ffi::LUA_MULTRET, |state| { + ffi::lua_next(state, -2) != 0 + })?; + if next { + ffi::lua_pushvalue(lua.state, -2); + let key = lua.pop_value(); + let value = lua.pop_value(); + self.next_key = Some(lua.pop_value()); + + Some((key, value)) + } else { + None + } + }; + + Ok(if let Some((key, value)) = res { + Some((K::from_lua(key, lua)?, V::from_lua(value, lua)?)) + } else { + None + }) + })(); + + match res { + Ok(Some((key, value))) => Some(Ok((key, value))), + Ok(None) => None, + Err(e) => Some(Err(e)), + } + } else { + None + } + } +} + +/// An iterator over the sequence part of a Lua table. +/// +/// This struct is created by the [`Table::sequence_values`] method. +/// +/// [`Table::sequence_values`]: struct.Table.html#method.sequence_values +pub struct TableSequence<'lua, V> { + table: LuaRef<'lua>, + index: Option, + len: Option, + raw: bool, + _phantom: PhantomData, +} + +impl<'lua, V> Iterator for TableSequence<'lua, V> +where + V: FromLua<'lua>, +{ + type Item = Result; + + fn next(&mut self) -> Option { + if let Some(index) = self.index.take() { + let lua = self.table.lua; + + let res = unsafe { + let _sg = StackGuard::new(lua.state); + assert_stack(lua.state, 5); + + lua.push_ref(&self.table); + let lua_geti = if self.raw { + ffi::lua_rawgeti + } else { + ffi::lua_geti + }; + match protect_lua_closure(lua.state, 1, 1, |state| lua_geti(state, -1, index)) { + Ok(ffi::LUA_TNIL) if index > self.len.unwrap_or(0) => None, + Ok(_) => { + let value = lua.pop_value(); + self.index = Some(index + 1); + Some(Ok(value)) + } + Err(err) => Some(Err(err)), + } + }; + + match res { + Some(Ok(r)) => Some(V::from_lua(r, lua)), + Some(Err(err)) => Some(Err(err)), + None => None, + } + } else { + None + } + } +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/src/thread.rs b/third_party/cargo/vendor/mlua-0.5.3/src/thread.rs new file mode 100644 index 0000000..f26eca1 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/src/thread.rs @@ -0,0 +1,366 @@ +use std::os::raw::c_int; + +use crate::error::{Error, Result}; +use crate::ffi; +use crate::types::LuaRef; +use crate::util::{ + assert_stack, check_stack, error_traceback, pop_error, protect_lua_closure, StackGuard, +}; +use crate::value::{FromLuaMulti, MultiValue, ToLuaMulti}; + +#[cfg(feature = "async")] +use { + crate::{ + error::ExternalError, + lua::{AsyncPollPending, Lua, WAKER_REGISTRY_KEY}, + util::{get_gc_userdata, push_gc_userdata}, + value::Value, + }, + futures_core::{future::Future, stream::Stream}, + std::{ + cell::RefCell, + marker::PhantomData, + os::raw::c_void, + pin::Pin, + task::{Context, Poll, Waker}, + }, +}; + +/// Status of a Lua thread (or coroutine). +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub enum ThreadStatus { + /// The thread was just created, or is suspended because it has called `coroutine.yield`. + /// + /// If a thread is in this state, it can be resumed by calling [`Thread::resume`]. + /// + /// [`Thread::resume`]: struct.Thread.html#method.resume + Resumable, + /// Either the thread has finished executing, or the thread is currently running. + Unresumable, + /// The thread has raised a Lua error during execution. + Error, +} + +/// Handle to an internal Lua thread (or coroutine). +#[derive(Clone, Debug)] +pub struct Thread<'lua>(pub(crate) LuaRef<'lua>); + +/// Thread (coroutine) representation as an async [`Future`] or [`Stream`]. +/// +/// Requires `feature = "async"` +/// +/// [`Future`]: ../futures_core/future/trait.Future.html +/// [`Stream`]: ../futures_core/stream/trait.Stream.html +#[cfg(feature = "async")] +#[cfg_attr(docsrs, doc(cfg(feature = "async")))] +#[derive(Debug)] +pub struct AsyncThread<'lua, R> { + thread: Thread<'lua>, + args0: RefCell>>>, + ret: PhantomData, +} + +impl<'lua> Thread<'lua> { + /// Resumes execution of this thread. + /// + /// Equivalent to `coroutine.resume`. + /// + /// Passes `args` as arguments to the thread. If the coroutine has called `coroutine.yield`, it + /// will return these arguments. Otherwise, the coroutine wasn't yet started, so the arguments + /// are passed to its main function. + /// + /// If the thread is no longer in `Active` state (meaning it has finished execution or + /// encountered an error), this will return `Err(CoroutineInactive)`, otherwise will return `Ok` + /// as follows: + /// + /// If the thread calls `coroutine.yield`, returns the values passed to `yield`. If the thread + /// `return`s values from its main function, returns those. + /// + /// # Examples + /// + /// ``` + /// # use mlua::{Error, Lua, Result, Thread}; + /// # fn main() -> Result<()> { + /// # let lua = Lua::new(); + /// let thread: Thread = lua.load(r#" + /// coroutine.create(function(arg) + /// assert(arg == 42) + /// local yieldarg = coroutine.yield(123) + /// assert(yieldarg == 43) + /// return 987 + /// end) + /// "#).eval()?; + /// + /// assert_eq!(thread.resume::<_, u32>(42)?, 123); + /// assert_eq!(thread.resume::<_, u32>(43)?, 987); + /// + /// // The coroutine has now returned, so `resume` will fail + /// match thread.resume::<_, u32>(()) { + /// Err(Error::CoroutineInactive) => {}, + /// unexpected => panic!("unexpected result {:?}", unexpected), + /// } + /// # Ok(()) + /// # } + /// ``` + pub fn resume(&self, args: A) -> Result + where + A: ToLuaMulti<'lua>, + R: FromLuaMulti<'lua>, + { + let lua = self.0.lua; + let args = args.to_lua_multi(lua)?; + let results = unsafe { + let _sg = StackGuard::new(lua.state); + assert_stack(lua.state, 3); + + lua.push_ref(&self.0); + let thread_state = ffi::lua_tothread(lua.state, -1); + + let status = ffi::lua_status(thread_state); + if status != ffi::LUA_YIELD && ffi::lua_gettop(thread_state) == 0 { + return Err(Error::CoroutineInactive); + } + + ffi::lua_pop(lua.state, 1); + + let nargs = args.len() as c_int; + check_stack(lua.state, nargs)?; + check_stack(thread_state, nargs + 1)?; + + for arg in args { + lua.push_value(arg)?; + } + ffi::lua_xmove(lua.state, thread_state, nargs); + + let mut nresults = 0; + + let ret = ffi::lua_resume(thread_state, lua.state, nargs, &mut nresults as *mut c_int); + if ret != ffi::LUA_OK && ret != ffi::LUA_YIELD { + protect_lua_closure(lua.state, 0, 0, |_| { + error_traceback(thread_state); + 0 + })?; + return Err(pop_error(thread_state, ret)); + } + + let mut results = MultiValue::new(); + ffi::lua_xmove(thread_state, lua.state, nresults); + + assert_stack(lua.state, 2); + for _ in 0..nresults { + results.push_front(lua.pop_value()); + } + results + }; + R::from_lua_multi(results, lua) + } + + /// Gets the status of the thread. + pub fn status(&self) -> ThreadStatus { + let lua = self.0.lua; + unsafe { + let _sg = StackGuard::new(lua.state); + assert_stack(lua.state, 1); + + lua.push_ref(&self.0); + let thread_state = ffi::lua_tothread(lua.state, -1); + ffi::lua_pop(lua.state, 1); + + let status = ffi::lua_status(thread_state); + if status != ffi::LUA_OK && status != ffi::LUA_YIELD { + ThreadStatus::Error + } else if status == ffi::LUA_YIELD || ffi::lua_gettop(thread_state) > 0 { + ThreadStatus::Resumable + } else { + ThreadStatus::Unresumable + } + } + } + + /// Converts Thread to an AsyncThread which implements Future and Stream traits. + /// + /// `args` are passed as arguments to the thread function for first call. + /// The object call `resume()` while polling and also allows to run rust futures + /// to completion using an executor. + /// + /// Using AsyncThread as a Stream allows to iterate through `coroutine.yield()` + /// values whereas Future version discards that values and poll until the final + /// one (returned from the thread function). + /// + /// Requires `feature = "async"` + /// + /// # Examples + /// + /// ``` + /// # use mlua::{Lua, Result, Thread}; + /// use futures::stream::TryStreamExt; + /// # #[tokio::main] + /// # async fn main() -> Result<()> { + /// # let lua = Lua::new(); + /// let thread: Thread = lua.load(r#" + /// coroutine.create(function (sum) + /// for i = 1,10 do + /// sum = sum + i + /// coroutine.yield(sum) + /// end + /// return sum + /// end) + /// "#).eval()?; + /// + /// let mut stream = thread.into_async::<_, i64>(1); + /// let mut sum = 0; + /// while let Some(n) = stream.try_next().await? { + /// sum += n; + /// } + /// + /// assert_eq!(sum, 286); + /// + /// # Ok(()) + /// # } + /// ``` + #[cfg(feature = "async")] + #[cfg_attr(docsrs, doc(cfg(feature = "async")))] + pub fn into_async(self, args: A) -> AsyncThread<'lua, R> + where + A: ToLuaMulti<'lua>, + R: FromLuaMulti<'lua>, + { + let args = args.to_lua_multi(&self.0.lua); + AsyncThread { + thread: self, + args0: RefCell::new(Some(args)), + ret: PhantomData, + } + } +} + +impl<'lua> PartialEq for Thread<'lua> { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} + +#[cfg(feature = "async")] +impl<'lua, R> Stream for AsyncThread<'lua, R> +where + R: FromLuaMulti<'lua>, +{ + type Item = Result; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let lua = self.thread.0.lua; + + match self.thread.status() { + ThreadStatus::Resumable => {} + _ => return Poll::Ready(None), + }; + + let _wg = WakerGuard::new(lua.state, cx.waker().clone()); + let ret: MultiValue = if let Some(args) = self.args0.borrow_mut().take() { + self.thread.resume(args?)? + } else { + self.thread.resume(())? + }; + + if is_poll_pending(lua, &ret) { + return Poll::Pending; + } + + cx.waker().wake_by_ref(); + Poll::Ready(Some(R::from_lua_multi(ret, lua))) + } +} + +#[cfg(feature = "async")] +impl<'lua, R> Future for AsyncThread<'lua, R> +where + R: FromLuaMulti<'lua>, +{ + type Output = Result; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let lua = self.thread.0.lua; + + match self.thread.status() { + ThreadStatus::Resumable => {} + _ => return Poll::Ready(Err("Thread already finished".to_lua_err())), + }; + + let _wg = WakerGuard::new(lua.state, cx.waker().clone()); + let ret: MultiValue = if let Some(args) = self.args0.borrow_mut().take() { + self.thread.resume(args?)? + } else { + self.thread.resume(())? + }; + + if is_poll_pending(lua, &ret) { + return Poll::Pending; + } + + if let ThreadStatus::Resumable = self.thread.status() { + // Ignore value returned via yield() + cx.waker().wake_by_ref(); + return Poll::Pending; + } + + Poll::Ready(R::from_lua_multi(ret, lua)) + } +} + +#[cfg(feature = "async")] +fn is_poll_pending(lua: &Lua, val: &MultiValue) -> bool { + if val.len() != 1 { + return false; + } + + if let Some(Value::UserData(ud)) = val.iter().next() { + unsafe { + let _sg = StackGuard::new(lua.state); + assert_stack(lua.state, 3); + + lua.push_ref(&ud.0); + let is_pending = get_gc_userdata::(lua.state, -1) + .as_ref() + .is_some(); + ffi::lua_pop(lua.state, 1); + + return is_pending; + } + } + + false +} + +#[cfg(feature = "async")] +struct WakerGuard(*mut ffi::lua_State); + +#[cfg(feature = "async")] +impl WakerGuard { + pub fn new(state: *mut ffi::lua_State, waker: Waker) -> Result { + unsafe { + let _sg = StackGuard::new(state); + assert_stack(state, 6); + + ffi::lua_pushlightuserdata(state, &WAKER_REGISTRY_KEY as *const u8 as *mut c_void); + push_gc_userdata(state, waker)?; + ffi::lua_rawset(state, ffi::LUA_REGISTRYINDEX); + + Ok(WakerGuard(state)) + } + } +} + +#[cfg(feature = "async")] +impl Drop for WakerGuard { + fn drop(&mut self) { + unsafe { + let state = self.0; + let _sg = StackGuard::new(state); + assert_stack(state, 2); + + ffi::lua_pushlightuserdata(state, &WAKER_REGISTRY_KEY as *const u8 as *mut c_void); + ffi::lua_pushnil(state); + ffi::lua_rawset(state, ffi::LUA_REGISTRYINDEX); + } + } +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/src/types.rs b/third_party/cargo/vendor/mlua-0.5.3/src/types.rs new file mode 100644 index 0000000..7621c43 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/src/types.rs @@ -0,0 +1,128 @@ +use std::cell::RefCell; +use std::os::raw::{c_int, c_void}; +use std::sync::{Arc, Mutex}; +use std::{fmt, mem, ptr}; + +#[cfg(feature = "async")] +use futures_core::future::LocalBoxFuture; + +use crate::error::Result; +use crate::ffi; +use crate::hook::Debug; +use crate::lua::Lua; +use crate::userdata::UserDataWrapped; +use crate::util::{assert_stack, StackGuard}; +use crate::value::MultiValue; + +/// Type of Lua integer numbers. +pub type Integer = ffi::lua_Integer; +/// Type of Lua floating point numbers. +pub type Number = ffi::lua_Number; + +/// A "light" userdata value. Equivalent to an unmanaged raw pointer. +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub struct LightUserData(pub *mut c_void); + +pub(crate) type Callback<'lua, 'a> = + Box) -> Result> + 'a>; + +#[cfg(feature = "async")] +pub(crate) type AsyncCallback<'lua, 'a> = + Box) -> LocalBoxFuture<'lua, Result>> + 'a>; + +pub(crate) type HookCallback = Arc Result<()>>>; + +pub(crate) type UserDataCell = RefCell>; + +#[cfg(feature = "send")] +pub trait MaybeSend: Send {} +#[cfg(feature = "send")] +impl MaybeSend for T {} + +#[cfg(not(feature = "send"))] +pub trait MaybeSend {} +#[cfg(not(feature = "send"))] +impl MaybeSend for T {} + +/// An auto generated key into the Lua registry. +/// +/// This is a handle to a value stored inside the Lua registry. It is not automatically +/// garbage collected on Drop, but it can be removed with [`Lua::remove_registry_value`], +/// and instances not manually removed can be garbage collected with [`Lua::expire_registry_values`]. +/// +/// Be warned, If you place this into Lua via a `UserData` type or a rust callback, it is *very +/// easy* to accidentally cause reference cycles that the Lua garbage collector cannot resolve. +/// Instead of placing a `RegistryKey` into a `UserData` type, prefer instead to use +/// [`UserData::set_user_value`] / [`UserData::get_user_value`]. +/// +/// [`Lua::remove_registry_value`]: struct.Lua.html#method.remove_registry_value +/// [`Lua::expire_registry_values`]: struct.Lua.html#method.expire_registry_values +/// [`UserData::set_user_value`]: struct.UserData.html#method.set_user_value +/// [`UserData::get_user_value`]: struct.UserData.html#method.get_user_value +pub struct RegistryKey { + pub(crate) registry_id: c_int, + pub(crate) unref_list: Arc>>>, +} + +impl fmt::Debug for RegistryKey { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "RegistryKey({})", self.registry_id) + } +} + +impl Drop for RegistryKey { + fn drop(&mut self) { + let mut unref_list = mlua_expect!(self.unref_list.lock(), "unref list poisoned"); + if let Some(list) = unref_list.as_mut() { + list.push(self.registry_id); + } + } +} + +impl RegistryKey { + // Destroys the RegistryKey without adding to the drop list + pub(crate) fn take(self) -> c_int { + let registry_id = self.registry_id; + unsafe { + ptr::read(&self.unref_list); + mem::forget(self); + } + registry_id + } +} + +pub(crate) struct LuaRef<'lua> { + pub(crate) lua: &'lua Lua, + pub(crate) index: c_int, +} + +impl<'lua> fmt::Debug for LuaRef<'lua> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Ref({})", self.index) + } +} + +impl<'lua> Clone for LuaRef<'lua> { + fn clone(&self) -> Self { + self.lua.clone_ref(self) + } +} + +impl<'lua> Drop for LuaRef<'lua> { + fn drop(&mut self) { + self.lua.drop_ref(self) + } +} + +impl<'lua> PartialEq for LuaRef<'lua> { + fn eq(&self, other: &Self) -> bool { + let lua = self.lua; + unsafe { + let _sg = StackGuard::new(lua.state); + assert_stack(lua.state, 2); + lua.push_ref(&self); + lua.push_ref(&other); + ffi::lua_rawequal(lua.state, -1, -2) == 1 + } + } +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/src/userdata.rs b/third_party/cargo/vendor/mlua-0.5.3/src/userdata.rs new file mode 100644 index 0000000..a6131a1 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/src/userdata.rs @@ -0,0 +1,662 @@ +use std::cell::{Ref, RefMut}; + +#[cfg(feature = "async")] +use std::future::Future; + +#[cfg(feature = "serialize")] +use { + serde::ser::{self, Serialize, Serializer}, + std::result::Result as StdResult, +}; + +use crate::error::{Error, Result}; +use crate::ffi; +use crate::function::Function; +use crate::lua::Lua; +use crate::table::Table; +use crate::types::{LuaRef, MaybeSend, UserDataCell}; +use crate::util::{assert_stack, get_destructed_userdata_metatable, get_userdata, StackGuard}; +use crate::value::{FromLua, FromLuaMulti, ToLua, ToLuaMulti, Value}; + +/// Kinds of metamethods that can be overridden. +/// +/// Currently, this mechanism does not allow overriding the `__gc` metamethod, since there is +/// generally no need to do so: [`UserData`] implementors can instead just implement `Drop`. +/// +/// [`UserData`]: trait.UserData.html +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub enum MetaMethod { + /// The `+` operator. + Add, + /// The `-` operator. + Sub, + /// The `*` operator. + Mul, + /// The `/` operator. + Div, + /// The `%` operator. + Mod, + /// The `^` operator. + Pow, + /// The unary minus (`-`) operator. + Unm, + /// The floor division (//) operator. + /// Requires `feature = "lua54/lua53"` + #[cfg(any(feature = "lua54", feature = "lua53", doc))] + IDiv, + /// The bitwise AND (&) operator. + /// Requires `feature = "lua54/lua53"` + #[cfg(any(feature = "lua54", feature = "lua53", doc))] + BAnd, + /// The bitwise OR (|) operator. + /// Requires `feature = "lua54/lua53"` + #[cfg(any(feature = "lua54", feature = "lua53", doc))] + BOr, + /// The bitwise XOR (binary ~) operator. + /// Requires `feature = "lua54/lua53"` + #[cfg(any(feature = "lua54", feature = "lua53", doc))] + BXor, + /// The bitwise NOT (unary ~) operator. + /// Requires `feature = "lua54/lua53"` + #[cfg(any(feature = "lua54", feature = "lua53", doc))] + BNot, + /// The bitwise left shift (<<) operator. + #[cfg(any(feature = "lua54", feature = "lua53", doc))] + Shl, + /// The bitwise right shift (>>) operator. + #[cfg(any(feature = "lua54", feature = "lua53", doc))] + Shr, + /// The string concatenation operator `..`. + Concat, + /// The length operator `#`. + Len, + /// The `==` operator. + Eq, + /// The `<` operator. + Lt, + /// The `<=` operator. + Le, + /// Index access `obj[key]`. + Index, + /// Index write access `obj[key] = value`. + NewIndex, + /// The call "operator" `obj(arg1, args2, ...)`. + Call, + /// The `__tostring` metamethod. + /// + /// This is not an operator, but will be called by methods such as `tostring` and `print`. + ToString, + /// The `__pairs` metamethod. + /// + /// This is not an operator, but it will be called by the built-in `pairs` function. + /// + /// Requires `feature = "lua54/lua53/lua52"` + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52", doc))] + Pairs, + /// The `__close` metamethod. + /// + /// Executed when a variable, that marked as to-be-closed, goes out of scope. + /// + /// More information about to-be-closed variabled can be found in the Lua 5.4 + /// [documentation][lua_doc]. + /// + /// Requires `feature = "lua54"` + /// + /// [lua_doc]: https://www.lua.org/manual/5.4/manual.html#3.3.8 + #[cfg(any(feature = "lua54", doc))] + Close, +} + +impl MetaMethod { + pub(crate) fn name(self) -> &'static [u8] { + match self { + MetaMethod::Add => b"__add", + MetaMethod::Sub => b"__sub", + MetaMethod::Mul => b"__mul", + MetaMethod::Div => b"__div", + MetaMethod::Mod => b"__mod", + MetaMethod::Pow => b"__pow", + MetaMethod::Unm => b"__unm", + + #[cfg(any(feature = "lua54", feature = "lua53"))] + MetaMethod::IDiv => b"__idiv", + #[cfg(any(feature = "lua54", feature = "lua53"))] + MetaMethod::BAnd => b"__band", + #[cfg(any(feature = "lua54", feature = "lua53"))] + MetaMethod::BOr => b"__bor", + #[cfg(any(feature = "lua54", feature = "lua53"))] + MetaMethod::BXor => b"__bxor", + #[cfg(any(feature = "lua54", feature = "lua53"))] + MetaMethod::BNot => b"__bnot", + #[cfg(any(feature = "lua54", feature = "lua53"))] + MetaMethod::Shl => b"__shl", + #[cfg(any(feature = "lua54", feature = "lua53"))] + MetaMethod::Shr => b"__shr", + + MetaMethod::Concat => b"__concat", + MetaMethod::Len => b"__len", + MetaMethod::Eq => b"__eq", + MetaMethod::Lt => b"__lt", + MetaMethod::Le => b"__le", + MetaMethod::Index => b"__index", + MetaMethod::NewIndex => b"__newindex", + MetaMethod::Call => b"__call", + MetaMethod::ToString => b"__tostring", + + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + MetaMethod::Pairs => b"__pairs", + + #[cfg(feature = "lua54")] + MetaMethod::Close => b"__close", + } + } +} + +/// Method registry for [`UserData`] implementors. +/// +/// [`UserData`]: trait.UserData.html +pub trait UserDataMethods<'lua, T: UserData> { + /// Add a method which accepts a `&T` as the first parameter. + /// + /// Regular methods are implemented by overriding the `__index` metamethod and returning the + /// accessed method. This allows them to be used with the expected `userdata:method()` syntax. + /// + /// If `add_meta_method` is used to set the `__index` metamethod, the `__index` metamethod will + /// be used as a fall-back if no regular method is found. + fn add_method(&mut self, name: &S, method: M) + where + S: ?Sized + AsRef<[u8]>, + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result; + + /// Add a regular method which accepts a `&mut T` as the first parameter. + /// + /// Refer to [`add_method`] for more information about the implementation. + /// + /// [`add_method`]: #method.add_method + fn add_method_mut(&mut self, name: &S, method: M) + where + S: ?Sized + AsRef<[u8]>, + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result; + + /// Add an async method which accepts a `T` as the first parameter and returns Future. + /// The passed `T` is cloned from the original value. + /// + /// Refer to [`add_method`] for more information about the implementation. + /// + /// Requires `feature = "async"` + /// + /// [`add_method`]: #method.add_method + #[cfg(feature = "async")] + #[cfg_attr(docsrs, doc(cfg(feature = "async")))] + fn add_async_method(&mut self, name: &S, method: M) + where + T: Clone, + S: ?Sized + AsRef<[u8]>, + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + M: 'static + MaybeSend + Fn(&'lua Lua, T, A) -> MR, + MR: 'lua + Future>; + + /// Add a regular method as a function which accepts generic arguments, the first argument will + /// be a `UserData` of type T if the method is called with Lua method syntax: + /// `my_userdata:my_method(arg1, arg2)`, or it is passed in as the first argument: + /// `my_userdata.my_method(my_userdata, arg1, arg2)`. + /// + /// Prefer to use [`add_method`] or [`add_method_mut`] as they are easier to use. + /// + /// [`add_method`]: #method.add_method + /// [`add_method_mut`]: #method.add_method_mut + fn add_function(&mut self, name: &S, function: F) + where + S: ?Sized + AsRef<[u8]>, + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result; + + /// Add a regular method as a mutable function which accepts generic arguments. + /// + /// This is a version of [`add_function`] that accepts a FnMut argument. + /// + /// [`add_function`]: #method.add_function + fn add_function_mut(&mut self, name: &S, function: F) + where + S: ?Sized + AsRef<[u8]>, + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result; + + /// Add a regular method as an async function which accepts generic arguments + /// and returns Future. + /// + /// This is an async version of [`add_function`]. + /// + /// Requires `feature = "async"` + /// + /// [`add_function`]: #method.add_function + #[cfg(feature = "async")] + #[cfg_attr(docsrs, doc(cfg(feature = "async")))] + fn add_async_function(&mut self, name: &S, function: F) + where + T: Clone, + S: ?Sized + AsRef<[u8]>, + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + F: 'static + MaybeSend + Fn(&'lua Lua, A) -> FR, + FR: 'lua + Future>; + + /// Add a metamethod which accepts a `&T` as the first parameter. + /// + /// # Note + /// + /// This can cause an error with certain binary metamethods that can trigger if only the right + /// side has a metatable. To prevent this, use [`add_meta_function`]. + /// + /// [`add_meta_function`]: #method.add_meta_function + fn add_meta_method(&mut self, meta: MetaMethod, method: M) + where + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result; + + /// Add a metamethod as a function which accepts a `&mut T` as the first parameter. + /// + /// # Note + /// + /// This can cause an error with certain binary metamethods that can trigger if only the right + /// side has a metatable. To prevent this, use [`add_meta_function`]. + /// + /// [`add_meta_function`]: #method.add_meta_function + fn add_meta_method_mut(&mut self, meta: MetaMethod, method: M) + where + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result; + + /// Add a metamethod which accepts generic arguments. + /// + /// Metamethods for binary operators can be triggered if either the left or right argument to + /// the binary operator has a metatable, so the first argument here is not necessarily a + /// userdata of type `T`. + fn add_meta_function(&mut self, meta: MetaMethod, function: F) + where + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result; + + /// Add a metamethod as a mutable function which accepts generic arguments. + /// + /// This is a version of [`add_meta_function`] that accepts a FnMut argument. + /// + /// [`add_meta_function`]: #method.add_meta_function + fn add_meta_function_mut(&mut self, meta: MetaMethod, function: F) + where + A: FromLuaMulti<'lua>, + R: ToLuaMulti<'lua>, + F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result; +} + +/// Trait for custom userdata types. +/// +/// By implementing this trait, a struct becomes eligible for use inside Lua code. Implementations +/// of [`ToLua`] and [`FromLua`] are automatically provided. +/// +/// # Examples +/// +/// ``` +/// # use mlua::{Lua, Result, UserData}; +/// # fn main() -> Result<()> { +/// # let lua = Lua::new(); +/// struct MyUserData(i32); +/// +/// impl UserData for MyUserData {} +/// +/// // `MyUserData` now implements `ToLua`: +/// lua.globals().set("myobject", MyUserData(123))?; +/// +/// lua.load("assert(type(myobject) == 'userdata')").exec()?; +/// # Ok(()) +/// # } +/// ``` +/// +/// Custom methods and operators can be provided by implementing `add_methods` (refer to +/// [`UserDataMethods`] for more information): +/// +/// ``` +/// # use mlua::{Lua, MetaMethod, Result, UserData, UserDataMethods}; +/// # fn main() -> Result<()> { +/// # let lua = Lua::new(); +/// struct MyUserData(i32); +/// +/// impl UserData for MyUserData { +/// fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { +/// methods.add_method("get", |_, this, _: ()| { +/// Ok(this.0) +/// }); +/// +/// methods.add_method_mut("add", |_, this, value: i32| { +/// this.0 += value; +/// Ok(()) +/// }); +/// +/// methods.add_meta_method(MetaMethod::Add, |_, this, value: i32| { +/// Ok(this.0 + value) +/// }); +/// } +/// } +/// +/// lua.globals().set("myobject", MyUserData(123))?; +/// +/// lua.load(r#" +/// assert(myobject:get() == 123) +/// myobject:add(7) +/// assert(myobject:get() == 130) +/// assert(myobject + 10 == 140) +/// "#).exec()?; +/// # Ok(()) +/// # } +/// ``` +/// +/// [`ToLua`]: trait.ToLua.html +/// [`FromLua`]: trait.FromLua.html +/// [`UserDataMethods`]: trait.UserDataMethods.html +pub trait UserData: Sized { + /// Adds custom methods and operators specific to this userdata. + fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(_methods: &mut M) {} +} + +pub(crate) struct UserDataWrapped { + pub(crate) data: *mut T, + #[cfg(feature = "serialize")] + ser: *mut dyn erased_serde::Serialize, +} + +impl Drop for UserDataWrapped { + fn drop(&mut self) { + unsafe { + drop(Box::from_raw(self.data)); + #[cfg(feature = "serialize")] + if self.data as *mut () != self.ser as *mut () { + drop(Box::from_raw(self.ser)); + } + } + } +} + +impl UserDataWrapped { + pub(crate) fn new(data: T) -> Self { + UserDataWrapped { + data: Box::into_raw(Box::new(data)), + #[cfg(feature = "serialize")] + ser: Box::into_raw(Box::new(UserDataSerializeError)), + } + } + + #[cfg(feature = "serialize")] + pub(crate) fn new_ser(data: T) -> Self + where + T: 'static + Serialize, + { + let data_raw = Box::into_raw(Box::new(data)); + UserDataWrapped { + data: data_raw, + ser: data_raw, + } + } +} + +impl AsRef for UserDataWrapped { + fn as_ref(&self) -> &T { + unsafe { &*self.data } + } +} + +impl AsMut for UserDataWrapped { + fn as_mut(&mut self) -> &mut T { + unsafe { &mut *self.data } + } +} + +#[cfg(feature = "serialize")] +pub(crate) struct UserDataSerializeError; + +#[cfg(feature = "serialize")] +impl Serialize for UserDataSerializeError { + fn serialize(&self, _serializer: S) -> StdResult + where + S: Serializer, + { + Err(ser::Error::custom("cannot serialize ")) + } +} + +/// Handle to an internal Lua userdata for any type that implements [`UserData`]. +/// +/// Similar to `std::any::Any`, this provides an interface for dynamic type checking via the [`is`] +/// and [`borrow`] methods. +/// +/// Internally, instances are stored in a `RefCell`, to best match the mutable semantics of the Lua +/// language. +/// +/// # Note +/// +/// This API should only be used when necessary. Implementing [`UserData`] already allows defining +/// methods which check the type and acquire a borrow behind the scenes. +/// +/// [`UserData`]: trait.UserData.html +/// [`is`]: #method.is +/// [`borrow`]: #method.borrow +#[derive(Clone, Debug)] +pub struct AnyUserData<'lua>(pub(crate) LuaRef<'lua>); + +impl<'lua> AnyUserData<'lua> { + /// Checks whether the type of this userdata is `T`. + pub fn is(&self) -> bool { + match self.inspect(|_: &UserDataCell| Ok(())) { + Ok(()) => true, + Err(Error::UserDataTypeMismatch) => false, + Err(_) => unreachable!(), + } + } + + /// Borrow this userdata immutably if it is of type `T`. + /// + /// # Errors + /// + /// Returns a `UserDataBorrowError` if the userdata is already mutably borrowed. Returns a + /// `UserDataTypeMismatch` if the userdata is not of type `T`. + pub fn borrow(&self) -> Result> { + self.inspect(|cell| { + let cell_ref = cell.try_borrow().map_err(|_| Error::UserDataBorrowError)?; + Ok(Ref::map(cell_ref, |x| unsafe { &*x.data })) + }) + } + + /// Borrow this userdata mutably if it is of type `T`. + /// + /// # Errors + /// + /// Returns a `UserDataBorrowMutError` if the userdata is already borrowed. Returns a + /// `UserDataTypeMismatch` if the userdata is not of type `T`. + pub fn borrow_mut(&self) -> Result> { + self.inspect(|cell| { + let cell_ref = cell + .try_borrow_mut() + .map_err(|_| Error::UserDataBorrowMutError)?; + Ok(RefMut::map(cell_ref, |x| unsafe { &mut *x.data })) + }) + } + + /// Sets an associated value to this `AnyUserData`. + /// + /// The value may be any Lua value whatsoever, and can be retrieved with [`get_user_value`]. + /// As Lua < 5.3 allows to store only tables, the value will be stored in a table at index 1. + /// + /// [`get_user_value`]: #method.get_user_value + pub fn set_user_value>(&self, v: V) -> Result<()> { + let lua = self.0.lua; + #[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))] + let v = { + // Lua 5.2/5.1 allows to store only a table. Then we will wrap the value. + let t = lua.create_table()?; + t.raw_set(1, v)?; + crate::Value::Table(t) + }; + #[cfg(any(feature = "lua54", feature = "lua53"))] + let v = v.to_lua(lua)?; + unsafe { + let _sg = StackGuard::new(lua.state); + assert_stack(lua.state, 2); + lua.push_ref(&self.0); + lua.push_value(v)?; + ffi::lua_setuservalue(lua.state, -2); + Ok(()) + } + } + + /// Returns an associated value set by [`set_user_value`]. + /// + /// For Lua < 5.3 the value will be automatically extracted from the table wrapper from index 1. + /// + /// [`set_user_value`]: #method.set_user_value + pub fn get_user_value>(&self) -> Result { + let lua = self.0.lua; + let res = unsafe { + let _sg = StackGuard::new(lua.state); + assert_stack(lua.state, 3); + lua.push_ref(&self.0); + ffi::lua_getuservalue(lua.state, -1); + lua.pop_value() + }; + #[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))] + return crate::Table::from_lua(res, lua)?.get(1); + #[cfg(any(feature = "lua54", feature = "lua53"))] + V::from_lua(res, lua) + } + + /// Checks for a metamethod in this `AnyUserData` + pub fn has_metamethod(&self, method: MetaMethod) -> Result { + match self.get_metatable() { + Ok(mt) => { + let name = self.0.lua.create_string(method.name())?; + if let Value::Nil = mt.raw_get(name)? { + Ok(false) + } else { + Ok(true) + } + } + Err(Error::UserDataTypeMismatch) => Ok(false), + Err(e) => Err(e), + } + } + + fn get_metatable(&self) -> Result> { + unsafe { + let lua = self.0.lua; + let _sg = StackGuard::new(lua.state); + assert_stack(lua.state, 3); + + lua.push_ref(&self.0); + + if ffi::lua_getmetatable(lua.state, -1) == 0 { + return Err(Error::UserDataTypeMismatch); + } + + Ok(Table(lua.pop_ref())) + } + } + + pub(crate) fn equals>(&self, other: T) -> Result { + let other = other.as_ref(); + if self == other { + return Ok(true); + } + + let mt = self.get_metatable()?; + if mt != other.get_metatable()? { + return Ok(false); + } + + if mt.contains_key("__eq")? { + return mt + .get::<_, Function>("__eq")? + .call((self.clone(), other.clone())); + } + + Ok(false) + } + + fn inspect<'a, T, R, F>(&'a self, func: F) -> Result + where + T: 'static + UserData, + F: FnOnce(&'a UserDataCell) -> Result, + { + unsafe { + let lua = self.0.lua; + let _sg = StackGuard::new(lua.state); + assert_stack(lua.state, 3); + + lua.push_ref(&self.0); + + if ffi::lua_getmetatable(lua.state, -1) == 0 { + Err(Error::UserDataTypeMismatch) + } else { + ffi::lua_rawgeti( + lua.state, + ffi::LUA_REGISTRYINDEX, + lua.userdata_metatable::()? as ffi::lua_Integer, + ); + + if ffi::lua_rawequal(lua.state, -1, -2) == 0 { + // Maybe UserData destructed? + ffi::lua_pop(lua.state, 1); + get_destructed_userdata_metatable(lua.state); + if ffi::lua_rawequal(lua.state, -1, -2) == 1 { + Err(Error::UserDataDestructed) + } else { + Err(Error::UserDataTypeMismatch) + } + } else { + func(&*get_userdata::>(lua.state, -3)) + } + } + } + } +} + +impl<'lua> PartialEq for AnyUserData<'lua> { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} + +impl<'lua> AsRef> for AnyUserData<'lua> { + #[inline] + fn as_ref(&self) -> &Self { + self + } +} + +#[cfg(feature = "serialize")] +impl<'lua> Serialize for AnyUserData<'lua> { + fn serialize(&self, serializer: S) -> StdResult + where + S: Serializer, + { + let f = || unsafe { + let lua = self.0.lua; + let _sg = StackGuard::new(lua.state); + assert_stack(lua.state, 2); + + lua.push_userdata_ref(&self.0)?; + let ud = &*get_userdata::>(lua.state, -1); + (*ud.try_borrow().map_err(|_| Error::UserDataBorrowError)?.ser) + .serialize(serializer) + .map_err(|err| Error::SerializeError(err.to_string())) + }; + f().map_err(ser::Error::custom) + } +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/src/util.rs b/third_party/cargo/vendor/mlua-0.5.3/src/util.rs new file mode 100644 index 0000000..ae668fc --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/src/util.rs @@ -0,0 +1,767 @@ +use std::any::{Any, TypeId}; +use std::borrow::Cow; +use std::collections::HashMap; +use std::fmt::Write; +use std::os::raw::{c_char, c_int, c_void}; +use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe}; +use std::sync::{Arc, Mutex}; +use std::{mem, ptr, slice}; + +use crate::error::{Error, Result}; +use crate::ffi; + +lazy_static::lazy_static! { + // The capacity must(!) be greater than number of stored keys + static ref METATABLE_CACHE: Mutex> = Mutex::new(HashMap::with_capacity(32)); +} + +// Checks that Lua has enough free stack space for future stack operations. On failure, this will +// panic with an internal error message. +pub unsafe fn assert_stack(state: *mut ffi::lua_State, amount: c_int) { + // TODO: This should only be triggered when there is a logic error in `mlua`. In the future, + // when there is a way to be confident about stack safety and test it, this could be enabled + // only when `cfg!(debug_assertions)` is true. + mlua_assert!( + ffi::lua_checkstack(state, amount) != 0, + "out of stack space" + ); +} + +// Checks that Lua has enough free stack space and returns `Error::StackError` on failure. +pub unsafe fn check_stack(state: *mut ffi::lua_State, amount: c_int) -> Result<()> { + if ffi::lua_checkstack(state, amount) == 0 { + Err(Error::StackError) + } else { + Ok(()) + } +} + +pub struct StackGuard { + state: *mut ffi::lua_State, + top: c_int, +} + +impl StackGuard { + // Creates a StackGuard instance with wa record of the stack size, and on Drop will check the + // stack size and drop any extra elements. If the stack size at the end is *smaller* than at + // the beginning, this is considered a fatal logic error and will result in a panic. + pub unsafe fn new(state: *mut ffi::lua_State) -> StackGuard { + StackGuard { + state, + top: ffi::lua_gettop(state), + } + } +} + +impl Drop for StackGuard { + fn drop(&mut self) { + unsafe { + let top = ffi::lua_gettop(self.state); + if top < self.top { + mlua_panic!("{} too many stack values popped", self.top - top) + } + if top > self.top { + ffi::lua_settop(self.state, self.top); + } + } + } +} + +// Call a function that calls into the Lua API and may trigger a Lua error (longjmp) in a safe way. +// Wraps the inner function in a call to `lua_pcall`, so the inner function only has access to a +// limited lua stack. `nargs` is the same as the the parameter to `lua_pcall`, and `nresults` is +// always LUA_MULTRET. Internally uses 2 extra stack spaces, and does not call checkstack. +// Provided function must *never* panic. +pub unsafe fn protect_lua( + state: *mut ffi::lua_State, + nargs: c_int, + f: unsafe extern "C" fn(*mut ffi::lua_State) -> c_int, +) -> Result<()> { + let stack_start = ffi::lua_gettop(state) - nargs; + + ffi::lua_pushcfunction(state, error_traceback); + ffi::lua_pushcfunction(state, f); + if nargs > 0 { + ffi::lua_rotate(state, stack_start + 1, 2); + } + + let ret = ffi::lua_pcall(state, nargs, ffi::LUA_MULTRET, stack_start + 1); + ffi::lua_remove(state, stack_start + 1); + + if ret == ffi::LUA_OK { + Ok(()) + } else { + Err(pop_error(state, ret)) + } +} + +// Call a function that calls into the Lua API and may trigger a Lua error (longjmp) in a safe way. +// Wraps the inner function in a call to `lua_pcall`, so the inner function only has access to a +// limited lua stack. `nargs` and `nresults` are similar to the parameters of `lua_pcall`, but the +// given function return type is not the return value count, instead the inner function return +// values are assumed to match the `nresults` param. Internally uses 3 extra stack spaces, and does +// not call checkstack. Provided function must *not* panic, and since it will generally be +// lonjmping, should not contain any values that implement Drop. +pub unsafe fn protect_lua_closure( + state: *mut ffi::lua_State, + nargs: c_int, + nresults: c_int, + f: F, +) -> Result +where + F: Fn(*mut ffi::lua_State) -> R, + R: Copy, +{ + union URes { + uninit: (), + init: R, + } + + struct Params { + function: F, + result: URes, + nresults: c_int, + } + + unsafe extern "C" fn do_call(state: *mut ffi::lua_State) -> c_int + where + R: Copy, + F: Fn(*mut ffi::lua_State) -> R, + { + let params = ffi::lua_touserdata(state, -1) as *mut Params; + ffi::lua_pop(state, 1); + + (*params).result.init = ((*params).function)(state); + + if (*params).nresults == ffi::LUA_MULTRET { + ffi::lua_gettop(state) + } else { + (*params).nresults + } + } + + let stack_start = ffi::lua_gettop(state) - nargs; + + ffi::lua_pushcfunction(state, error_traceback); + ffi::lua_pushcfunction(state, do_call::); + if nargs > 0 { + ffi::lua_rotate(state, stack_start + 1, 2); + } + + let mut params = Params { + function: f, + result: URes { uninit: () }, + nresults, + }; + + ffi::lua_pushlightuserdata(state, &mut params as *mut Params as *mut c_void); + let ret = ffi::lua_pcall(state, nargs + 1, nresults, stack_start + 1); + ffi::lua_remove(state, stack_start + 1); + + if ret == ffi::LUA_OK { + // LUA_OK is only returned when the do_call function has completed successfully, so + // params.result is definitely initialized. + Ok(params.result.init) + } else { + Err(pop_error(state, ret)) + } +} + +// Pops an error off of the stack and returns it. The specific behavior depends on the type of the +// error at the top of the stack: +// 1) If the error is actually a WrappedPanic, this will continue the panic. +// 2) If the error on the top of the stack is actually a WrappedError, just returns it. +// 3) Otherwise, interprets the error as the appropriate lua error. +// Uses 2 stack spaces, does not call lua_checkstack. +pub unsafe fn pop_error(state: *mut ffi::lua_State, err_code: c_int) -> Error { + mlua_debug_assert!( + err_code != ffi::LUA_OK && err_code != ffi::LUA_YIELD, + "pop_error called with non-error return code" + ); + + if let Some(err) = get_wrapped_error(state, -1).as_ref() { + ffi::lua_pop(state, 1); + err.clone() + } else if let Some(panic) = get_gc_userdata::(state, -1).as_mut() { + if let Some(p) = (*panic).0.take() { + resume_unwind(p); + } else { + mlua_panic!("error during panic handling, panic was resumed twice") + } + } else { + let err_string = to_string(state, -1).into_owned(); + ffi::lua_pop(state, 1); + + match err_code { + ffi::LUA_ERRRUN => Error::RuntimeError(err_string), + ffi::LUA_ERRSYNTAX => { + Error::SyntaxError { + // This seems terrible, but as far as I can tell, this is exactly what the + // stock Lua REPL does. + incomplete_input: err_string.ends_with("") + || err_string.ends_with("''"), + message: err_string, + } + } + ffi::LUA_ERRERR => { + // This error is raised when the error handler raises an error too many times + // recursively, and continuing to trigger the error handler would cause a stack + // overflow. It is not very useful to differentiate between this and "ordinary" + // runtime errors, so we handle them the same way. + Error::RuntimeError(err_string) + } + ffi::LUA_ERRMEM => Error::MemoryError(err_string), + #[cfg(any(feature = "lua53", feature = "lua52"))] + ffi::LUA_ERRGCMM => Error::GarbageCollectorError(err_string), + _ => mlua_panic!("unrecognized lua error code"), + } + } +} + +// Internally uses 4 stack spaces, does not call checkstack +pub unsafe fn push_string>( + state: *mut ffi::lua_State, + s: &S, +) -> Result<()> { + protect_lua_closure(state, 0, 1, |state| { + let s = s.as_ref(); + ffi::lua_pushlstring(state, s.as_ptr() as *const c_char, s.len()); + }) +} + +// Internally uses 4 stack spaces, does not call checkstack +pub unsafe fn push_userdata(state: *mut ffi::lua_State, t: T) -> Result<()> { + let ud = protect_lua_closure(state, 0, 1, move |state| { + ffi::lua_newuserdata(state, mem::size_of::()) as *mut T + })?; + ptr::write(ud, t); + Ok(()) +} + +pub unsafe fn get_userdata(state: *mut ffi::lua_State, index: c_int) -> *mut T { + let ud = ffi::lua_touserdata(state, index) as *mut T; + mlua_debug_assert!(!ud.is_null(), "userdata pointer is null"); + ud +} + +// Pops the userdata off of the top of the stack and returns it to rust, invalidating the lua +// userdata and gives it the special "destructed" userdata metatable. Userdata must not have been +// previously invalidated, and this method does not check for this. Uses 1 extra stack space and +// does not call checkstack +pub unsafe fn take_userdata(state: *mut ffi::lua_State) -> T { + // We set the metatable of userdata on __gc to a special table with no __gc method and with + // metamethods that trigger an error on access. We do this so that it will not be double + // dropped, and also so that it cannot be used or identified as any particular userdata type + // after the first call to __gc. + get_destructed_userdata_metatable(state); + ffi::lua_setmetatable(state, -2); + let ud = ffi::lua_touserdata(state, -1) as *mut T; + mlua_debug_assert!(!ud.is_null(), "userdata pointer is null"); + ffi::lua_pop(state, 1); + ptr::read(ud) +} + +// Pushes the userdata and attaches a metatable with __gc method +// Internally uses 5 stack spaces, does not call checkstack +pub unsafe fn push_gc_userdata(state: *mut ffi::lua_State, t: T) -> Result<()> { + push_meta_gc_userdata::(state, t) +} + +pub unsafe fn push_meta_gc_userdata(state: *mut ffi::lua_State, t: T) -> Result<()> { + let ud = protect_lua_closure(state, 0, 1, move |state| { + ffi::lua_newuserdata(state, mem::size_of::()) as *mut T + })?; + ptr::write(ud, t); + get_gc_metatable_for::(state); + ffi::lua_setmetatable(state, -2); + Ok(()) +} + +// Uses 2 stack spaces, does not call checkstack +pub unsafe fn get_gc_userdata(state: *mut ffi::lua_State, index: c_int) -> *mut T { + let ud = ffi::lua_touserdata(state, index) as *mut T; + if ud.is_null() || ffi::lua_getmetatable(state, index) == 0 { + return ptr::null_mut(); + } + get_gc_metatable_for::(state); + let res = ffi::lua_rawequal(state, -1, -2) != 0; + ffi::lua_pop(state, 2); + if !res { + return ptr::null_mut(); + } + ud +} + +// Populates the given table with the appropriate members to be a userdata metatable for the given +// type. This function takes the given table at the `metatable` index, and adds an appropriate __gc +// member to it for the given type and a __metatable entry to protect the table from script access. +// The function also, if given a `members` table index, will set up an __index metamethod to return +// the appropriate member on __index. Additionally, if there is already an __index entry on the +// given metatable, instead of simply overwriting the __index, instead the created __index method +// will capture the previous one, and use it as a fallback only if the given key is not found in the +// provided members table. Internally uses 6 stack spaces and does not call checkstack. +pub unsafe fn init_userdata_metatable( + state: *mut ffi::lua_State, + metatable: c_int, + members: Option, +) -> Result<()> { + // Used if both an __index metamethod is set and regular methods, checks methods table + // first, then __index metamethod. + unsafe extern "C" fn meta_index_impl(state: *mut ffi::lua_State) -> c_int { + ffi::luaL_checkstack(state, 2, ptr::null()); + + ffi::lua_pushvalue(state, -1); + ffi::lua_gettable(state, ffi::lua_upvalueindex(2)); + if ffi::lua_isnil(state, -1) == 0 { + ffi::lua_insert(state, -3); + ffi::lua_pop(state, 2); + 1 + } else { + ffi::lua_pop(state, 1); + ffi::lua_pushvalue(state, ffi::lua_upvalueindex(1)); + ffi::lua_insert(state, -3); + ffi::lua_call(state, 2, 1); + 1 + } + } + + let members = members.map(|i| ffi::lua_absindex(state, i)); + ffi::lua_pushvalue(state, metatable); + + if let Some(members) = members { + push_string(state, "__index")?; + ffi::lua_pushvalue(state, -1); + + let index_type = ffi::lua_rawget(state, -3); + if index_type == ffi::LUA_TNIL { + ffi::lua_pop(state, 1); + ffi::lua_pushvalue(state, members); + } else if index_type == ffi::LUA_TFUNCTION { + ffi::lua_pushvalue(state, members); + protect_lua_closure(state, 2, 1, |state| { + ffi::lua_pushcclosure(state, meta_index_impl, 2); + })?; + } else { + mlua_panic!("improper __index type {}", index_type); + } + + protect_lua_closure(state, 3, 1, |state| { + ffi::lua_rawset(state, -3); + })?; + } + + push_string(state, "__gc")?; + ffi::lua_pushcfunction(state, userdata_destructor::); + protect_lua_closure(state, 3, 1, |state| { + ffi::lua_rawset(state, -3); + })?; + + push_string(state, "__metatable")?; + ffi::lua_pushboolean(state, 0); + protect_lua_closure(state, 3, 1, |state| { + ffi::lua_rawset(state, -3); + })?; + + ffi::lua_pop(state, 1); + + Ok(()) +} + +pub unsafe extern "C" fn userdata_destructor(state: *mut ffi::lua_State) -> c_int { + callback_error(state, |_| { + check_stack(state, 1)?; + take_userdata::(state); + Ok(0) + }) +} + +// In the context of a lua callback, this will call the given function and if the given function +// returns an error, *or if the given function panics*, this will result in a call to lua_error (a +// longjmp). The error or panic is wrapped in such a way that when calling pop_error back on +// the rust side, it will resume the panic. +// +// This function assumes the structure of the stack at the beginning of a callback, that the only +// elements on the stack are the arguments to the callback. +// +// This function uses some of the bottom of the stack for error handling, the given callback will be +// given the number of arguments available as an argument, and should return the number of returns +// as normal, but cannot assume that the arguments available start at 0. +pub unsafe fn callback_error(state: *mut ffi::lua_State, f: F) -> R +where + F: FnOnce(c_int) -> Result, +{ + let nargs = ffi::lua_gettop(state); + + // We need one extra stack space to store preallocated memory, and at least 3 stack spaces + // overall for handling error metatables + let extra_stack = if nargs < 3 { 3 - nargs } else { 1 }; + ffi::luaL_checkstack( + state, + extra_stack, + cstr!("not enough stack space for callback error handling"), + ); + + // We cannot shadow rust errors with Lua ones, we pre-allocate enough memory to store a wrapped + // error or panic *before* we proceed. + let ud = ffi::lua_newuserdata( + state, + mem::size_of::().max(mem::size_of::()), + ); + ffi::lua_rotate(state, 1, 1); + + match catch_unwind(AssertUnwindSafe(|| f(nargs))) { + Ok(Ok(r)) => { + ffi::lua_remove(state, 1); + r + } + Ok(Err(err)) => { + ffi::lua_settop(state, 1); + ptr::write(ud as *mut WrappedError, WrappedError(err)); + get_gc_metatable_for::(state); + ffi::lua_setmetatable(state, -2); + ffi::lua_error(state) + } + Err(p) => { + ffi::lua_settop(state, 1); + ptr::write(ud as *mut WrappedPanic, WrappedPanic(Some(p))); + get_gc_metatable_for::(state); + ffi::lua_setmetatable(state, -2); + ffi::lua_error(state) + } + } +} + +// Takes an error at the top of the stack, and if it is a WrappedError, converts it to an +// Error::CallbackError with a traceback, if it is some lua type, prints the error along with a +// traceback, and if it is a WrappedPanic, does not modify it. This function does its best to avoid +// triggering another error and shadowing previous rust errors, but it may trigger Lua errors that +// shadow rust errors under certain memory conditions. This function ensures that such behavior +// will *never* occur with a rust panic, however. +pub unsafe extern "C" fn error_traceback(state: *mut ffi::lua_State) -> c_int { + // I believe luaL_traceback requires this much free stack to not error. + const LUA_TRACEBACK_STACK: c_int = 11; + + if ffi::lua_checkstack(state, 2) == 0 { + // If we don't have enough stack space to even check the error type, do nothing so we don't + // risk shadowing a rust panic. + } else if let Some(error) = get_wrapped_error(state, -1).as_ref() { + // lua_newuserdata and luaL_traceback may error, but nothing that implements Drop should be + // on the rust stack at this time. + let ud = ffi::lua_newuserdata(state, mem::size_of::()) as *mut WrappedError; + let traceback = if ffi::lua_checkstack(state, LUA_TRACEBACK_STACK) != 0 { + ffi::luaL_traceback(state, state, ptr::null(), 0); + + let traceback = to_string(state, -1).into_owned(); + ffi::lua_pop(state, 1); + traceback + } else { + "".to_owned() + }; + + let error = error.clone(); + ffi::lua_remove(state, -2); + + ptr::write( + ud, + WrappedError(Error::CallbackError { + traceback, + cause: Arc::new(error), + }), + ); + get_gc_metatable_for::(state); + ffi::lua_setmetatable(state, -2); + } else if get_gc_userdata::(state, -1).is_null() + && ffi::lua_checkstack(state, LUA_TRACEBACK_STACK) != 0 + { + let s = ffi::luaL_tolstring(state, -1, ptr::null_mut()); + ffi::luaL_traceback(state, state, s, 0); + ffi::lua_remove(state, -2); + } + 1 +} + +// Does not call lua_checkstack, uses 1 stack space. +pub unsafe fn get_main_state(state: *mut ffi::lua_State) -> Option<*mut ffi::lua_State> { + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + { + ffi::lua_rawgeti(state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_MAINTHREAD); + let main_state = ffi::lua_tothread(state, -1); + ffi::lua_pop(state, 1); + Some(main_state) + } + #[cfg(any(feature = "lua51", feature = "luajit"))] + { + // Check the current state first + let is_main_state = ffi::lua_pushthread(state) == 1; + ffi::lua_pop(state, 1); + if is_main_state { + Some(state) + } else { + None + } + } +} + +// Pushes a WrappedError to the top of the stack. Uses two stack spaces and does not call +// lua_checkstack. +pub unsafe fn push_wrapped_error(state: *mut ffi::lua_State, err: Error) -> Result<()> { + push_gc_userdata::(state, WrappedError(err)) +} + +// Checks if the value at the given index is a WrappedError, and if it is returns a pointer to it, +// otherwise returns null. Uses 2 stack spaces and does not call lua_checkstack. +pub unsafe fn get_wrapped_error(state: *mut ffi::lua_State, index: c_int) -> *const Error { + let ud = get_gc_userdata::(state, index); + if ud.is_null() { + return ptr::null(); + } + &(*ud).0 +} + +// Initialize the internal (with __gc) metatable for a type T +pub unsafe fn init_gc_metatable_for( + state: *mut ffi::lua_State, + customize_fn: Option, +) { + let type_id = TypeId::of::(); + + let ref_addr = { + let mut mt_cache = mlua_expect!(METATABLE_CACHE.lock(), "cannot lock metatable cache"); + mlua_assert!( + mt_cache.capacity() - mt_cache.len() > 0, + "out of metatable cache capacity" + ); + mt_cache.insert(type_id, 0); + &mt_cache[&type_id] as *const u8 + }; + + ffi::lua_newtable(state); + + ffi::lua_pushstring(state, cstr!("__gc")); + ffi::lua_pushcfunction(state, userdata_destructor::); + ffi::lua_rawset(state, -3); + + ffi::lua_pushstring(state, cstr!("__metatable")); + ffi::lua_pushboolean(state, 0); + ffi::lua_rawset(state, -3); + + if let Some(f) = customize_fn { + f(state) + } + + ffi::lua_rawsetp(state, ffi::LUA_REGISTRYINDEX, ref_addr as *mut c_void); +} + +pub unsafe fn get_gc_metatable_for(state: *mut ffi::lua_State) { + let type_id = TypeId::of::(); + let ref_addr = { + let mt_cache = mlua_expect!(METATABLE_CACHE.lock(), "cannot lock metatable cache"); + mlua_expect!(mt_cache.get(&type_id), "gc metatable does not exist") as *const u8 + }; + ffi::lua_rawgetp(state, ffi::LUA_REGISTRYINDEX, ref_addr as *mut c_void); +} + +// Initialize the error, panic, and destructed userdata metatables. +pub unsafe fn init_error_registry(state: *mut ffi::lua_State) { + assert_stack(state, 8); + + // Create error and panic metatables + + unsafe extern "C" fn error_tostring(state: *mut ffi::lua_State) -> c_int { + let err_buf = callback_error(state, |_| { + check_stack(state, 3)?; + if let Some(error) = get_wrapped_error(state, -1).as_ref() { + ffi::lua_pushlightuserdata( + state, + &ERROR_PRINT_BUFFER_KEY as *const u8 as *mut c_void, + ); + ffi::lua_rawget(state, ffi::LUA_REGISTRYINDEX); + let err_buf = ffi::lua_touserdata(state, -1) as *mut String; + ffi::lua_pop(state, 2); + + (*err_buf).clear(); + // Depending on how the API is used and what error types scripts are given, it may + // be possible to make this consume arbitrary amounts of memory (for example, some + // kind of recursive error structure?) + let _ = write!(&mut (*err_buf), "{}", error); + Ok(err_buf) + } else if let Some(panic) = get_gc_userdata::(state, -1).as_ref() { + if let Some(ref p) = (*panic).0 { + ffi::lua_pushlightuserdata( + state, + &ERROR_PRINT_BUFFER_KEY as *const u8 as *mut c_void, + ); + ffi::lua_rawget(state, ffi::LUA_REGISTRYINDEX); + let err_buf = ffi::lua_touserdata(state, -1) as *mut String; + ffi::lua_pop(state, 2); + + let error = if let Some(x) = p.downcast_ref::<&str>() { + x.to_string() + } else if let Some(x) = p.downcast_ref::() { + x.to_string() + } else { + "panic".to_string() + }; + + (*err_buf).clear(); + let _ = write!(&mut (*err_buf), "{}", error); + Ok(err_buf) + } else { + mlua_panic!("error during panic handling, panic was resumed") + } + } else { + // I'm not sure whether this is possible to trigger without bugs in mlua? + Err(Error::UserDataTypeMismatch) + } + }); + + ffi::lua_pushlstring( + state, + (*err_buf).as_ptr() as *const c_char, + (*err_buf).len(), + ); + (*err_buf).clear(); + 1 + } + + init_gc_metatable_for::( + state, + Some(|state| { + ffi::lua_pushstring(state, cstr!("__tostring")); + ffi::lua_pushcfunction(state, error_tostring); + ffi::lua_rawset(state, -3); + }), + ); + + init_gc_metatable_for::( + state, + Some(|state| { + ffi::lua_pushstring(state, cstr!("__tostring")); + ffi::lua_pushcfunction(state, error_tostring); + ffi::lua_rawset(state, -3); + }), + ); + + // Create destructed userdata metatable + + unsafe extern "C" fn destructed_error(state: *mut ffi::lua_State) -> c_int { + ffi::luaL_checkstack(state, 2, ptr::null()); + let ud = ffi::lua_newuserdata(state, mem::size_of::()) as *mut WrappedError; + ptr::write(ud, WrappedError(Error::CallbackDestructed)); + get_gc_metatable_for::(state); + ffi::lua_setmetatable(state, -2); + ffi::lua_error(state) + } + + ffi::lua_pushlightuserdata( + state, + &DESTRUCTED_USERDATA_METATABLE as *const u8 as *mut c_void, + ); + ffi::lua_newtable(state); + + for &method in &[ + cstr!("__add"), + cstr!("__sub"), + cstr!("__mul"), + cstr!("__div"), + cstr!("__mod"), + cstr!("__pow"), + cstr!("__unm"), + #[cfg(any(feature = "lua54", feature = "lua53"))] + cstr!("__idiv"), + #[cfg(any(feature = "lua54", feature = "lua53"))] + cstr!("__band"), + #[cfg(any(feature = "lua54", feature = "lua53"))] + cstr!("__bor"), + #[cfg(any(feature = "lua54", feature = "lua53"))] + cstr!("__bxor"), + #[cfg(any(feature = "lua54", feature = "lua53"))] + cstr!("__bnot"), + #[cfg(any(feature = "lua54", feature = "lua53"))] + cstr!("__shl"), + #[cfg(any(feature = "lua54", feature = "lua53"))] + cstr!("__shr"), + cstr!("__concat"), + cstr!("__len"), + cstr!("__eq"), + cstr!("__lt"), + cstr!("__le"), + cstr!("__index"), + cstr!("__newindex"), + cstr!("__call"), + cstr!("__tostring"), + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + cstr!("__pairs"), + #[cfg(any(feature = "lua53", feature = "lua52"))] + cstr!("__ipairs"), + #[cfg(feature = "lua54")] + cstr!("__close"), + ] { + ffi::lua_pushstring(state, method); + ffi::lua_pushcfunction(state, destructed_error); + ffi::lua_rawset(state, -3); + } + + ffi::lua_rawset(state, ffi::LUA_REGISTRYINDEX); + + // Create error print buffer + + ffi::lua_pushlightuserdata(state, &ERROR_PRINT_BUFFER_KEY as *const u8 as *mut c_void); + + let ud = ffi::lua_newuserdata(state, mem::size_of::()) as *mut String; + ptr::write(ud, String::new()); + + ffi::lua_newtable(state); + ffi::lua_pushstring(state, cstr!("__gc")); + ffi::lua_pushcfunction(state, userdata_destructor::); + ffi::lua_rawset(state, -3); + ffi::lua_setmetatable(state, -2); + + ffi::lua_rawset(state, ffi::LUA_REGISTRYINDEX); +} + +struct WrappedError(pub Error); +struct WrappedPanic(pub Option>); + +// Converts the given lua value to a string in a reasonable format without causing a Lua error or +// panicking. +unsafe fn to_string<'a>(state: *mut ffi::lua_State, index: c_int) -> Cow<'a, str> { + match ffi::lua_type(state, index) { + ffi::LUA_TNONE => "".into(), + ffi::LUA_TNIL => "".into(), + ffi::LUA_TBOOLEAN => (ffi::lua_toboolean(state, index) != 1).to_string().into(), + ffi::LUA_TLIGHTUSERDATA => { + format!("", ffi::lua_topointer(state, index)).into() + } + ffi::LUA_TNUMBER => { + let mut isint = 0; + let i = ffi::lua_tointegerx(state, -1, &mut isint); + if isint == 0 { + ffi::lua_tonumber(state, index).to_string().into() + } else { + i.to_string().into() + } + } + ffi::LUA_TSTRING => { + let mut size = 0; + let data = ffi::lua_tolstring(state, index, &mut size); + String::from_utf8_lossy(slice::from_raw_parts(data as *const u8, size)) + } + ffi::LUA_TTABLE => format!("
", ffi::lua_topointer(state, index)).into(), + ffi::LUA_TFUNCTION => format!("", ffi::lua_topointer(state, index)).into(), + ffi::LUA_TUSERDATA => format!("", ffi::lua_topointer(state, index)).into(), + ffi::LUA_TTHREAD => format!("", ffi::lua_topointer(state, index)).into(), + _ => "".into(), + } +} + +pub(crate) unsafe fn get_destructed_userdata_metatable(state: *mut ffi::lua_State) { + ffi::lua_pushlightuserdata( + state, + &DESTRUCTED_USERDATA_METATABLE as *const u8 as *mut c_void, + ); + ffi::lua_rawget(state, ffi::LUA_REGISTRYINDEX); +} + +static DESTRUCTED_USERDATA_METATABLE: u8 = 0; +static ERROR_PRINT_BUFFER_KEY: u8 = 0; diff --git a/third_party/cargo/vendor/mlua-0.5.3/src/value.rs b/third_party/cargo/vendor/mlua-0.5.3/src/value.rs new file mode 100644 index 0000000..15da2ec --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/src/value.rs @@ -0,0 +1,255 @@ +use std::iter::{self, FromIterator}; +use std::{slice, str, vec}; + +#[cfg(feature = "serialize")] +use { + serde::ser::{self, Serialize, Serializer}, + std::result::Result as StdResult, +}; + +use crate::error::{Error, Result}; +use crate::ffi; +use crate::function::Function; +use crate::lua::Lua; +use crate::string::String; +use crate::table::Table; +use crate::thread::Thread; +use crate::types::{Integer, LightUserData, Number}; +use crate::userdata::AnyUserData; + +/// A dynamically typed Lua value. The `String`, `Table`, `Function`, `Thread`, and `UserData` +/// variants contain handle types into the internal Lua state. It is a logic error to mix handle +/// types between separate `Lua` instances, or between a parent `Lua` instance and one received as a +/// parameter in a Rust callback, and doing so will result in a panic. +#[derive(Debug, Clone)] +pub enum Value<'lua> { + /// The Lua value `nil`. + Nil, + /// The Lua value `true` or `false`. + Boolean(bool), + /// A "light userdata" object, equivalent to a raw pointer. + LightUserData(LightUserData), + /// An integer number. + /// + /// Any Lua number convertible to a `Integer` will be represented as this variant. + Integer(Integer), + /// A floating point number. + Number(Number), + /// An interned string, managed by Lua. + /// + /// Unlike Rust strings, Lua strings may not be valid UTF-8. + String(String<'lua>), + /// Reference to a Lua table. + Table(Table<'lua>), + /// Reference to a Lua function (or closure). + Function(Function<'lua>), + /// Reference to a Lua thread (or coroutine). + Thread(Thread<'lua>), + /// Reference to a userdata object that holds a custom type which implements `UserData`. + /// Special builtin userdata types will be represented as other `Value` variants. + UserData(AnyUserData<'lua>), + /// `Error` is a special builtin userdata type. When received from Lua it is implicitly cloned. + Error(Error), +} +pub use self::Value::Nil; + +impl<'lua> Value<'lua> { + pub fn type_name(&self) -> &'static str { + match *self { + Value::Nil => "nil", + Value::Boolean(_) => "boolean", + Value::LightUserData(_) => "lightuserdata", + Value::Integer(_) => "integer", + Value::Number(_) => "number", + Value::String(_) => "string", + Value::Table(_) => "table", + Value::Function(_) => "function", + Value::Thread(_) => "thread", + Value::UserData(_) => "userdata", + Value::Error(_) => "error", + } + } + + /// Compares two values for equality. + /// + /// Equality comparisons do not convert strings to numbers or vice versa. + /// Tables, Functions, Threads, and Userdata are compared by reference: + /// two objects are considered equal only if they are the same object. + /// + /// If Tables or Userdata have `__eq` metamethod then mlua will try to invoke it. + /// The first value is checked first. If that value does not define a metamethod + /// for `__eq`, then mlua will check the second value. + /// Then mlua calls the metamethod with the two values as arguments, if found. + pub fn equals>(&self, other: T) -> Result { + match (self, other.as_ref()) { + (Value::Table(a), Value::Table(b)) => a.equals(b), + (Value::UserData(a), Value::UserData(b)) => a.equals(b), + _ => Ok(self == other.as_ref()), + } + } +} + +impl<'lua> PartialEq for Value<'lua> { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (Value::Nil, Value::Nil) => true, + (Value::Boolean(a), Value::Boolean(b)) => a == b, + (Value::LightUserData(a), Value::LightUserData(b)) => a == b, + (Value::Integer(a), Value::Integer(b)) => *a == *b, + (Value::Integer(a), Value::Number(b)) => *a as ffi::lua_Number == *b, + (Value::Number(a), Value::Integer(b)) => *a == *b as ffi::lua_Number, + (Value::Number(a), Value::Number(b)) => *a == *b, + (Value::String(a), Value::String(b)) => a == b, + (Value::Table(a), Value::Table(b)) => a == b, + (Value::Function(a), Value::Function(b)) => a == b, + (Value::Thread(a), Value::Thread(b)) => a == b, + (Value::UserData(a), Value::UserData(b)) => a == b, + _ => false, + } + } +} + +impl<'lua> AsRef> for Value<'lua> { + #[inline] + fn as_ref(&self) -> &Self { + self + } +} + +#[cfg(feature = "serialize")] +impl<'lua> Serialize for Value<'lua> { + fn serialize(&self, serializer: S) -> StdResult + where + S: Serializer, + { + match self { + Value::Nil => serializer.serialize_unit(), + Value::Boolean(b) => serializer.serialize_bool(*b), + #[allow(clippy::useless_conversion)] + Value::Integer(i) => serializer.serialize_i64((*i).into()), + #[allow(clippy::useless_conversion)] + Value::Number(n) => serializer.serialize_f64((*n).into()), + Value::String(s) => s.serialize(serializer), + Value::Table(t) => t.serialize(serializer), + Value::UserData(ud) => ud.serialize(serializer), + Value::LightUserData(ud) if ud.0.is_null() => serializer.serialize_none(), + Value::Error(_) | Value::LightUserData(_) | Value::Function(_) | Value::Thread(_) => { + let msg = format!("cannot serialize <{}>", self.type_name()); + Err(ser::Error::custom(msg)) + } + } + } +} + +/// Trait for types convertible to `Value`. +pub trait ToLua<'lua> { + /// Performs the conversion. + fn to_lua(self, lua: &'lua Lua) -> Result>; +} + +/// Trait for types convertible from `Value`. +pub trait FromLua<'lua>: Sized { + /// Performs the conversion. + fn from_lua(lua_value: Value<'lua>, lua: &'lua Lua) -> Result; +} + +/// Multiple Lua values used for both argument passing and also for multiple return values. +#[derive(Debug, Clone)] +pub struct MultiValue<'lua>(Vec>); + +impl<'lua> MultiValue<'lua> { + /// Creates an empty `MultiValue` containing no values. + pub fn new() -> MultiValue<'lua> { + MultiValue(Vec::new()) + } +} + +impl<'lua> Default for MultiValue<'lua> { + fn default() -> MultiValue<'lua> { + MultiValue::new() + } +} + +impl<'lua> FromIterator> for MultiValue<'lua> { + fn from_iter>>(iter: I) -> Self { + MultiValue::from_vec(Vec::from_iter(iter)) + } +} + +impl<'lua> IntoIterator for MultiValue<'lua> { + type Item = Value<'lua>; + type IntoIter = iter::Rev>>; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter().rev() + } +} + +impl<'a, 'lua> IntoIterator for &'a MultiValue<'lua> { + type Item = &'a Value<'lua>; + type IntoIter = iter::Rev>>; + + fn into_iter(self) -> Self::IntoIter { + (&self.0).iter().rev() + } +} + +impl<'lua> MultiValue<'lua> { + pub fn from_vec(mut v: Vec>) -> MultiValue<'lua> { + v.reverse(); + MultiValue(v) + } + + pub fn into_vec(self) -> Vec> { + let mut v = self.0; + v.reverse(); + v + } + + pub(crate) fn reserve(&mut self, size: usize) { + self.0.reserve(size); + } + + pub(crate) fn push_front(&mut self, value: Value<'lua>) { + self.0.push(value); + } + + pub(crate) fn pop_front(&mut self) -> Option> { + self.0.pop() + } + + pub fn len(&self) -> usize { + self.0.len() + } + + pub fn is_empty(&self) -> bool { + self.0.len() == 0 + } + + pub fn iter(&self) -> iter::Rev>> { + self.0.iter().rev() + } +} + +/// Trait for types convertible to any number of Lua values. +/// +/// This is a generalization of `ToLua`, allowing any number of resulting Lua values instead of just +/// one. Any type that implements `ToLua` will automatically implement this trait. +pub trait ToLuaMulti<'lua> { + /// Performs the conversion. + fn to_lua_multi(self, lua: &'lua Lua) -> Result>; +} + +/// Trait for types that can be created from an arbitrary number of Lua values. +/// +/// This is a generalization of `FromLua`, allowing an arbitrary number of Lua values to participate +/// in the conversion. Any type that implements `FromLua` will automatically implement this trait. +pub trait FromLuaMulti<'lua>: Sized { + /// Performs the conversion. + /// + /// In case `values` contains more values than needed to perform the conversion, the excess + /// values should be ignored. This reflects the semantics of Lua when calling a function or + /// assigning values. Similarly, if not enough values are given, conversions should assume that + /// any missing values are nil. + fn from_lua_multi(values: MultiValue<'lua>, lua: &'lua Lua) -> Result; +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/async.rs b/third_party/cargo/vendor/mlua-0.5.3/tests/async.rs new file mode 100644 index 0000000..7d87b49 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/async.rs @@ -0,0 +1,448 @@ +#![cfg(feature = "async")] +#![cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + feature(link_args) +)] + +#[cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + link_args = "-pagezero_size 10000 -image_base 100000000", + allow(unused_attributes) +)] +extern "system" {} + +use std::cell::Cell; +use std::rc::Rc; +use std::sync::{ + atomic::{AtomicI64, Ordering}, + Arc, +}; +use std::time::Duration; + +use futures_timer::Delay; +use futures_util::stream::TryStreamExt; + +use mlua::{ + Error, Function, Lua, Result, Table, TableExt, Thread, UserData, UserDataMethods, Value, +}; + +#[tokio::test] +async fn test_async_function() -> Result<()> { + let lua = Lua::new(); + + let f = lua + .create_async_function(|_lua, (a, b, c): (i64, i64, i64)| async move { Ok((a + b) * c) })?; + lua.globals().set("f", f)?; + + let res: i64 = lua.load("f(1, 2, 3)").eval_async().await?; + assert_eq!(res, 9); + + Ok(()) +} + +#[tokio::test] +async fn test_async_sleep() -> Result<()> { + let lua = Lua::new(); + + let sleep = lua.create_async_function(move |_lua, n: u64| async move { + Delay::new(Duration::from_millis(n)).await; + Ok(format!("elapsed:{}ms", n)) + })?; + lua.globals().set("sleep", sleep)?; + + let res: String = lua.load(r"return sleep(...)").call_async(100).await?; + assert_eq!(res, "elapsed:100ms"); + + Ok(()) +} + +#[tokio::test] +async fn test_async_call() -> Result<()> { + let lua = Lua::new(); + + let hello = lua.create_async_function(|_lua, name: String| async move { + Delay::new(Duration::from_millis(10)).await; + Ok(format!("hello, {}!", name)) + })?; + + match hello.call::<_, ()>("alex") { + Err(Error::RuntimeError(_)) => {} + _ => panic!( + "non-async executing async function must fail on the yield stage with RuntimeError" + ), + }; + + assert_eq!(hello.call_async::<_, String>("alex").await?, "hello, alex!"); + + // Executing non-async functions using async call is allowed + let sum = lua.create_function(|_lua, (a, b): (i64, i64)| return Ok(a + b))?; + assert_eq!(sum.call_async::<_, i64>((5, 1)).await?, 6); + + Ok(()) +} + +#[tokio::test] +async fn test_async_bind_call() -> Result<()> { + let lua = Lua::new(); + + let sum = lua.create_async_function(|_lua, (a, b): (i64, i64)| async move { Ok(a + b) })?; + + let plus_10 = sum.bind(10)?; + lua.globals().set("plus_10", plus_10)?; + + assert_eq!(lua.load("plus_10(-1)").eval_async::().await?, 9); + assert_eq!(lua.load("plus_10(1)").eval_async::().await?, 11); + + Ok(()) +} + +#[tokio::test] +async fn test_async_handle_yield() -> Result<()> { + let lua = Lua::new(); + + let sum = lua.create_async_function(|_lua, (a, b): (i64, i64)| async move { + Delay::new(Duration::from_millis(10)).await; + Ok(a + b) + })?; + + lua.globals().set("sleep_sum", sum)?; + + let res: String = lua + .load( + r#" + sum = sleep_sum(6, 7) + assert(sum == 13) + coroutine.yield("in progress") + return "done" + "#, + ) + .call_async(()) + .await?; + + assert_eq!(res, "done"); + + let min = lua + .load( + r#" + function (a, b) + coroutine.yield("ignore me") + if a < b then return a else return b end + end + "#, + ) + .eval::()?; + assert_eq!(min.call_async::<_, i64>((-1, 1)).await?, -1); + + Ok(()) +} + +#[tokio::test] +async fn test_async_multi_return_nil() -> Result<()> { + let lua = Lua::new(); + lua.globals().set( + "func", + lua.create_async_function(|_, _: ()| async { Ok((Option::::None, "error")) })?, + )?; + + lua.load( + r#" + local ok, err = func() + assert(err == "error") + "#, + ) + .exec_async() + .await +} + +#[tokio::test] +async fn test_async_return_async_closure() -> Result<()> { + let lua = Lua::new(); + + let f = lua.create_async_function(|lua, a: i64| async move { + Delay::new(Duration::from_millis(10)).await; + + let g = lua.create_async_function(move |_, b: i64| async move { + Delay::new(Duration::from_millis(10)).await; + return Ok(a + b); + })?; + + Ok(g) + })?; + + lua.globals().set("f", f)?; + + let res: i64 = lua + .load("local g = f(1); return g(2) + g(3)") + .call_async(()) + .await?; + + assert_eq!(res, 7); + + Ok(()) +} + +#[tokio::test] +async fn test_async_thread_stream() -> Result<()> { + let lua = Lua::new(); + + let thread = lua.create_thread( + lua.load( + r#" + function (sum) + for i = 1,10 do + sum = sum + i + coroutine.yield(sum) + end + return sum + end + "#, + ) + .eval()?, + )?; + + let mut stream = thread.into_async::<_, i64>(1); + let mut sum = 0; + while let Some(n) = stream.try_next().await? { + sum += n; + } + + assert_eq!(sum, 286); + + Ok(()) +} + +#[tokio::test] +async fn test_async_thread() -> Result<()> { + let lua = Lua::new(); + + let cnt = Arc::new(10); // sleep 10ms + let cnt2 = cnt.clone(); + let f = lua.create_async_function(move |_lua, ()| { + let cnt3 = cnt2.clone(); + async move { + Delay::new(Duration::from_millis(*cnt3.as_ref())).await; + Ok("done") + } + })?; + + let res: String = lua.create_thread(f)?.into_async(()).await?; + + assert_eq!(res, "done"); + + assert_eq!(Arc::strong_count(&cnt), 2); + lua.gc_collect()?; // thread_s is non-resumable and subject to garbage collection + assert_eq!(Arc::strong_count(&cnt), 1); + + Ok(()) +} + +#[tokio::test] +async fn test_async_table() -> Result<()> { + let lua = Lua::new(); + + let table = lua.create_table()?; + table.set("val", 10)?; + + let get_value = lua.create_async_function(|_, table: Table| async move { + Delay::new(Duration::from_millis(10)).await; + table.get::<_, i64>("val") + })?; + table.set("get_value", get_value)?; + + let set_value = lua.create_async_function(|_, (table, n): (Table, i64)| async move { + Delay::new(Duration::from_millis(10)).await; + table.set("val", n) + })?; + table.set("set_value", set_value)?; + + let sleep = lua.create_async_function(|_, n| async move { + Delay::new(Duration::from_millis(n)).await; + Ok(format!("elapsed:{}ms", n)) + })?; + table.set("sleep", sleep)?; + + assert_eq!( + table + .call_async_method::<_, _, i64>("get_value", ()) + .await?, + 10 + ); + table.call_async_method("set_value", 15).await?; + assert_eq!( + table + .call_async_method::<_, _, i64>("get_value", ()) + .await?, + 15 + ); + assert_eq!( + table + .call_async_function::<_, _, String>("sleep", 7) + .await?, + "elapsed:7ms" + ); + + Ok(()) +} + +#[tokio::test] +async fn test_async_userdata() -> Result<()> { + #[derive(Clone)] + struct MyUserData(Arc); + + impl UserData for MyUserData { + fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_async_method("get_value", |_, data, ()| async move { + Delay::new(Duration::from_millis(10)).await; + Ok(data.0.load(Ordering::Relaxed)) + }); + + methods.add_async_method("set_value", |_, data, n| async move { + Delay::new(Duration::from_millis(10)).await; + data.0.store(n, Ordering::Relaxed); + Ok(()) + }); + + methods.add_async_function("sleep", |_, n| async move { + Delay::new(Duration::from_millis(n)).await; + Ok(format!("elapsed:{}ms", n)) + }); + } + } + + let lua = Lua::new(); + let globals = lua.globals(); + + let userdata = lua.create_userdata(MyUserData(Arc::new(AtomicI64::new(11))))?; + globals.set("userdata", userdata.clone())?; + + lua.load( + r#" + assert(userdata:get_value() == 11) + userdata:set_value(12) + assert(userdata.sleep(5) == "elapsed:5ms") + assert(userdata:get_value() == 12) + "#, + ) + .exec_async() + .await?; + + Ok(()) +} + +#[tokio::test] +async fn test_async_scope() -> Result<()> { + let ref lua = Lua::new(); + + let ref rc = Rc::new(Cell::new(0)); + + let fut = lua.async_scope(|scope| async move { + let f = scope.create_async_function(move |_, n: u64| { + let rc2 = rc.clone(); + async move { + rc2.set(42); + Delay::new(Duration::from_millis(n)).await; + assert_eq!(Rc::strong_count(&rc2), 2); + Ok(()) + } + })?; + + lua.globals().set("f", f.clone())?; + + assert_eq!(Rc::strong_count(rc), 1); + let _ = f.call_async::(10).await?; + assert_eq!(Rc::strong_count(rc), 1); + + // Create future in partialy polled state (Poll::Pending) + let g = lua.create_thread(f)?; + g.resume::(10)?; + lua.globals().set("g", g)?; + assert_eq!(Rc::strong_count(rc), 2); + + Ok(()) + }); + + assert_eq!(Rc::strong_count(rc), 1); + let _ = fut.await?; + assert_eq!(Rc::strong_count(rc), 1); + + match lua + .globals() + .get::<_, Function>("f")? + .call_async::<_, ()>(10) + .await + { + Err(Error::CallbackError { ref cause, .. }) => match cause.as_ref() { + Error::CallbackDestructed => {} + e => panic!("expected `CallbackDestructed` error cause, got {:?}", e), + }, + r => panic!("improper return for destructed function: {:?}", r), + }; + + match lua.globals().get::<_, Thread>("g")?.resume::<_, Value>(()) { + Err(Error::CallbackError { ref cause, .. }) => match cause.as_ref() { + Error::CallbackDestructed => {} + e => panic!("expected `CallbackDestructed` error cause, got {:?}", e), + }, + r => panic!("improper return for destructed function: {:?}", r), + }; + + Ok(()) +} + +#[tokio::test] +async fn test_async_scope_userdata() -> Result<()> { + #[derive(Clone)] + struct MyUserData(Arc); + + impl UserData for MyUserData { + fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_async_method("get_value", |_, data, ()| async move { + Delay::new(Duration::from_millis(10)).await; + Ok(data.0.load(Ordering::Relaxed)) + }); + + methods.add_async_method("set_value", |_, data, n| async move { + Delay::new(Duration::from_millis(10)).await; + data.0.store(n, Ordering::Relaxed); + Ok(()) + }); + + methods.add_async_function("sleep", |_, n| async move { + Delay::new(Duration::from_millis(n)).await; + Ok(format!("elapsed:{}ms", n)) + }); + } + } + + let ref lua = Lua::new(); + + let ref arc = Arc::new(AtomicI64::new(11)); + + lua.async_scope(|scope| async move { + let ud = scope.create_userdata(MyUserData(arc.clone()))?; + lua.globals().set("userdata", ud)?; + lua.load( + r#" + assert(userdata:get_value() == 11) + userdata:set_value(12) + assert(userdata.sleep(5) == "elapsed:5ms") + assert(userdata:get_value() == 12) + "#, + ) + .exec_async() + .await + }) + .await?; + + assert_eq!(Arc::strong_count(arc), 1); + + match lua.load("userdata:get_value()").exec_async().await { + Err(Error::CallbackError { ref cause, .. }) => match cause.as_ref() { + Error::CallbackDestructed => {} + e => panic!("expected `CallbackDestructed` error cause, got {:?}", e), + }, + r => panic!("improper return for destructed userdata: {:?}", r), + }; + + Ok(()) +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/byte_string.rs b/third_party/cargo/vendor/mlua-0.5.3/tests/byte_string.rs new file mode 100644 index 0000000..22752c8 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/byte_string.rs @@ -0,0 +1,108 @@ +#![cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + feature(link_args) +)] + +#[cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + link_args = "-pagezero_size 10000 -image_base 100000000", + allow(unused_attributes) +)] +extern "system" {} + +use bstr::{BStr, BString}; +use mlua::{Lua, Result}; + +#[test] +fn byte_string_round_trip() -> Result<()> { + let lua = Lua::new(); + + lua.load( + r#" + invalid_sequence_identifier = "\160\161" + invalid_2_octet_sequence_2nd = "\195\040" + invalid_3_octet_sequence_2nd = "\226\040\161" + invalid_3_octet_sequence_3rd = "\226\130\040" + invalid_4_octet_sequence_2nd = "\240\040\140\188" + invalid_4_octet_sequence_3rd = "\240\144\040\188" + invalid_4_octet_sequence_4th = "\240\040\140\040" + + an_actual_string = "Hello, world!" + "#, + ) + .exec()?; + + let globals = lua.globals(); + + let isi = globals.get::<_, BString>("invalid_sequence_identifier")?; + assert_eq!(isi, [0xa0, 0xa1].as_ref()); + + let i2os2 = globals.get::<_, BString>("invalid_2_octet_sequence_2nd")?; + assert_eq!(i2os2, [0xc3, 0x28].as_ref()); + + let i3os2 = globals.get::<_, BString>("invalid_3_octet_sequence_2nd")?; + assert_eq!(i3os2, [0xe2, 0x28, 0xa1].as_ref()); + + let i3os3 = globals.get::<_, BString>("invalid_3_octet_sequence_3rd")?; + assert_eq!(i3os3, [0xe2, 0x82, 0x28].as_ref()); + + let i4os2 = globals.get::<_, BString>("invalid_4_octet_sequence_2nd")?; + assert_eq!(i4os2, [0xf0, 0x28, 0x8c, 0xbc].as_ref()); + + let i4os3 = globals.get::<_, BString>("invalid_4_octet_sequence_3rd")?; + assert_eq!(i4os3, [0xf0, 0x90, 0x28, 0xbc].as_ref()); + + let i4os4 = globals.get::<_, BString>("invalid_4_octet_sequence_4th")?; + assert_eq!(i4os4, [0xf0, 0x28, 0x8c, 0x28].as_ref()); + + let aas = globals.get::<_, BString>("an_actual_string")?; + assert_eq!(aas, b"Hello, world!".as_ref()); + + globals.set::<_, &BStr>("bstr_invalid_sequence_identifier", isi.as_ref())?; + globals.set::<_, &BStr>("bstr_invalid_2_octet_sequence_2nd", i2os2.as_ref())?; + globals.set::<_, &BStr>("bstr_invalid_3_octet_sequence_2nd", i3os2.as_ref())?; + globals.set::<_, &BStr>("bstr_invalid_3_octet_sequence_3rd", i3os3.as_ref())?; + globals.set::<_, &BStr>("bstr_invalid_4_octet_sequence_2nd", i4os2.as_ref())?; + globals.set::<_, &BStr>("bstr_invalid_4_octet_sequence_3rd", i4os3.as_ref())?; + globals.set::<_, &BStr>("bstr_invalid_4_octet_sequence_4th", i4os4.as_ref())?; + globals.set::<_, &BStr>("bstr_an_actual_string", aas.as_ref())?; + + lua.load( + r#" + assert(bstr_invalid_sequence_identifier == invalid_sequence_identifier) + assert(bstr_invalid_2_octet_sequence_2nd == invalid_2_octet_sequence_2nd) + assert(bstr_invalid_3_octet_sequence_2nd == invalid_3_octet_sequence_2nd) + assert(bstr_invalid_3_octet_sequence_3rd == invalid_3_octet_sequence_3rd) + assert(bstr_invalid_4_octet_sequence_2nd == invalid_4_octet_sequence_2nd) + assert(bstr_invalid_4_octet_sequence_3rd == invalid_4_octet_sequence_3rd) + assert(bstr_invalid_4_octet_sequence_4th == invalid_4_octet_sequence_4th) + assert(bstr_an_actual_string == an_actual_string) + "#, + ) + .exec()?; + + globals.set::<_, BString>("bstring_invalid_sequence_identifier", isi)?; + globals.set::<_, BString>("bstring_invalid_2_octet_sequence_2nd", i2os2)?; + globals.set::<_, BString>("bstring_invalid_3_octet_sequence_2nd", i3os2)?; + globals.set::<_, BString>("bstring_invalid_3_octet_sequence_3rd", i3os3)?; + globals.set::<_, BString>("bstring_invalid_4_octet_sequence_2nd", i4os2)?; + globals.set::<_, BString>("bstring_invalid_4_octet_sequence_3rd", i4os3)?; + globals.set::<_, BString>("bstring_invalid_4_octet_sequence_4th", i4os4)?; + globals.set::<_, BString>("bstring_an_actual_string", aas)?; + + lua.load( + r#" + assert(bstring_invalid_sequence_identifier == invalid_sequence_identifier) + assert(bstring_invalid_2_octet_sequence_2nd == invalid_2_octet_sequence_2nd) + assert(bstring_invalid_3_octet_sequence_2nd == invalid_3_octet_sequence_2nd) + assert(bstring_invalid_3_octet_sequence_3rd == invalid_3_octet_sequence_3rd) + assert(bstring_invalid_4_octet_sequence_2nd == invalid_4_octet_sequence_2nd) + assert(bstring_invalid_4_octet_sequence_3rd == invalid_4_octet_sequence_3rd) + assert(bstring_invalid_4_octet_sequence_4th == invalid_4_octet_sequence_4th) + assert(bstring_an_actual_string == an_actual_string) + "#, + ) + .exec()?; + + Ok(()) +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/compile.rs b/third_party/cargo/vendor/mlua-0.5.3/tests/compile.rs new file mode 100644 index 0000000..e4d822a --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/compile.rs @@ -0,0 +1,24 @@ +#[test] +#[ignore] +fn test_compilation() { + let t = trybuild::TestCases::new(); + + t.compile_fail("tests/compile/function_borrow.rs"); + t.compile_fail("tests/compile/lua_norefunwindsafe.rs"); + t.compile_fail("tests/compile/ref_nounwindsafe.rs"); + t.compile_fail("tests/compile/scope_callback_capture.rs"); + t.compile_fail("tests/compile/scope_callback_inner.rs"); + t.compile_fail("tests/compile/scope_callback_outer.rs"); + t.compile_fail("tests/compile/scope_invariance.rs"); + t.compile_fail("tests/compile/scope_mutable_aliasing.rs"); + t.compile_fail("tests/compile/scope_userdata_borrow.rs"); + t.compile_fail("tests/compile/static_callback_args.rs"); + + #[cfg(feature = "async")] + t.compile_fail("tests/compile/async_nonstatic_userdata.rs"); + + #[cfg(feature = "send")] + t.compile_fail("tests/compile/non_send.rs"); + #[cfg(not(feature = "send"))] + t.pass("tests/compile/non_send.rs"); +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/compile/async_nonstatic_userdata.rs b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/async_nonstatic_userdata.rs new file mode 100644 index 0000000..8aede32 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/async_nonstatic_userdata.rs @@ -0,0 +1,17 @@ +use mlua::{Lua, UserData, UserDataMethods}; + +fn main() { + let ref lua = Lua::new(); + + #[derive(Clone)] + struct MyUserData<'a>(&'a i64); + + impl<'a> UserData for MyUserData<'a> { + fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_async_method("print", |_, data, ()| async move { + println!("{}", data.0); + Ok(()) + }); + } + } +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/compile/async_nonstatic_userdata.stderr b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/async_nonstatic_userdata.stderr new file mode 100644 index 0000000..e6f8cf7 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/async_nonstatic_userdata.stderr @@ -0,0 +1,36 @@ +error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements + --> $DIR/async_nonstatic_userdata.rs:11:72 + | +11 | methods.add_async_method("print", |_, data, ()| async move { + | ________________________________________________________________________^ +12 | | println!("{}", data.0); +13 | | Ok(()) +14 | | }); + | |_____________^ + | +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 9:10... + --> $DIR/async_nonstatic_userdata.rs:9:10 + | +9 | impl<'a> UserData for MyUserData<'a> { + | ^^ +note: ...so that the types are compatible + --> $DIR/async_nonstatic_userdata.rs:11:72 + | +11 | methods.add_async_method("print", |_, data, ()| async move { + | ________________________________________________________________________^ +12 | | println!("{}", data.0); +13 | | Ok(()) +14 | | }); + | |_____________^ + = note: expected `(MyUserData<'_>,)` + found `(MyUserData<'a>,)` +note: but, the lifetime must be valid for the lifetime `'lua` as defined on the method body at 10:24... + --> $DIR/async_nonstatic_userdata.rs:10:24 + | +10 | fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { + | ^^^^ +note: ...so that the type `impl Future` will meet its required lifetime bounds + --> $DIR/async_nonstatic_userdata.rs:11:21 + | +11 | methods.add_async_method("print", |_, data, ()| async move { + | ^^^^^^^^^^^^^^^^ diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/compile/function_borrow.rs b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/function_borrow.rs new file mode 100644 index 0000000..f64f3b8 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/function_borrow.rs @@ -0,0 +1,12 @@ +use mlua::{Lua, Result}; + +struct Test(i32); + +fn main() { + let test = Test(0); + + let lua = Lua::new(); + let _ = lua.create_function(|_, ()| -> Result { + Ok(test.0) + }); +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/compile/function_borrow.stderr b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/function_borrow.stderr new file mode 100644 index 0000000..c1c4d1f --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/function_borrow.stderr @@ -0,0 +1,20 @@ +error[E0373]: closure may outlive the current function, but it borrows `test`, which is owned by the current function + --> $DIR/function_borrow.rs:9:33 + | +9 | let _ = lua.create_function(|_, ()| -> Result { + | ^^^^^^^^^^^^^^^^^^^^^^ may outlive borrowed value `test` +10 | Ok(test.0) + | ---- `test` is borrowed here + | +note: function requires argument type to outlive `'static` + --> $DIR/function_borrow.rs:9:13 + | +9 | let _ = lua.create_function(|_, ()| -> Result { + | _____________^ +10 | | Ok(test.0) +11 | | }); + | |______^ +help: to force the closure to take ownership of `test` (and any other referenced variables), use the `move` keyword + | +9 | let _ = lua.create_function(move |_, ()| -> Result { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/compile/lua_norefunwindsafe.rs b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/lua_norefunwindsafe.rs new file mode 100644 index 0000000..805f61f --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/lua_norefunwindsafe.rs @@ -0,0 +1,8 @@ +use std::panic::catch_unwind; + +use mlua::Lua; + +fn main() { + let lua = Lua::new(); + catch_unwind(|| lua.create_table().unwrap()); +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/compile/lua_norefunwindsafe.stderr b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/lua_norefunwindsafe.stderr new file mode 100644 index 0000000..e687ffc --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/lua_norefunwindsafe.stderr @@ -0,0 +1,16 @@ +error[E0277]: the type `UnsafeCell<()>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary + --> $DIR/lua_norefunwindsafe.rs:7:5 + | +7 | catch_unwind(|| lua.create_table().unwrap()); + | ^^^^^^^^^^^^ `UnsafeCell<()>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary + | + ::: $RUST/std/src/panic.rs + | + | pub fn catch_unwind R + UnwindSafe, R>(f: F) -> Result { + | ---------- required by this bound in `catch_unwind` + | + = help: within `Lua`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<()>` + = note: required because it appears within the type `PhantomData>` + = note: required because it appears within the type `Lua` + = note: required because of the requirements on the impl of `UnwindSafe` for `&Lua` + = note: required because it appears within the type `[closure@$DIR/tests/compile/lua_norefunwindsafe.rs:7:18: 7:48]` diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/compile/non_send.rs b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/non_send.rs new file mode 100644 index 0000000..fe030a5 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/non_send.rs @@ -0,0 +1,17 @@ +use std::cell::Cell; +use std::rc::Rc; + +use mlua::{Lua, Result}; + +fn main() -> Result<()> { + let lua = Lua::new(); + + let data = Rc::new(Cell::new(0)); + + lua.create_function(move |_, ()| { + Ok(data.get()) + })? + .call::<_, i32>(())?; + + Ok(()) +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/compile/non_send.stderr b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/non_send.stderr new file mode 100644 index 0000000..6a86081 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/non_send.stderr @@ -0,0 +1,14 @@ +error[E0277]: `Rc>` cannot be sent between threads safely + --> $DIR/non_send.rs:11:9 + | +11 | lua.create_function(move |_, ()| { + | _________^^^^^^^^^^^^^^^_- + | | | + | | `Rc>` cannot be sent between threads safely +12 | | Ok(data.get()) +13 | | })? + | |_____- within this `[closure@$DIR/tests/compile/non_send.rs:11:25: 13:6]` + | + = help: within `[closure@$DIR/tests/compile/non_send.rs:11:25: 13:6]`, the trait `Send` is not implemented for `Rc>` + = note: required because it appears within the type `[closure@$DIR/tests/compile/non_send.rs:11:25: 13:6]` + = note: required because of the requirements on the impl of `mlua::types::MaybeSend` for `[closure@$DIR/tests/compile/non_send.rs:11:25: 13:6]` diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/compile/ref_nounwindsafe.rs b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/ref_nounwindsafe.rs new file mode 100644 index 0000000..8518c40 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/ref_nounwindsafe.rs @@ -0,0 +1,9 @@ +use std::panic::catch_unwind; + +use mlua::Lua; + +fn main() { + let lua = Lua::new(); + let table = lua.create_table().unwrap(); + catch_unwind(move || table.set("a", "b").unwrap()); +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/compile/ref_nounwindsafe.stderr b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/ref_nounwindsafe.stderr new file mode 100644 index 0000000..b6cf3f4 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/ref_nounwindsafe.stderr @@ -0,0 +1,18 @@ +error[E0277]: the type `UnsafeCell<()>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary + --> $DIR/ref_nounwindsafe.rs:8:5 + | +8 | catch_unwind(move || table.set("a", "b").unwrap()); + | ^^^^^^^^^^^^ `UnsafeCell<()>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary + | + ::: $RUST/std/src/panic.rs + | + | pub fn catch_unwind R + UnwindSafe, R>(f: F) -> Result { + | ---------- required by this bound in `catch_unwind` + | + = help: within `Lua`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<()>` + = note: required because it appears within the type `PhantomData>` + = note: required because it appears within the type `Lua` + = note: required because of the requirements on the impl of `UnwindSafe` for `&Lua` + = note: required because it appears within the type `mlua::types::LuaRef<'_>` + = note: required because it appears within the type `LuaTable<'_>` + = note: required because it appears within the type `[closure@$DIR/tests/compile/ref_nounwindsafe.rs:8:18: 8:54]` diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_callback_capture.rs b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_callback_capture.rs new file mode 100644 index 0000000..927c36d --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_callback_capture.rs @@ -0,0 +1,18 @@ +use mlua::{Lua, Table}; + +fn main() { + let lua = Lua::new(); + lua.scope(|scope| { + let mut inner: Option
= None; + let f = scope + .create_function_mut(move |_, t: Table| { + if let Some(old) = inner.take() { + // Access old callback `Lua`. + } + inner = Some(t); + Ok(()) + })?; + f.call::<_, ()>(lua.create_table()?)?; + Ok(()) + }); +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_callback_capture.stderr b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_callback_capture.stderr new file mode 100644 index 0000000..5c8914b --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_callback_capture.stderr @@ -0,0 +1,26 @@ +warning: unused variable: `old` + --> $DIR/scope_callback_capture.rs:9:29 + | +9 | if let Some(old) = inner.take() { + | ^^^ help: if this is intentional, prefix it with an underscore: `_old` + | + = note: `#[warn(unused_variables)]` on by default + +error[E0521]: borrowed data escapes outside of closure + --> $DIR/scope_callback_capture.rs:7:17 + | +5 | lua.scope(|scope| { + | ----- + | | + | `scope` declared here, outside of the closure body + | `scope` is a reference that is only valid in the closure body +6 | let mut inner: Option
= None; +7 | let f = scope + | _________________^ +8 | | .create_function_mut(move |_, t: Table| { +9 | | if let Some(old) = inner.take() { +10 | | // Access old callback `Lua`. +... | +13 | | Ok(()) +14 | | })?; + | |______________^ `scope` escapes the closure body here diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_callback_inner.rs b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_callback_inner.rs new file mode 100644 index 0000000..037c6ac --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_callback_inner.rs @@ -0,0 +1,15 @@ +use mlua::{Lua, Table}; + +fn main() { + let lua = Lua::new(); + lua.scope(|scope| { + let mut inner: Option
= None; + let f = scope + .create_function_mut(|_, t: Table| { + inner = Some(t); + Ok(()) + })?; + f.call::<_, ()>(lua.create_table()?)?; + Ok(()) + }); +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_callback_inner.stderr b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_callback_inner.stderr new file mode 100644 index 0000000..6718c98 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_callback_inner.stderr @@ -0,0 +1,42 @@ +error[E0521]: borrowed data escapes outside of closure + --> $DIR/scope_callback_inner.rs:7:17 + | +5 | lua.scope(|scope| { + | ----- + | | + | `scope` declared here, outside of the closure body + | `scope` is a reference that is only valid in the closure body +6 | let mut inner: Option
= None; +7 | let f = scope + | _________________^ +8 | | .create_function_mut(|_, t: Table| { +9 | | inner = Some(t); +10 | | Ok(()) +11 | | })?; + | |______________^ `scope` escapes the closure body here + +error[E0373]: closure may outlive the current function, but it borrows `inner`, which is owned by the current function + --> $DIR/scope_callback_inner.rs:8:34 + | +5 | lua.scope(|scope| { + | ----- has type `&Scope<'_, '2>` +... +8 | .create_function_mut(|_, t: Table| { + | ^^^^^^^^^^^^^ may outlive borrowed value `inner` +9 | inner = Some(t); + | ----- `inner` is borrowed here + | +note: function requires argument type to outlive `'2` + --> $DIR/scope_callback_inner.rs:7:17 + | +7 | let f = scope + | _________________^ +8 | | .create_function_mut(|_, t: Table| { +9 | | inner = Some(t); +10 | | Ok(()) +11 | | })?; + | |______________^ +help: to force the closure to take ownership of `inner` (and any other referenced variables), use the `move` keyword + | +8 | .create_function_mut(move |_, t: Table| { + | ^^^^^^^^^^^^^^^^^^ diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_callback_outer.rs b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_callback_outer.rs new file mode 100644 index 0000000..7c9974e --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_callback_outer.rs @@ -0,0 +1,15 @@ +use mlua::{Lua, Table}; + +fn main() { + let lua = Lua::new(); + let mut outer: Option
= None; + lua.scope(|scope| { + let f = scope + .create_function_mut(|_, t: Table| { + outer = Some(t); + Ok(()) + })?; + f.call::<_, ()>(lua.create_table()?)?; + Ok(()) + }); +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_callback_outer.stderr b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_callback_outer.stderr new file mode 100644 index 0000000..2a15e4a --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_callback_outer.stderr @@ -0,0 +1,30 @@ +error[E0521]: borrowed data escapes outside of closure + --> $DIR/scope_callback_outer.rs:7:17 + | +6 | lua.scope(|scope| { + | ----- + | | + | `scope` declared here, outside of the closure body + | `scope` is a reference that is only valid in the closure body +7 | let f = scope + | _________________^ +8 | | .create_function_mut(|_, t: Table| { +9 | | outer = Some(t); +10 | | Ok(()) +11 | | })?; + | |______________^ `scope` escapes the closure body here + +error[E0597]: `outer` does not live long enough + --> $DIR/scope_callback_outer.rs:9:17 + | +6 | lua.scope(|scope| { + | ------- value captured here +... +9 | outer = Some(t); + | ^^^^^ borrowed value does not live long enough +... +15 | } + | - + | | + | `outer` dropped here while still borrowed + | borrow might be used here, when `outer` is dropped and runs the destructor for type `Option>` diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_invariance.rs b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_invariance.rs new file mode 100644 index 0000000..e4f4ea7 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_invariance.rs @@ -0,0 +1,23 @@ +use mlua::Lua; + +struct Test { + field: i32, +} + +fn main() { + let lua = Lua::new(); + lua.scope(|scope| { + let f = { + let mut test = Test { field: 0 }; + + scope + .create_function_mut(|_, ()| { + test.field = 42; + //~^ error: `test` does not live long enough + Ok(()) + })? + }; + + f.call::<_, ()>(()) + }); +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_invariance.stderr b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_invariance.stderr new file mode 100644 index 0000000..a91260c --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_invariance.stderr @@ -0,0 +1,25 @@ +error[E0373]: closure may outlive the current function, but it borrows `test`, which is owned by the current function + --> $DIR/scope_invariance.rs:14:38 + | +9 | lua.scope(|scope| { + | ----- has type `&Scope<'_, '1>` +... +14 | .create_function_mut(|_, ()| { + | ^^^^^^^ may outlive borrowed value `test` +15 | test.field = 42; + | ---- `test` is borrowed here + | +note: function requires argument type to outlive `'1` + --> $DIR/scope_invariance.rs:13:13 + | +13 | / scope +14 | | .create_function_mut(|_, ()| { +15 | | test.field = 42; +16 | | //~^ error: `test` does not live long enough +17 | | Ok(()) +18 | | })? + | |__________________^ +help: to force the closure to take ownership of `test` (and any other referenced variables), use the `move` keyword + | +14 | .create_function_mut(move |_, ()| { + | ^^^^^^^^^^^^ diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_mutable_aliasing.rs b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_mutable_aliasing.rs new file mode 100644 index 0000000..6bdf498 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_mutable_aliasing.rs @@ -0,0 +1,15 @@ +use mlua::{Lua, UserData}; + +fn main() { + struct MyUserData<'a>(&'a mut i32); + impl<'a> UserData for MyUserData<'a> {}; + + let mut i = 1; + + let lua = Lua::new(); + lua.scope(|scope| { + let _a = scope.create_nonstatic_userdata(MyUserData(&mut i)).unwrap(); + let _b = scope.create_nonstatic_userdata(MyUserData(&mut i)).unwrap(); + Ok(()) + }); +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_mutable_aliasing.stderr b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_mutable_aliasing.stderr new file mode 100644 index 0000000..c661826 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_mutable_aliasing.stderr @@ -0,0 +1,9 @@ +error[E0499]: cannot borrow `i` as mutable more than once at a time + --> $DIR/scope_mutable_aliasing.rs:12:61 + | +11 | let _a = scope.create_nonstatic_userdata(MyUserData(&mut i)).unwrap(); + | ------ first mutable borrow occurs here +12 | let _b = scope.create_nonstatic_userdata(MyUserData(&mut i)).unwrap(); + | ------------------------- ^^^^^^ second mutable borrow occurs here + | | + | first borrow later used by call diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_userdata_borrow.rs b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_userdata_borrow.rs new file mode 100644 index 0000000..6546633 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_userdata_borrow.rs @@ -0,0 +1,19 @@ +use mlua::{Lua, UserData}; + +fn main() { + // Should not allow userdata borrow to outlive lifetime of AnyUserData handle + struct MyUserData<'a>(&'a i32); + impl<'a> UserData for MyUserData<'a> {}; + + let igood = 1; + + let lua = Lua::new(); + lua.scope(|scope| { + let _ugood = scope.create_nonstatic_userdata(MyUserData(&igood)).unwrap(); + let _ubad = { + let ibad = 42; + scope.create_nonstatic_userdata(MyUserData(&ibad)).unwrap(); + }; + Ok(()) + }); +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_userdata_borrow.stderr b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_userdata_borrow.stderr new file mode 100644 index 0000000..02e1bdb --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/scope_userdata_borrow.stderr @@ -0,0 +1,13 @@ +error[E0597]: `ibad` does not live long enough + --> $DIR/scope_userdata_borrow.rs:15:56 + | +11 | lua.scope(|scope| { + | ----- has type `&Scope<'_, '1>` +... +15 | scope.create_nonstatic_userdata(MyUserData(&ibad)).unwrap(); + | -------------------------------------------^^^^^-- + | | | + | | borrowed value does not live long enough + | argument requires that `ibad` is borrowed for `'1` +16 | }; + | - `ibad` dropped here while still borrowed diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/compile/static_callback_args.rs b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/static_callback_args.rs new file mode 100644 index 0000000..66dbf8b --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/static_callback_args.rs @@ -0,0 +1,32 @@ +use std::cell::RefCell; + +use mlua::{Lua, Result, Table}; + +fn main() -> Result<()> { + thread_local! { + static BAD_TIME: RefCell>> = RefCell::new(None); + } + + let lua = Lua::new(); + + lua.create_function(|_, table: Table| { + BAD_TIME.with(|bt| { + *bt.borrow_mut() = Some(table); + }); + Ok(()) + })? + .call::<_, ()>(lua.create_table()?)?; + + // In debug, this will panic with a reference leak before getting to the next part but + // it segfaults anyway. + drop(lua); + + BAD_TIME.with(|bt| { + println!( + "you're gonna have a bad time: {}", + bt.borrow().as_ref().unwrap().len().unwrap() + ); + }); + + Ok(()) +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/compile/static_callback_args.stderr b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/static_callback_args.stderr new file mode 100644 index 0000000..561bcbe --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/static_callback_args.stderr @@ -0,0 +1,35 @@ +error[E0597]: `lua` does not live long enough + --> $DIR/static_callback_args.rs:12:5 + | +12 | lua.create_function(|_, table: Table| { + | -^^ + | | + | _____borrowed value does not live long enough + | | +13 | | BAD_TIME.with(|bt| { +14 | | *bt.borrow_mut() = Some(table); +15 | | }); +16 | | Ok(()) +17 | | })? + | |______- argument requires that `lua` is borrowed for `'static` +... +32 | } + | - `lua` dropped here while still borrowed + +error[E0505]: cannot move out of `lua` because it is borrowed + --> $DIR/static_callback_args.rs:22:10 + | +12 | lua.create_function(|_, table: Table| { + | --- + | | + | _____borrow of `lua` occurs here + | | +13 | | BAD_TIME.with(|bt| { +14 | | *bt.borrow_mut() = Some(table); +15 | | }); +16 | | Ok(()) +17 | | })? + | |______- argument requires that `lua` is borrowed for `'static` +... +22 | drop(lua); + | ^^^ move out of `lua` occurs here diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/compile/userdata_borrow.rs b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/userdata_borrow.rs new file mode 100644 index 0000000..26eb3c7 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/userdata_borrow.rs @@ -0,0 +1,19 @@ +use mlua::{AnyUserData, Lua, Table, UserData, Result}; + +fn main() -> Result<()> { + let lua = Lua::new(); + let globals = lua.globals(); + + // Should not allow userdata borrow to outlive lifetime of AnyUserData handle + struct MyUserData; + impl UserData for MyUserData {}; + let _userdata_ref; + { + let touter = globals.get::<_, Table>("touter")?; + touter.set("userdata", lua.create_userdata(MyUserData)?)?; + let userdata = touter.get::<_, AnyUserData>("userdata")?; + _userdata_ref = userdata.borrow::(); + //~^ error: `userdata` does not live long enough + } + Ok(()) +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/compile/userdata_borrow.stderr b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/userdata_borrow.stderr new file mode 100644 index 0000000..7ac9670 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/compile/userdata_borrow.stderr @@ -0,0 +1,13 @@ +error[E0597]: `userdata` does not live long enough + --> $DIR/userdata_borrow.rs:15:25 + | +15 | _userdata_ref = userdata.borrow::(); + | ^^^^^^^^ borrowed value does not live long enough +16 | //~^ error: `userdata` does not live long enough +17 | } + | - `userdata` dropped here while still borrowed +18 | Ok(()) +19 | } + | - borrow might be used here, when `_userdata_ref` is dropped and runs the destructor for type `std::result::Result, mlua::error::Error>` + | + = note: values in a scope are dropped in the opposite order they are defined diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/function.rs b/third_party/cargo/vendor/mlua-0.5.3/tests/function.rs new file mode 100644 index 0000000..f7ce7c0 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/function.rs @@ -0,0 +1,103 @@ +#![cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + feature(link_args) +)] + +#[cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + link_args = "-pagezero_size 10000 -image_base 100000000", + allow(unused_attributes) +)] +extern "system" {} + +use mlua::{Function, Lua, Result, String}; + +#[test] +fn test_function() -> Result<()> { + let lua = Lua::new(); + + let globals = lua.globals(); + lua.load( + r#" + function concat(arg1, arg2) + return arg1 .. arg2 + end + "#, + ) + .exec()?; + + let concat = globals.get::<_, Function>("concat")?; + assert_eq!(concat.call::<_, String>(("foo", "bar"))?, "foobar"); + + Ok(()) +} + +#[test] +fn test_bind() -> Result<()> { + let lua = Lua::new(); + + let globals = lua.globals(); + lua.load( + r#" + function concat(...) + local res = "" + for _, s in pairs({...}) do + res = res..s + end + return res + end + "#, + ) + .exec()?; + + let mut concat = globals.get::<_, Function>("concat")?; + concat = concat.bind("foo")?; + concat = concat.bind("bar")?; + concat = concat.bind(("baz", "baf"))?; + assert_eq!( + concat.call::<_, String>(("hi", "wut"))?, + "foobarbazbafhiwut" + ); + + Ok(()) +} + +#[test] +fn test_rust_function() -> Result<()> { + let lua = Lua::new(); + + let globals = lua.globals(); + lua.load( + r#" + function lua_function() + return rust_function() + end + + -- Test to make sure chunk return is ignored + return 1 + "#, + ) + .exec()?; + + let lua_function = globals.get::<_, Function>("lua_function")?; + let rust_function = lua.create_function(|_, ()| Ok("hello"))?; + + globals.set("rust_function", rust_function)?; + assert_eq!(lua_function.call::<_, String>(())?, "hello"); + + Ok(()) +} + +#[test] +fn test_dump() -> Result<()> { + let lua = unsafe { Lua::unsafe_new() }; + + let concat_lua = lua + .load(r#"function(arg1, arg2) return arg1 .. arg2 end"#) + .eval::()?; + let concat = lua.load(&concat_lua.dump(false)?).into_function()?; + + assert_eq!(concat.call::<_, String>(("foo", "bar"))?, "foobar"); + + Ok(()) +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/hooks.rs b/third_party/cargo/vendor/mlua-0.5.3/tests/hooks.rs new file mode 100644 index 0000000..a1dd3d6 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/hooks.rs @@ -0,0 +1,261 @@ +#![cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + feature(link_args) +)] + +#[cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + link_args = "-pagezero_size 10000 -image_base 100000000", + allow(unused_attributes) +)] +extern "system" {} + +use std::cell::RefCell; +use std::ops::Deref; +use std::str; +use std::sync::{Arc, Mutex}; + +use mlua::{Error, HookTriggers, Lua, Result, Value}; + +#[test] +fn line_counts() -> Result<()> { + let output = Arc::new(Mutex::new(Vec::new())); + let hook_output = output.clone(); + + let lua = Lua::new(); + lua.set_hook( + HookTriggers { + every_line: true, + ..Default::default() + }, + move |_lua, debug| { + hook_output.lock().unwrap().push(debug.curr_line()); + Ok(()) + }, + )?; + lua.load( + r#" + local x = 2 + 3 + local y = x * 63 + local z = string.len(x..", "..y) + "#, + ) + .exec()?; + + lua.remove_hook(); + + let output = output.lock().unwrap(); + if cfg!(feature = "luajit") && lua.load("jit.version_num").eval::()? >= 20100 { + assert_eq!(*output, vec![2, 3, 4, 0, 4]); + } else { + assert_eq!(*output, vec![2, 3, 4]); + } + + Ok(()) +} + +#[test] +fn function_calls() -> Result<()> { + let output = Arc::new(Mutex::new(Vec::new())); + let hook_output = output.clone(); + + let lua = Lua::new(); + lua.set_hook( + HookTriggers { + on_calls: true, + ..Default::default() + }, + move |_lua, debug| { + let names = debug.names(); + let source = debug.source(); + let name = names.name.map(|s| str::from_utf8(s).unwrap().to_owned()); + let what = source.what.map(|s| str::from_utf8(s).unwrap().to_owned()); + hook_output.lock().unwrap().push((name, what)); + Ok(()) + }, + )?; + + lua.load( + r#" + local v = string.len("Hello World") + "#, + ) + .exec()?; + + lua.remove_hook(); + + let output = output.lock().unwrap(); + if cfg!(feature = "luajit") && lua.load("jit.version_num").eval::()? >= 20100 { + assert_eq!( + *output, + vec![ + (None, Some("main".to_string())), + (Some("len".to_string()), Some("Lua".to_string())) + ] + ); + } else { + assert_eq!( + *output, + vec![ + (None, Some("main".to_string())), + (Some("len".to_string()), Some("C".to_string())) + ] + ); + } + + Ok(()) +} + +#[test] +fn error_within_hook() -> Result<()> { + let lua = Lua::new(); + lua.set_hook( + HookTriggers { + every_line: true, + ..Default::default() + }, + |_lua, _debug| { + Err(Error::RuntimeError( + "Something happened in there!".to_string(), + )) + }, + )?; + + let err = lua + .load("x = 1") + .exec() + .expect_err("panic didn't propagate"); + + match err { + Error::CallbackError { cause, .. } => match cause.deref() { + Error::RuntimeError(s) => assert_eq!(s, "Something happened in there!"), + _ => panic!("wrong callback error kind caught"), + }, + _ => panic!("wrong error kind caught"), + }; + + Ok(()) +} + +#[test] +fn limit_execution_instructions() -> Result<()> { + let lua = Lua::new(); + let mut max_instructions = 10000; + + #[cfg(feature = "luajit")] + // For LuaJIT disable JIT, as compiled code does not trigger hooks + lua.load("jit.off()").exec()?; + + lua.set_hook( + HookTriggers { + every_nth_instruction: Some(30), + ..Default::default() + }, + move |_lua, _debug| { + max_instructions -= 30; + if max_instructions < 0 { + Err(Error::RuntimeError("time's up".to_string())) + } else { + Ok(()) + } + }, + )?; + + lua.globals().set("x", Value::Integer(0))?; + let _ = lua + .load( + r#" + for i = 1, 10000 do + x = x + 1 + end + "#, + ) + .exec() + .expect_err("instruction limit didn't occur"); + + Ok(()) +} + +#[test] +fn hook_removal() -> Result<()> { + let lua = Lua::new(); + + lua.set_hook( + HookTriggers { + every_nth_instruction: Some(1), + ..Default::default() + }, + |_lua, _debug| { + Err(Error::RuntimeError( + "this hook should've been removed by this time".to_string(), + )) + }, + )?; + + assert!(lua.load("local x = 1").exec().is_err()); + lua.remove_hook(); + assert!(lua.load("local x = 1").exec().is_ok()); + + Ok(()) +} + +#[test] +fn hook_swap_within_hook() -> Result<()> { + thread_local! { + static TL_LUA: RefCell> = RefCell::new(None); + } + + TL_LUA.with(|tl| { + *tl.borrow_mut() = Some(Lua::new()); + }); + + TL_LUA.with(|tl| { + tl.borrow().as_ref().unwrap().set_hook( + HookTriggers { + every_line: true, + ..Default::default() + }, + move |lua, _debug| { + lua.globals().set("ok", 1i64)?; + TL_LUA.with(|tl| { + tl.borrow().as_ref().unwrap().set_hook( + HookTriggers { + every_line: true, + ..Default::default() + }, + move |lua, _debug| { + lua.load( + r#" + if ok ~= nil then + ok = ok + 1 + end + "#, + ) + .exec() + .expect("exec failure within hook"); + TL_LUA.with(|tl| { + tl.borrow().as_ref().unwrap().remove_hook(); + }); + Ok(()) + }, + ) + }) + }, + ) + })?; + + TL_LUA.with(|tl| { + let tl = tl.borrow(); + let lua = tl.as_ref().unwrap(); + lua.load( + r#" + local x = 1 + x = 2 + local y = 3 + "#, + ) + .exec()?; + assert_eq!(lua.globals().get::<_, i64>("ok")?, 2); + Ok(()) + }) +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/memory.rs b/third_party/cargo/vendor/mlua-0.5.3/tests/memory.rs new file mode 100644 index 0000000..b51ca3d --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/memory.rs @@ -0,0 +1,103 @@ +#![cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + feature(link_args) +)] + +#[cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + link_args = "-pagezero_size 10000 -image_base 100000000", + allow(unused_attributes) +)] +extern "system" {} + +use std::sync::Arc; + +use mlua::{Lua, Result, UserData}; + +#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] +use mlua::Error; + +#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] +#[test] +fn test_memory_limit() -> Result<()> { + let lua = Lua::new(); + + let initial_memory = lua.used_memory(); + assert!( + initial_memory > 0, + "used_memory reporting is wrong, lua uses memory for stdlib" + ); + + let f = lua + .load("local t = {}; for i = 1,10000 do t[i] = i end") + .into_function()?; + f.call::<_, ()>(()).expect("should trigger no memory limit"); + + lua.set_memory_limit(initial_memory + 10000)?; + match f.call::<_, ()>(()) { + Err(Error::MemoryError(_)) => {} + something_else => panic!("did not trigger memory error: {:?}", something_else), + }; + + lua.set_memory_limit(0)?; + f.call::<_, ()>(()).expect("should trigger no memory limit"); + + Ok(()) +} + +#[test] +fn test_gc_control() -> Result<()> { + let lua = Lua::new(); + let globals = lua.globals(); + + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + { + assert!(lua.gc_is_running()); + lua.gc_stop(); + assert!(!lua.gc_is_running()); + lua.gc_restart(); + assert!(lua.gc_is_running()); + } + + struct MyUserdata(Arc<()>); + impl UserData for MyUserdata {} + + let rc = Arc::new(()); + globals.set("userdata", lua.create_userdata(MyUserdata(rc.clone()))?)?; + globals.raw_remove("userdata")?; + + assert_eq!(Arc::strong_count(&rc), 2); + lua.gc_collect()?; + lua.gc_collect()?; + assert_eq!(Arc::strong_count(&rc), 1); + + Ok(()) +} + +#[cfg(any(feature = "lua53", feature = "lua52"))] +#[test] +fn test_gc_error() { + use mlua::Error; + + let lua = Lua::new(); + match lua + .load( + r#" + val = nil + table = {} + setmetatable(table, { + __gc = function() + error("gcwascalled") + end + }) + table = nil + collectgarbage("collect") + "#, + ) + .exec() + { + Err(Error::GarbageCollectorError(_)) => {} + Err(e) => panic!("__gc error did not result in correct error, instead: {}", e), + Ok(()) => panic!("__gc error did not result in error"), + } +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/scope.rs b/third_party/cargo/vendor/mlua-0.5.3/tests/scope.rs new file mode 100644 index 0000000..f7dc32d --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/scope.rs @@ -0,0 +1,240 @@ +#![cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + feature(link_args) +)] + +#[cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + link_args = "-pagezero_size 10000 -image_base 100000000", + allow(unused_attributes) +)] +extern "system" {} + +use std::cell::Cell; +use std::rc::Rc; + +use mlua::{Error, Function, Lua, MetaMethod, Result, String, UserData, UserDataMethods}; + +#[test] +fn scope_func() -> Result<()> { + let lua = Lua::new(); + + let rc = Rc::new(Cell::new(0)); + lua.scope(|scope| { + let r = rc.clone(); + let f = scope.create_function(move |_, ()| { + r.set(42); + Ok(()) + })?; + lua.globals().set("bad", f.clone())?; + f.call::<_, ()>(())?; + assert_eq!(Rc::strong_count(&rc), 2); + Ok(()) + })?; + assert_eq!(rc.get(), 42); + assert_eq!(Rc::strong_count(&rc), 1); + + match lua.globals().get::<_, Function>("bad")?.call::<_, ()>(()) { + Err(Error::CallbackError { .. }) => {} + r => panic!("improper return for destructed function: {:?}", r), + }; + + Ok(()) +} + +#[test] +fn scope_drop() -> Result<()> { + let lua = Lua::new(); + + struct MyUserdata(Rc<()>); + impl UserData for MyUserdata { + fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_method("method", |_, _, ()| Ok(())); + } + } + + let rc = Rc::new(()); + + lua.scope(|scope| { + lua.globals() + .set("test", scope.create_userdata(MyUserdata(rc.clone()))?)?; + assert_eq!(Rc::strong_count(&rc), 2); + Ok(()) + })?; + assert_eq!(Rc::strong_count(&rc), 1); + + match lua.load("test:method()").exec() { + Err(Error::CallbackError { .. }) => {} + r => panic!("improper return for destructed userdata: {:?}", r), + }; + + Ok(()) +} + +#[test] +fn scope_capture() -> Result<()> { + let lua = Lua::new(); + + let mut i = 0; + lua.scope(|scope| { + scope + .create_function_mut(|_, ()| { + i = 42; + Ok(()) + })? + .call::<_, ()>(()) + })?; + assert_eq!(i, 42); + + Ok(()) +} + +#[test] +fn outer_lua_access() -> Result<()> { + let lua = Lua::new(); + + let table = lua.create_table()?; + lua.scope(|scope| { + scope + .create_function_mut(|_, ()| table.set("a", "b"))? + .call::<_, ()>(()) + })?; + assert_eq!(table.get::<_, String>("a")?, "b"); + + Ok(()) +} + +#[test] +fn scope_userdata_methods() -> Result<()> { + struct MyUserData<'a>(&'a Cell); + + impl<'a> UserData for MyUserData<'a> { + fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_method("inc", |_, data, ()| { + data.0.set(data.0.get() + 1); + Ok(()) + }); + + methods.add_method("dec", |_, data, ()| { + data.0.set(data.0.get() - 1); + Ok(()) + }); + } + } + + let lua = Lua::new(); + + let i = Cell::new(42); + let f: Function = lua + .load( + r#" + function(u) + u:inc() + u:inc() + u:inc() + u:dec() + end + "#, + ) + .eval()?; + + lua.scope(|scope| f.call::<_, ()>(scope.create_nonstatic_userdata(MyUserData(&i))?))?; + + assert_eq!(i.get(), 44); + + Ok(()) +} + +#[test] +fn scope_userdata_functions() -> Result<()> { + struct MyUserData<'a>(&'a i64); + + impl<'a> UserData for MyUserData<'a> { + fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_meta_function(MetaMethod::Add, |lua, ()| { + let globals = lua.globals(); + globals.set("i", globals.get::<_, i64>("i")? + 1)?; + Ok(()) + }); + methods.add_meta_function(MetaMethod::Sub, |lua, ()| { + let globals = lua.globals(); + globals.set("i", globals.get::<_, i64>("i")? + 1)?; + Ok(()) + }); + } + } + + let lua = Lua::new(); + + let dummy = 0; + let f = lua + .load( + r#" + i = 0 + return function(u) + _ = u + u + _ = u - 1 + _ = 1 + u + end + "#, + ) + .eval::()?; + + lua.scope(|scope| f.call::<_, ()>(scope.create_nonstatic_userdata(MyUserData(&dummy))?))?; + + assert_eq!(lua.globals().get::<_, i64>("i")?, 3); + + Ok(()) +} + +#[test] +fn scope_userdata_mismatch() -> Result<()> { + struct MyUserData<'a>(&'a Cell); + + impl<'a> UserData for MyUserData<'a> { + fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_method("inc", |_, data, ()| { + data.0.set(data.0.get() + 1); + Ok(()) + }); + } + } + + let lua = Lua::new(); + + lua.load( + r#" + function okay(a, b) + a.inc(a) + b.inc(b) + end + function bad(a, b) + a.inc(b) + end + "#, + ) + .exec()?; + + let a = Cell::new(1); + let b = Cell::new(1); + + let okay: Function = lua.globals().get("okay")?; + let bad: Function = lua.globals().get("bad")?; + + lua.scope(|scope| { + let au = scope.create_nonstatic_userdata(MyUserData(&a))?; + let bu = scope.create_nonstatic_userdata(MyUserData(&b))?; + assert!(okay.call::<_, ()>((au.clone(), bu.clone())).is_ok()); + match bad.call::<_, ()>((au, bu)) { + Err(Error::CallbackError { ref cause, .. }) => match *cause.as_ref() { + Error::UserDataTypeMismatch => {} + ref other => panic!("wrong error type {:?}", other), + }, + Err(other) => panic!("wrong error type {:?}", other), + Ok(_) => panic!("incorrectly returned Ok"), + } + Ok(()) + })?; + + Ok(()) +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/serde.rs b/third_party/cargo/vendor/mlua-0.5.3/tests/serde.rs new file mode 100644 index 0000000..13d6b1e --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/serde.rs @@ -0,0 +1,341 @@ +#![cfg(feature = "serialize")] +#![cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + feature(link_args) +)] + +#[cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + link_args = "-pagezero_size 10000 -image_base 100000000", + allow(unused_attributes) +)] +extern "system" {} + +use mlua::{Error, Lua, LuaSerdeExt, Result as LuaResult, UserData, Value}; +use serde::{Deserialize, Serialize}; + +#[test] +fn test_serialize() -> Result<(), Box> { + #[derive(Serialize)] + struct MyUserData(i64, String); + + impl UserData for MyUserData {} + + let lua = Lua::new(); + let globals = lua.globals(); + + let ud = lua.create_ser_userdata(MyUserData(123, "test userdata".into()))?; + globals.set("ud", ud)?; + globals.set("null", lua.null()?)?; + + let empty_array = lua.create_table()?; + empty_array.set_metatable(Some(lua.array_metatable()?)); + globals.set("empty_array", empty_array)?; + + let val = lua + .load( + r#" + { + _bool = true, + _integer = 123, + _number = 321.99, + _string = "test string serialization", + _table_arr = {nil, "value 1", nil, "value 2", {}}, + _table_map = {["table"] = "map", ["null"] = null}, + _bytes = "\240\040\140\040", + _userdata = ud, + _null = null, + _empty_map = {}, + _empty_array = empty_array, + } + "#, + ) + .eval::()?; + + let json = serde_json::json!({ + "_bool": true, + "_integer": 123, + "_number": 321.99, + "_string": "test string serialization", + "_table_arr": [null, "value 1", null, "value 2", {}], + "_table_map": {"table": "map", "null": null}, + "_bytes": [240, 40, 140, 40], + "_userdata": [123, "test userdata"], + "_null": null, + "_empty_map": {}, + "_empty_array": [], + }); + + assert_eq!(serde_json::to_value(&val)?, json); + + // Test to-from loop + let val = lua.to_value(&json)?; + let expected_json = lua.from_value::(val)?; + assert_eq!(expected_json, json); + + Ok(()) +} + +#[test] +fn test_serialize_in_scope() -> LuaResult<()> { + #[derive(Serialize, Clone)] + struct MyUserData(i64, String); + + impl UserData for MyUserData {} + + let lua = Lua::new(); + lua.scope(|scope| { + let ud = scope.create_ser_userdata(MyUserData(-5, "test userdata".into()))?; + assert_eq!( + serde_json::to_value(&ud).unwrap(), + serde_json::json!((-5, "test userdata")) + ); + Ok(()) + })?; + + lua.scope(|scope| { + let ud = scope.create_ser_userdata(MyUserData(-5, "test userdata".into()))?; + lua.globals().set("ud", ud) + })?; + let val = lua.load("ud").eval::()?; + match serde_json::to_value(&val) { + Ok(v) => panic!("expected destructed error, got {}", v), + Err(e) if e.to_string().contains("destructed") => {} + Err(e) => panic!("expected destructed error, got {}", e), + } + + Ok(()) +} + +#[test] +fn test_serialize_failure() -> Result<(), Box> { + #[derive(Serialize)] + struct MyUserData(i64); + + impl UserData for MyUserData {} + + let lua = Lua::new(); + + let ud = Value::UserData(lua.create_userdata(MyUserData(123))?); + match serde_json::to_value(&ud) { + Ok(v) => panic!("expected serialization error, got {}", v), + Err(serde_json::Error { .. }) => {} + } + + let func = lua.create_function(|_, _: ()| Ok(()))?; + match serde_json::to_value(&Value::Function(func.clone())) { + Ok(v) => panic!("expected serialization error, got {}", v), + Err(serde_json::Error { .. }) => {} + } + + let thr = lua.create_thread(func)?; + match serde_json::to_value(&Value::Thread(thr)) { + Ok(v) => panic!("expected serialization error, got {}", v), + Err(serde_json::Error { .. }) => {} + } + + Ok(()) +} + +#[test] +fn test_to_value_struct() -> LuaResult<()> { + let lua = Lua::new(); + let globals = lua.globals(); + globals.set("null", lua.null()?)?; + + #[derive(Serialize)] + struct Test { + name: String, + key: i64, + data: Option, + } + + let test = Test { + name: "alex".to_string(), + key: -16, + data: None, + }; + + globals.set("value", lua.to_value(&test)?)?; + lua.load( + r#" + assert(value["name"] == "alex") + assert(value["key"] == -16) + assert(value["data"] == null) + "#, + ) + .exec() +} + +#[test] +fn test_to_value_enum() -> LuaResult<()> { + let lua = Lua::new(); + let globals = lua.globals(); + globals.set("null", lua.null()?)?; + + #[derive(Serialize)] + struct Test { + name: String, + key: i64, + data: Option, + } + + let test = Test { + name: "alex".to_string(), + key: -16, + data: None, + }; + + globals.set("value", lua.to_value(&test)?)?; + lua.load( + r#" + assert(value["name"] == "alex") + assert(value["key"] == -16) + assert(value["data"] == null) + "#, + ) + .exec()?; + + #[derive(Serialize)] + enum E { + Unit, + Integer(u32), + Tuple(u32, u32), + Struct { a: u32 }, + } + + let u = E::Unit; + globals.set("value", lua.to_value(&u)?)?; + lua.load(r#"assert(value == "Unit")"#).exec()?; + + let n = E::Integer(1); + globals.set("value", lua.to_value(&n)?)?; + lua.load(r#"assert(value["Integer"] == 1)"#).exec()?; + + let t = E::Tuple(1, 2); + globals.set("value", lua.to_value(&t)?)?; + lua.load( + r#" + assert(value["Tuple"][1] == 1) + assert(value["Tuple"][2] == 2) + "#, + ) + .exec()?; + + let s = E::Struct { a: 1 }; + globals.set("value", lua.to_value(&s)?)?; + lua.load(r#"assert(value["Struct"]["a"] == 1)"#).exec()?; + Ok(()) +} + +#[test] +fn test_from_value_struct() -> Result<(), Box> { + let lua = Lua::new(); + + #[derive(Deserialize, PartialEq, Debug)] + struct Test { + int: u32, + seq: Vec, + map: std::collections::HashMap, + empty: Vec<()>, + tuple: (u8, u8, u8), + } + + let value = lua + .load( + r#" + { + int = 1, + seq = {"a", "b"}, + map = {2, [4] = 1}, + empty = {}, + tuple = {10, 20, 30}, + } + "#, + ) + .eval::()?; + let got = lua.from_value(value)?; + assert_eq!( + Test { + int: 1, + seq: vec!["a".into(), "b".into()], + map: vec![(1, 2), (4, 1)].into_iter().collect(), + empty: vec![], + tuple: (10, 20, 30), + }, + got + ); + + Ok(()) +} + +#[test] +fn test_from_value_enum() -> Result<(), Box> { + let lua = Lua::new(); + + #[derive(Deserialize, PartialEq, Debug)] + enum E { + Unit, + Integer(u32), + Tuple(u32, u32), + Struct { a: u32 }, + } + + let value = lua.load(r#""Unit""#).eval()?; + let got = lua.from_value(value)?; + assert_eq!(E::Unit, got); + + let value = lua.load(r#"{Integer = 1}"#).eval()?; + let got = lua.from_value(value)?; + assert_eq!(E::Integer(1), got); + + let value = lua.load(r#"{Tuple = {1, 2}}"#).eval()?; + let got = lua.from_value(value)?; + assert_eq!(E::Tuple(1, 2), got); + + let value = lua.load(r#"{Struct = {a = 3}}"#).eval()?; + let got = lua.from_value(value)?; + assert_eq!(E::Struct { a: 3 }, got); + + Ok(()) +} + +#[test] +fn test_from_value_enum_untagged() -> Result<(), Box> { + let lua = Lua::new(); + lua.globals().set("null", lua.null()?)?; + + #[derive(Deserialize, PartialEq, Debug)] + #[serde(untagged)] + enum Eut { + Unit, + Integer(u64), + Tuple(u32, u32), + Struct { a: u32 }, + } + + let value = lua.load(r#"null"#).eval()?; + let got = lua.from_value(value)?; + assert_eq!(Eut::Unit, got); + + let value = lua.load(r#"1"#).eval()?; + let got = lua.from_value(value)?; + assert_eq!(Eut::Integer(1), got); + + let value = lua.load(r#"{3, 1}"#).eval()?; + let got = lua.from_value(value)?; + assert_eq!(Eut::Tuple(3, 1), got); + + let value = lua.load(r#"{a = 10}"#).eval()?; + let got = lua.from_value(value)?; + assert_eq!(Eut::Struct { a: 10 }, got); + + let value = lua.load(r#"{b = 12}"#).eval()?; + match lua.from_value::(value) { + Ok(v) => panic!("expected Error::DeserializeError, got {:?}", v), + Err(Error::DeserializeError(_)) => {} + Err(e) => panic!("expected Error::DeserializeError, got {}", e), + } + + Ok(()) +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/string.rs b/third_party/cargo/vendor/mlua-0.5.3/tests/string.rs new file mode 100644 index 0000000..f7e551e --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/string.rs @@ -0,0 +1,77 @@ +#![cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + feature(link_args) +)] + +#[cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + link_args = "-pagezero_size 10000 -image_base 100000000", + allow(unused_attributes) +)] +extern "system" {} + +use std::borrow::Cow; + +use mlua::{Lua, Result, String}; + +#[test] +fn compare() { + fn with_str(s: &str, f: F) { + f(Lua::new().create_string(s).unwrap()); + } + + // Tests that all comparisons we want to have are usable + with_str("teststring", |t| assert_eq!(t, "teststring")); // &str + with_str("teststring", |t| assert_eq!(t, b"teststring")); // &[u8] + with_str("teststring", |t| assert_eq!(t, b"teststring".to_vec())); // Vec + with_str("teststring", |t| assert_eq!(t, "teststring".to_string())); // String + with_str("teststring", |t| assert_eq!(t, t)); // mlua::String + with_str("teststring", |t| { + assert_eq!(t, Cow::from(b"teststring".as_ref())) + }); // Cow (borrowed) + with_str("bla", |t| assert_eq!(t, Cow::from(b"bla".to_vec()))); // Cow (owned) +} + +#[test] +fn string_views() -> Result<()> { + let lua = Lua::new(); + + lua.load( + r#" + ok = "null bytes are valid utf-8, wh\0 knew?" + err = "but \255 isn't :(" + empty = "" + "#, + ) + .exec()?; + + let globals = lua.globals(); + let ok: String = globals.get("ok")?; + let err: String = globals.get("err")?; + let empty: String = globals.get("empty")?; + + assert_eq!(ok.to_str()?, "null bytes are valid utf-8, wh\0 knew?"); + assert_eq!( + ok.as_bytes(), + &b"null bytes are valid utf-8, wh\0 knew?"[..] + ); + + assert!(err.to_str().is_err()); + assert_eq!(err.as_bytes(), &b"but \xff isn't :("[..]); + + assert_eq!(empty.to_str()?, ""); + assert_eq!(empty.as_bytes_with_nul(), &[0]); + assert_eq!(empty.as_bytes(), &[]); + + Ok(()) +} + +#[test] +fn raw_string() -> Result<()> { + let lua = Lua::new(); + + let rs = lua.create_string(&[0, 1, 2, 3, 0, 1, 2, 3])?; + assert_eq!(rs.as_bytes(), &[0, 1, 2, 3, 0, 1, 2, 3]); + + Ok(()) +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/table.rs b/third_party/cargo/vendor/mlua-0.5.3/tests/table.rs new file mode 100644 index 0000000..2417619 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/table.rs @@ -0,0 +1,311 @@ +#![cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + feature(link_args) +)] + +#[cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + link_args = "-pagezero_size 10000 -image_base 100000000", + allow(unused_attributes) +)] +extern "system" {} + +use mlua::{Lua, Nil, Result, Table, TableExt, Value}; + +#[test] +fn test_set_get() -> Result<()> { + let lua = Lua::new(); + + let globals = lua.globals(); + globals.set("foo", "bar")?; + globals.set("baz", "baf")?; + assert_eq!(globals.get::<_, String>("foo")?, "bar"); + assert_eq!(globals.get::<_, String>("baz")?, "baf"); + + Ok(()) +} + +#[test] +fn test_table() -> Result<()> { + let lua = Lua::new(); + + let globals = lua.globals(); + + globals.set("table", lua.create_table()?)?; + let table1: Table = globals.get("table")?; + let table2: Table = globals.get("table")?; + + table1.set("foo", "bar")?; + table2.set("baz", "baf")?; + + assert_eq!(table2.get::<_, String>("foo")?, "bar"); + assert_eq!(table1.get::<_, String>("baz")?, "baf"); + + lua.load( + r#" + table1 = {1, 2, 3, 4, 5} + table2 = {} + table3 = {1, 2, nil, 4, 5} + "#, + ) + .exec()?; + + let table1 = globals.get::<_, Table>("table1")?; + let table2 = globals.get::<_, Table>("table2")?; + let table3 = globals.get::<_, Table>("table3")?; + + assert_eq!(table1.len()?, 5); + assert_eq!( + table1 + .clone() + .pairs() + .collect::>>()?, + vec![(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)] + ); + assert_eq!( + table1 + .clone() + .sequence_values() + .collect::>>()?, + vec![1, 2, 3, 4, 5] + ); + + assert_eq!(table2.len()?, 0); + assert_eq!( + table2 + .clone() + .pairs() + .collect::>>()?, + vec![] + ); + assert_eq!( + table2.sequence_values().collect::>>()?, + vec![] + ); + + // sequence_values should only iterate until the first border + assert_eq!( + table3.sequence_values().collect::>>()?, + vec![1, 2] + ); + + globals.set("table4", lua.create_sequence_from(vec![1, 2, 3, 4, 5])?)?; + let table4 = globals.get::<_, Table>("table4")?; + assert_eq!( + table4 + .clone() + .pairs() + .collect::>>()?, + vec![(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)] + ); + + table4.raw_insert(4, 35)?; + table4.raw_insert(7, 7)?; + assert_eq!( + table4 + .clone() + .pairs() + .collect::>>()?, + vec![(1, 1), (2, 2), (3, 3), (4, 35), (5, 4), (6, 5), (7, 7)] + ); + + table4.raw_remove(1)?; + assert_eq!( + table4 + .clone() + .pairs() + .collect::>>()?, + vec![(1, 2), (2, 3), (3, 35), (4, 4), (5, 5), (6, 7)] + ); + + Ok(()) +} + +#[test] +fn test_table_sequence_from() -> Result<()> { + let lua = Lua::new(); + + let get_table = lua.create_function(|_, t: Table| Ok(t))?; + + assert_eq!( + get_table + .call::<_, Table>(vec![1, 2, 3])? + .sequence_values() + .collect::>>()?, + vec![1, 2, 3] + ); + + assert_eq!( + get_table + .call::<_, Table>([1, 2, 3].as_ref())? + .sequence_values() + .collect::>>()?, + vec![1, 2, 3] + ); + + assert_eq!( + get_table + .call::<_, Table>([1, 2, 3])? + .sequence_values() + .collect::>>()?, + vec![1, 2, 3] + ); + + assert_eq!( + get_table + .call::<_, Table>(&[1, 2, 3])? + .sequence_values() + .collect::>>()?, + vec![1, 2, 3] + ); + + Ok(()) +} + +#[test] +fn test_table_scope() -> Result<()> { + let lua = Lua::new(); + + let globals = lua.globals(); + lua.load( + r#" + touter = { + tin = {1, 2, 3} + } + "#, + ) + .exec()?; + + // Make sure that table gets do not borrow the table, but instead just borrow lua. + let tin; + { + let touter = globals.get::<_, Table>("touter")?; + tin = touter.get::<_, Table>("tin")?; + } + + assert_eq!(tin.get::<_, i64>(1)?, 1); + assert_eq!(tin.get::<_, i64>(2)?, 2); + assert_eq!(tin.get::<_, i64>(3)?, 3); + + Ok(()) +} + +#[test] +fn test_metatable() -> Result<()> { + let lua = Lua::new(); + + let table = lua.create_table()?; + let metatable = lua.create_table()?; + metatable.set("__index", lua.create_function(|_, ()| Ok("index_value"))?)?; + table.set_metatable(Some(metatable)); + assert_eq!(table.get::<_, String>("any_key")?, "index_value"); + match table.raw_get::<_, Value>("any_key")? { + Nil => {} + _ => panic!(), + } + table.set_metatable(None); + match table.get::<_, Value>("any_key")? { + Nil => {} + _ => panic!(), + }; + + Ok(()) +} + +#[test] +fn test_table_eq() -> Result<()> { + let lua = Lua::new(); + let globals = lua.globals(); + + lua.load( + r#" + table1 = {1} + table2 = {1} + table3 = table1 + table4 = {1} + + setmetatable(table4, { + __eq = function(a, b) return a[1] == b[1] end + }) + "#, + ) + .exec()?; + + let table1 = globals.get::<_, Table>("table1")?; + let table2 = globals.get::<_, Table>("table2")?; + let table3 = globals.get::<_, Table>("table3")?; + let table4 = globals.get::<_, Table>("table4")?; + + assert!(table1 != table2); + assert!(!table1.equals(&table2)?); + assert!(table1 == table3); + assert!(table1.equals(&table3)?); + assert!(table1 != table4); + assert!(table1.equals(&table4)?); + + Ok(()) +} + +#[test] +fn test_table_error() -> Result<()> { + let lua = Lua::new(); + + let globals = lua.globals(); + lua.load( + r#" + table = {} + setmetatable(table, { + __index = function() + error("lua error") + end, + __newindex = function() + error("lua error") + end, + __len = function() + error("lua error") + end + }) + "#, + ) + .exec()?; + + let bad_table: Table = globals.get("table")?; + assert!(bad_table.set(1, 1).is_err()); + assert!(bad_table.get::<_, i32>(1).is_err()); + assert!(bad_table.len().is_err()); + assert!(bad_table.raw_set(1, 1).is_ok()); + assert!(bad_table.raw_get::<_, i32>(1).is_ok()); + assert_eq!(bad_table.raw_len(), 1); + + Ok(()) +} + +#[test] +fn test_table_call() -> Result<()> { + let lua = Lua::new(); + + lua.load( + r#" + table = {a = 1} + + function table.func(key) + return "func_"..key + end + + function table:method(key) + return "method_"..self[key] + end + "#, + ) + .exec()?; + + let table: Table = lua.globals().get("table")?; + + assert_eq!(table.call_function::<_, _, String>("func", "a")?, "func_a"); + assert_eq!( + table.call_method::<_, _, String>("method", "a")?, + "method_1" + ); + + Ok(()) +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/tests.rs b/third_party/cargo/vendor/mlua-0.5.3/tests/tests.rs new file mode 100644 index 0000000..813ea1d --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/tests.rs @@ -0,0 +1,967 @@ +#![cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + feature(link_args) +)] + +#[cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + link_args = "-pagezero_size 10000 -image_base 100000000", + allow(unused_attributes) +)] +extern "system" {} + +use std::iter::FromIterator; +use std::panic::catch_unwind; +use std::sync::Arc; +use std::{error, f32, f64, fmt}; + +use mlua::{ + ChunkMode, Error, ExternalError, Function, Lua, Nil, Result, StdLib, String, Table, UserData, + Value, Variadic, +}; + +#[test] +fn test_safety() -> Result<()> { + let lua = Lua::new(); + assert!(lua.load(r#"require "debug""#).exec().is_err()); + match lua.load_from_std_lib(StdLib::DEBUG) { + Err(Error::SafetyError(_)) => {} + Err(e) => panic!("expected SafetyError, got {:?}", e), + Ok(_) => panic!("expected SafetyError, got no error"), + } + drop(lua); + + let lua = unsafe { Lua::unsafe_new() }; + assert!(lua.load(r#"require "debug""#).exec().is_ok()); + drop(lua); + + match Lua::new_with(StdLib::DEBUG) { + Err(Error::SafetyError(_)) => {} + Err(e) => panic!("expected SafetyError, got {:?}", e), + Ok(_) => panic!("expected SafetyError, got new Lua state"), + } + + let lua = Lua::new(); + match lua.load(r#"package.loadlib()"#).exec() { + Err(Error::CallbackError { ref cause, .. }) => match cause.as_ref() { + Error::SafetyError(_) => {} + e => panic!("expected SafetyError cause, got {:?}", e), + }, + Err(e) => panic!("expected CallbackError, got {:?}", e), + Ok(_) => panic!("expected CallbackError, got no error"), + }; + match lua.load(r#"require "fake_ffi""#).exec() { + Err(Error::RuntimeError(msg)) => assert!(msg.contains("can't load C modules in safe mode")), + Err(e) => panic!("expected RuntimeError, got {:?}", e), + Ok(_) => panic!("expected RuntimeError, got no error"), + } + + match lua.load("1 + 1").set_mode(ChunkMode::Binary).exec() { + Err(Error::SafetyError(msg)) => { + assert!(msg.contains("binary chunks are disabled in safe mode")) + } + Err(e) => panic!("expected SafetyError, got {:?}", e), + Ok(_) => panic!("expected SafetyError, got no error"), + } + + let bytecode = lua.load("return 1 + 1").into_function()?.dump(true)?; + match lua.load(&bytecode).exec() { + Err(Error::SafetyError(msg)) => { + assert!(msg.contains("binary chunks are disabled in safe mode")) + } + Err(e) => panic!("expected SafetyError, got {:?}", e), + Ok(_) => panic!("expected SafetyError, got no error"), + } + drop(lua); + + // Test safety rules after dynamically loading `package` library + let lua = Lua::new_with(StdLib::NONE)?; + assert!(lua.globals().get::<_, Option>("require")?.is_none()); + lua.load_from_std_lib(StdLib::PACKAGE)?; + match lua.load(r#"package.loadlib()"#).exec() { + Err(Error::CallbackError { ref cause, .. }) => match cause.as_ref() { + Error::SafetyError(_) => {} + e => panic!("expected SafetyError cause, got {:?}", e), + }, + Err(e) => panic!("expected CallbackError, got {:?}", e), + Ok(_) => panic!("expected CallbackError, got no error"), + }; + + Ok(()) +} + +#[test] +fn test_load() -> Result<()> { + let lua = Lua::new(); + let func = lua.load("return 1+2").into_function()?; + let result: i32 = func.call(())?; + assert_eq!(result, 3); + + assert!(lua.load("§$%§&$%&").exec().is_err()); + + Ok(()) +} + +#[test] +fn test_exec() -> Result<()> { + let lua = Lua::new(); + + let globals = lua.globals(); + lua.load( + r#" + res = 'foo'..'bar' + "#, + ) + .exec()?; + assert_eq!(globals.get::<_, String>("res")?, "foobar"); + + let module: Table = lua + .load( + r#" + local module = {} + + function module.func() + return "hello" + end + + return module + "#, + ) + .eval()?; + assert!(module.contains_key("func")?); + assert_eq!( + module.get::<_, Function>("func")?.call::<_, String>(())?, + "hello" + ); + + Ok(()) +} + +#[test] +fn test_eval() -> Result<()> { + let lua = Lua::new(); + + assert_eq!(lua.load("1 + 1").eval::()?, 2); + assert_eq!(lua.load("false == false").eval::()?, true); + assert_eq!(lua.load("return 1 + 2").eval::()?, 3); + match lua.load("if true then").eval::<()>() { + Err(Error::SyntaxError { + incomplete_input: true, + .. + }) => {} + r => panic!( + "expected SyntaxError with incomplete_input=true, got {:?}", + r + ), + } + + Ok(()) +} + +#[test] +fn test_load_mode() -> Result<()> { + let lua = unsafe { Lua::unsafe_new() }; + + assert_eq!( + lua.load("1 + 1").set_mode(ChunkMode::Text).eval::()?, + 2 + ); + match lua.load("1 + 1").set_mode(ChunkMode::Binary).exec() { + Ok(_) => panic!("expected SyntaxError, got no error"), + Err(Error::SyntaxError { message: msg, .. }) => { + assert!(msg.contains("attempt to load a text chunk")) + } + Err(e) => panic!("expected SyntaxError, got {:?}", e), + }; + + let bytecode = lua.load("return 1 + 1").into_function()?.dump(true)?; + assert_eq!(lua.load(&bytecode).eval::()?, 2); + assert_eq!( + lua.load(&bytecode) + .set_mode(ChunkMode::Binary) + .eval::()?, + 2 + ); + match lua.load(&bytecode).set_mode(ChunkMode::Text).exec() { + Ok(_) => panic!("expected SyntaxError, got no error"), + Err(Error::SyntaxError { message: msg, .. }) => { + assert!(msg.contains("attempt to load a binary chunk")) + } + Err(e) => panic!("expected SyntaxError, got {:?}", e), + }; + + Ok(()) +} + +#[test] +fn test_lua_multi() -> Result<()> { + let lua = Lua::new(); + + lua.load( + r#" + function concat(arg1, arg2) + return arg1 .. arg2 + end + + function mreturn() + return 1, 2, 3, 4, 5, 6 + end + "#, + ) + .exec()?; + + let globals = lua.globals(); + let concat = globals.get::<_, Function>("concat")?; + let mreturn = globals.get::<_, Function>("mreturn")?; + + assert_eq!(concat.call::<_, String>(("foo", "bar"))?, "foobar"); + let (a, b) = mreturn.call::<_, (u64, u64)>(())?; + assert_eq!((a, b), (1, 2)); + let (a, b, v) = mreturn.call::<_, (u64, u64, Variadic)>(())?; + assert_eq!((a, b), (1, 2)); + assert_eq!(v[..], [3, 4, 5, 6]); + + Ok(()) +} + +#[test] +fn test_coercion() -> Result<()> { + let lua = Lua::new(); + + lua.load( + r#" + int = 123 + str = "123" + num = 123.0 + "#, + ) + .exec()?; + + let globals = lua.globals(); + assert_eq!(globals.get::<_, String>("int")?, "123"); + assert_eq!(globals.get::<_, i32>("str")?, 123); + assert_eq!(globals.get::<_, i32>("num")?, 123); + + Ok(()) +} + +#[test] +fn test_error() -> Result<()> { + #[derive(Debug)] + pub struct TestError; + + impl fmt::Display for TestError { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "test error") + } + } + + impl error::Error for TestError { + fn description(&self) -> &str { + "test error" + } + + fn cause(&self) -> Option<&dyn error::Error> { + None + } + } + + let lua = Lua::new(); + + let globals = lua.globals(); + lua.load( + r#" + function no_error() + end + + function lua_error() + error("this is a lua error") + end + + function rust_error() + rust_error_function() + end + + function return_error() + local status, res = pcall(rust_error_function) + assert(not status) + return res + end + + function return_string_error() + return "this should be converted to an error" + end + + function test_pcall() + local testvar = 0 + + pcall(function(arg) + testvar = testvar + arg + error("should be ignored") + end, 3) + + local function handler(err) + if string.match(_VERSION, ' 5%.1$') or string.match(_VERSION, ' 5%.2$') then + -- Special case for Lua 5.1/5.2 + local caps = string.match(err, ': (%d+)$') + if caps then + err = caps + end + end + testvar = testvar + err + return "should be ignored" + end + + local status, res = xpcall(function() + error(5) + end, handler) + assert(not status) + + if testvar ~= 8 then + error("testvar had the wrong value, pcall / xpcall misbehaving "..testvar) + end + end + + function understand_recursion() + understand_recursion() + end + "#, + ) + .exec()?; + + let rust_error_function = + lua.create_function(|_, ()| -> Result<()> { Err(TestError.to_lua_err()) })?; + globals.set("rust_error_function", rust_error_function)?; + + let no_error = globals.get::<_, Function>("no_error")?; + let lua_error = globals.get::<_, Function>("lua_error")?; + let rust_error = globals.get::<_, Function>("rust_error")?; + let return_error = globals.get::<_, Function>("return_error")?; + let return_string_error = globals.get::<_, Function>("return_string_error")?; + let test_pcall = globals.get::<_, Function>("test_pcall")?; + let understand_recursion = globals.get::<_, Function>("understand_recursion")?; + + assert!(no_error.call::<_, ()>(()).is_ok()); + match lua_error.call::<_, ()>(()) { + Err(Error::RuntimeError(_)) => {} + Err(e) => panic!("error is not RuntimeError kind, got {:?}", e), + _ => panic!("error not returned"), + } + match rust_error.call::<_, ()>(()) { + Err(Error::CallbackError { .. }) => {} + Err(e) => panic!("error is not CallbackError kind, got {:?}", e), + _ => panic!("error not returned"), + } + + match return_error.call::<_, Value>(()) { + Ok(Value::Error(_)) => {} + _ => panic!("Value::Error not returned"), + } + + assert!(return_string_error.call::<_, Error>(()).is_ok()); + + match lua + .load("if youre happy and you know it syntax error") + .exec() + { + Err(Error::SyntaxError { + incomplete_input: false, + .. + }) => {} + Err(_) => panic!("error is not LuaSyntaxError::Syntax kind"), + _ => panic!("error not returned"), + } + match lua.load("function i_will_finish_what_i()").exec() { + Err(Error::SyntaxError { + incomplete_input: true, + .. + }) => {} + Err(_) => panic!("error is not LuaSyntaxError::IncompleteStatement kind"), + _ => panic!("error not returned"), + } + + test_pcall.call::<_, ()>(())?; + + assert!(understand_recursion.call::<_, ()>(()).is_err()); + + match catch_unwind(|| -> Result<()> { + let lua = Lua::new(); + let globals = lua.globals(); + + lua.load( + r#" + function rust_panic() + local _, err = pcall(function () rust_panic_function() end) + if err ~= nil then + error(err) + end + end + "#, + ) + .exec()?; + let rust_panic_function = + lua.create_function(|_, ()| -> Result<()> { panic!("test_panic") })?; + globals.set("rust_panic_function", rust_panic_function)?; + + let rust_panic = globals.get::<_, Function>("rust_panic")?; + + rust_panic.call::<_, ()>(()) + }) { + Ok(Ok(_)) => panic!("no panic was detected"), + Ok(Err(e)) => panic!("error during panic test {:?}", e), + Err(p) => assert!(*p.downcast::<&str>().unwrap() == "test_panic"), + }; + + match catch_unwind(|| -> Result<()> { + let lua = Lua::new(); + let globals = lua.globals(); + + lua.load( + r#" + function rust_panic() + local _, err = pcall(function () rust_panic_function() end) + if err ~= nil then + error(tostring(err)) + end + end + "#, + ) + .exec()?; + let rust_panic_function = + lua.create_function(|_, ()| -> Result<()> { panic!("test_panic") })?; + globals.set("rust_panic_function", rust_panic_function)?; + + let rust_panic = globals.get::<_, Function>("rust_panic")?; + + rust_panic.call::<_, ()>(()) + }) { + Ok(Ok(_)) => panic!("no error was detected"), + Ok(Err(Error::RuntimeError(_))) => {} + Ok(Err(e)) => panic!("unexpected error during panic test {:?}", e), + Err(_) => panic!("panic was detected"), + }; + + Ok(()) +} + +#[test] +fn test_result_conversions() -> Result<()> { + let lua = Lua::new(); + let globals = lua.globals(); + + let err = lua.create_function(|_, ()| { + Ok(Err::( + "only through failure can we succeed".to_lua_err(), + )) + })?; + let ok = lua.create_function(|_, ()| Ok(Ok::<_, Error>("!".to_owned())))?; + + globals.set("err", err)?; + globals.set("ok", ok)?; + + lua.load( + r#" + local r, e = err() + assert(r == nil) + assert(tostring(e):find("only through failure can we succeed") ~= nil) + + local r, e = ok() + assert(r == "!") + assert(e == nil) + "#, + ) + .exec()?; + + Ok(()) +} + +#[test] +fn test_num_conversion() -> Result<()> { + let lua = Lua::new(); + + assert_eq!( + lua.coerce_integer(Value::String(lua.create_string("1")?))?, + Some(1) + ); + assert_eq!( + lua.coerce_integer(Value::String(lua.create_string("1.0")?))?, + Some(1) + ); + assert_eq!( + lua.coerce_integer(Value::String(lua.create_string("1.5")?))?, + None + ); + + assert_eq!( + lua.coerce_number(Value::String(lua.create_string("1")?))?, + Some(1.0) + ); + assert_eq!( + lua.coerce_number(Value::String(lua.create_string("1.0")?))?, + Some(1.0) + ); + assert_eq!( + lua.coerce_number(Value::String(lua.create_string("1.5")?))?, + Some(1.5) + ); + + assert_eq!(lua.load("1.0").eval::()?, 1); + assert_eq!(lua.load("1.0").eval::()?, 1.0); + #[cfg(any(feature = "lua54", feature = "lua53"))] + assert_eq!(lua.load("1.0").eval::()?, "1.0"); + #[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))] + assert_eq!(lua.load("1.0").eval::()?, "1"); + + assert_eq!(lua.load("1.5").eval::()?, 1); + assert_eq!(lua.load("1.5").eval::()?, 1.5); + assert_eq!(lua.load("1.5").eval::()?, "1.5"); + + assert!(lua.load("-1").eval::().is_err()); + assert_eq!(lua.load("-1").eval::()?, -1); + + assert!(lua.unpack::(lua.pack(1u128 << 64)?).is_err()); + assert!(lua.load("math.huge").eval::().is_err()); + + assert_eq!(lua.unpack::(lua.pack(f32::MAX)?)?, f32::MAX as f64); + assert_eq!(lua.unpack::(lua.pack(f32::MIN)?)?, f32::MIN as f64); + assert_eq!(lua.unpack::(lua.pack(f64::MAX)?)?, f32::INFINITY); + assert_eq!(lua.unpack::(lua.pack(f64::MIN)?)?, f32::NEG_INFINITY); + + assert_eq!(lua.unpack::(lua.pack(1i128 << 64)?)?, 1i128 << 64); + + Ok(()) +} + +#[test] +fn test_pcall_xpcall() -> Result<()> { + let lua = Lua::new(); + let globals = lua.globals(); + + // make sure that we handle not enough arguments + + assert!(lua.load("pcall()").exec().is_err()); + assert!(lua.load("xpcall()").exec().is_err()); + assert!(lua.load("xpcall(function() end)").exec().is_err()); + + // Lua 5.3/5.2 / LuaJIT compatible version of xpcall + #[cfg(feature = "lua51")] + lua.load( + r#" + local xpcall_orig = xpcall + function xpcall(f, err, ...) + return xpcall_orig(function() return f(unpack(arg)) end, err) + end + "#, + ) + .exec()?; + + // Make sure that the return values from are correct on success + + let (r, e) = lua + .load("pcall(function(p) return p end, 'foo')") + .eval::<(bool, String)>()?; + assert!(r); + assert_eq!(e, "foo"); + + let (r, e) = lua + .load("xpcall(function(p) return p end, print, 'foo')") + .eval::<(bool, String)>()?; + assert!(r); + assert_eq!(e, "foo"); + + // Make sure that the return values are correct on errors, and that error handling works + + lua.load( + r#" + pcall_error = nil + pcall_status, pcall_error = pcall(error, "testerror") + + xpcall_error = nil + xpcall_status, _ = xpcall(error, function(err) xpcall_error = err end, "testerror") + "#, + ) + .exec()?; + + assert_eq!(globals.get::<_, bool>("pcall_status")?, false); + assert_eq!(globals.get::<_, String>("pcall_error")?, "testerror"); + + assert_eq!(globals.get::<_, bool>("xpcall_statusr")?, false); + #[cfg(any( + feature = "lua54", + feature = "lua53", + feature = "lua52", + feature = "luajit" + ))] + assert_eq!( + globals.get::<_, std::string::String>("xpcall_error")?, + "testerror" + ); + #[cfg(feature = "lua51")] + assert!(globals + .get::<_, String>("xpcall_error")? + .to_str()? + .ends_with(": testerror")); + + // Make sure that weird xpcall error recursion at least doesn't cause unsafety or panics. + lua.load( + r#" + function xpcall_recursion() + xpcall(error, function(err) error(err) end, "testerror") + end + "#, + ) + .exec()?; + let _ = globals + .get::<_, Function>("xpcall_recursion")? + .call::<_, ()>(()); + + Ok(()) +} + +#[test] +fn test_recursive_mut_callback_error() -> Result<()> { + let lua = Lua::new(); + + let mut v = Some(Box::new(123)); + let f = lua.create_function_mut::<_, (), _>(move |lua, mutate: bool| { + if mutate { + v = None; + } else { + // Produce a mutable reference + let r = v.as_mut().unwrap(); + // Whoops, this will recurse into the function and produce another mutable reference! + lua.globals().get::<_, Function>("f")?.call::<_, ()>(true)?; + println!("Should not get here, mutable aliasing has occurred!"); + println!("value at {:p}", r as *mut _); + println!("value is {}", r); + } + + Ok(()) + })?; + lua.globals().set("f", f)?; + match lua.globals().get::<_, Function>("f")?.call::<_, ()>(false) { + Err(Error::CallbackError { ref cause, .. }) => match *cause.as_ref() { + Error::CallbackError { ref cause, .. } => match *cause.as_ref() { + Error::RecursiveMutCallback { .. } => {} + ref other => panic!("incorrect result: {:?}", other), + }, + ref other => panic!("incorrect result: {:?}", other), + }, + other => panic!("incorrect result: {:?}", other), + }; + + Ok(()) +} + +#[test] +fn test_set_metatable_nil() -> Result<()> { + let lua = Lua::new(); + lua.load( + r#" + a = {} + setmetatable(a, nil) + "#, + ) + .exec()?; + Ok(()) +} + +#[test] +fn test_named_registry_value() -> Result<()> { + let lua = Lua::new(); + + lua.set_named_registry_value::<_, i32>("test", 42)?; + let f = lua.create_function(move |lua, ()| { + assert_eq!(lua.named_registry_value::<_, i32>("test")?, 42); + Ok(()) + })?; + + f.call::<_, ()>(())?; + + lua.unset_named_registry_value("test")?; + match lua.named_registry_value("test")? { + Nil => {} + val => panic!("registry value was not Nil, was {:?}", val), + }; + + Ok(()) +} + +#[test] +fn test_registry_value() -> Result<()> { + let lua = Lua::new(); + + let mut r = Some(lua.create_registry_value::(42)?); + let f = lua.create_function_mut(move |lua, ()| { + if let Some(r) = r.take() { + assert_eq!(lua.registry_value::(&r)?, 42); + lua.remove_registry_value(r).unwrap(); + } else { + panic!(); + } + Ok(()) + })?; + + f.call::<_, ()>(())?; + + Ok(()) +} + +#[test] +fn test_drop_registry_value() -> Result<()> { + struct MyUserdata(Arc<()>); + + impl UserData for MyUserdata {} + + let lua = Lua::new(); + let rc = Arc::new(()); + + let r = lua.create_registry_value(MyUserdata(rc.clone()))?; + assert_eq!(Arc::strong_count(&rc), 2); + + drop(r); + lua.expire_registry_values(); + + lua.load(r#"collectgarbage("collect")"#).exec()?; + + assert_eq!(Arc::strong_count(&rc), 1); + + Ok(()) +} + +#[test] +fn test_lua_registry_ownership() -> Result<()> { + let lua1 = Lua::new(); + let lua2 = Lua::new(); + + let r1 = lua1.create_registry_value("hello")?; + let r2 = lua2.create_registry_value("hello")?; + + assert!(lua1.owns_registry_value(&r1)); + assert!(!lua2.owns_registry_value(&r1)); + assert!(lua2.owns_registry_value(&r2)); + assert!(!lua1.owns_registry_value(&r2)); + + Ok(()) +} + +#[test] +fn test_mismatched_registry_key() -> Result<()> { + let lua1 = Lua::new(); + let lua2 = Lua::new(); + + let r = lua1.create_registry_value("hello")?; + match lua2.remove_registry_value(r) { + Err(Error::MismatchedRegistryKey) => {} + r => panic!("wrong result type for mismatched registry key, {:?}", r), + }; + + Ok(()) +} + +#[test] +fn too_many_returns() -> Result<()> { + let lua = Lua::new(); + let f = lua.create_function(|_, ()| Ok(Variadic::from_iter(1..1000000)))?; + assert!(f.call::<_, Vec>(()).is_err()); + Ok(()) +} + +#[test] +fn too_many_arguments() -> Result<()> { + let lua = Lua::new(); + lua.load("function test(...) end").exec()?; + let args = Variadic::from_iter(1..1000000); + assert!(lua + .globals() + .get::<_, Function>("test")? + .call::<_, ()>(args) + .is_err()); + Ok(()) +} + +#[test] +#[cfg(not(feature = "luajit"))] +fn too_many_recursions() -> Result<()> { + let lua = Lua::new(); + let f = lua + .create_function(move |lua, ()| lua.globals().get::<_, Function>("f")?.call::<_, ()>(()))?; + lua.globals().set("f", f)?; + + assert!(lua + .globals() + .get::<_, Function>("f")? + .call::<_, ()>(()) + .is_err()); + + Ok(()) +} + +#[test] +fn too_many_binds() -> Result<()> { + let lua = Lua::new(); + let globals = lua.globals(); + lua.load( + r#" + function f(...) + end + "#, + ) + .exec()?; + + let concat = globals.get::<_, Function>("f")?; + assert!(concat.bind(Variadic::from_iter(1..1000000)).is_err()); + assert!(concat + .call::<_, ()>(Variadic::from_iter(1..1000000)) + .is_err()); + + Ok(()) +} + +#[test] +fn large_args() -> Result<()> { + let lua = Lua::new(); + let globals = lua.globals(); + + globals.set( + "c", + lua.create_function(|_, args: Variadic| { + let mut s = 0; + for i in 0..args.len() { + s += i; + assert_eq!(i, args[i]); + } + Ok(s) + })?, + )?; + + let f: Function = lua + .load( + r#" + return function(...) + return c(...) + end + "#, + ) + .eval()?; + + assert_eq!( + f.call::<_, usize>((0..100).collect::>())?, + 4950 + ); + + Ok(()) +} + +#[test] +fn large_args_ref() -> Result<()> { + let lua = Lua::new(); + + let f = lua.create_function(|_, args: Variadic| { + for i in 0..args.len() { + assert_eq!(args[i], i.to_string()); + } + Ok(()) + })?; + + f.call::<_, ()>((0..100).map(|i| i.to_string()).collect::>())?; + + Ok(()) +} + +#[test] +fn chunk_env() -> Result<()> { + let lua = Lua::new(); + + let assert: Function = lua.globals().get("assert")?; + + let env1 = lua.create_table()?; + env1.set("assert", assert.clone())?; + + let env2 = lua.create_table()?; + env2.set("assert", assert)?; + + lua.load( + r#" + test_var = 1 + "#, + ) + .set_environment(env1.clone())? + .exec()?; + + lua.load( + r#" + assert(test_var == nil) + test_var = 2 + "#, + ) + .set_environment(env2.clone())? + .exec()?; + + assert_eq!( + lua.load("test_var").set_environment(env1)?.eval::()?, + 1 + ); + + assert_eq!( + lua.load("test_var").set_environment(env2)?.eval::()?, + 2 + ); + + Ok(()) +} + +#[test] +fn context_thread() -> Result<()> { + let lua = Lua::new(); + + let f = lua + .load( + r#" + local thread = ... + assert(coroutine.running() == thread) + "#, + ) + .into_function()?; + + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + f.call::<_, ()>(lua.current_thread())?; + + #[cfg(any(feature = "lua51", feature = "luajit"))] + f.call::<_, ()>(Nil)?; + + Ok(()) +} + +#[test] +#[cfg(any(feature = "lua51", feature = "luajit"))] +fn context_thread_51() -> Result<()> { + let lua = Lua::new(); + + let thread = lua.create_thread( + lua.load( + r#" + function (thread) + assert(coroutine.running() == thread) + end + "#, + ) + .eval()?, + )?; + + thread.resume::<_, ()>(thread.clone())?; + + Ok(()) +} + +#[test] +#[cfg(feature = "luajit")] +fn test_jit_version() -> Result<()> { + let lua = Lua::new(); + let jit: Table = lua.globals().get("jit")?; + assert!(jit + .get::<_, String>("version")? + .to_str()? + .contains("LuaJIT")); + Ok(()) +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/thread.rs b/third_party/cargo/vendor/mlua-0.5.3/tests/thread.rs new file mode 100644 index 0000000..1094052 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/thread.rs @@ -0,0 +1,147 @@ +#![cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + feature(link_args) +)] + +#[cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + link_args = "-pagezero_size 10000 -image_base 100000000", + allow(unused_attributes) +)] +extern "system" {} + +use std::panic::catch_unwind; + +use mlua::{Error, Function, Lua, Result, Thread, ThreadStatus}; + +#[test] +fn test_thread() -> Result<()> { + let lua = Lua::new(); + + let thread = lua.create_thread( + lua.load( + r#" + function (s) + local sum = s + for i = 1,4 do + sum = sum + coroutine.yield(sum) + end + return sum + end + "#, + ) + .eval()?, + )?; + + assert_eq!(thread.status(), ThreadStatus::Resumable); + assert_eq!(thread.resume::<_, i64>(0)?, 0); + assert_eq!(thread.status(), ThreadStatus::Resumable); + assert_eq!(thread.resume::<_, i64>(1)?, 1); + assert_eq!(thread.status(), ThreadStatus::Resumable); + assert_eq!(thread.resume::<_, i64>(2)?, 3); + assert_eq!(thread.status(), ThreadStatus::Resumable); + assert_eq!(thread.resume::<_, i64>(3)?, 6); + assert_eq!(thread.status(), ThreadStatus::Resumable); + assert_eq!(thread.resume::<_, i64>(4)?, 10); + assert_eq!(thread.status(), ThreadStatus::Unresumable); + + let accumulate = lua.create_thread( + lua.load( + r#" + function (sum) + while true do + sum = sum + coroutine.yield(sum) + end + end + "#, + ) + .eval::()?, + )?; + + for i in 0..4 { + accumulate.resume::<_, ()>(i)?; + } + assert_eq!(accumulate.resume::<_, i64>(4)?, 10); + assert_eq!(accumulate.status(), ThreadStatus::Resumable); + assert!(accumulate.resume::<_, ()>("error").is_err()); + assert_eq!(accumulate.status(), ThreadStatus::Error); + + let thread = lua + .load( + r#" + coroutine.create(function () + while true do + coroutine.yield(42) + end + end) + "#, + ) + .eval::()?; + assert_eq!(thread.status(), ThreadStatus::Resumable); + assert_eq!(thread.resume::<_, i64>(())?, 42); + + let thread: Thread = lua + .load( + r#" + coroutine.create(function(arg) + assert(arg == 42) + local yieldarg = coroutine.yield(123) + assert(yieldarg == 43) + return 987 + end) + "#, + ) + .eval()?; + + assert_eq!(thread.resume::<_, u32>(42)?, 123); + assert_eq!(thread.resume::<_, u32>(43)?, 987); + + match thread.resume::<_, u32>(()) { + Err(Error::CoroutineInactive) => {} + Err(_) => panic!("resuming dead coroutine error is not CoroutineInactive kind"), + _ => panic!("resuming dead coroutine did not return error"), + } + + Ok(()) +} + +#[test] +fn coroutine_from_closure() -> Result<()> { + let lua = Lua::new(); + + let thrd_main = lua.create_function(|_, ()| Ok(()))?; + lua.globals().set("main", thrd_main)?; + + #[cfg(any( + feature = "lua54", + feature = "lua53", + feature = "lua52", + feature = "luajit" + ))] + let thrd: Thread = lua.load("coroutine.create(main)").eval()?; + #[cfg(feature = "lua51")] + let thrd: Thread = lua + .load("coroutine.create(function(...) return main(unpack(arg)) end)") + .eval()?; + + thrd.resume::<_, ()>(())?; + + Ok(()) +} + +#[test] +fn coroutine_panic() { + match catch_unwind(|| -> Result<()> { + // check that coroutines propagate panics correctly + let lua = Lua::new(); + let thrd_main = lua.create_function(|_, ()| -> Result<()> { + panic!("test_panic"); + })?; + lua.globals().set("main", thrd_main.clone())?; + let thrd: Thread = lua.create_thread(thrd_main)?; + thrd.resume(()) + }) { + Ok(r) => panic!("coroutine panic not propagated, instead returned {:?}", r), + Err(p) => assert!(*p.downcast::<&str>().unwrap() == "test_panic"), + } +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/types.rs b/third_party/cargo/vendor/mlua-0.5.3/tests/types.rs new file mode 100644 index 0000000..bbec13d --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/types.rs @@ -0,0 +1,38 @@ +#![cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + feature(link_args) +)] + +#[cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + link_args = "-pagezero_size 10000 -image_base 100000000", + allow(unused_attributes) +)] +extern "system" {} + +use std::os::raw::c_void; + +use mlua::{Function, LightUserData, Lua, Result}; + +#[test] +fn test_lightuserdata() -> Result<()> { + let lua = Lua::new(); + + let globals = lua.globals(); + lua.load( + r#" + function id(a) + return a + end + "#, + ) + .exec()?; + + let res = globals + .get::<_, Function>("id")? + .call::<_, LightUserData>(LightUserData(42 as *mut c_void))?; + + assert_eq!(res, LightUserData(42 as *mut c_void)); + + Ok(()) +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/userdata.rs b/third_party/cargo/vendor/mlua-0.5.3/tests/userdata.rs new file mode 100644 index 0000000..6146aed --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/userdata.rs @@ -0,0 +1,349 @@ +#![cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + feature(link_args) +)] + +#[cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + link_args = "-pagezero_size 10000 -image_base 100000000", + allow(unused_attributes) +)] +extern "system" {} + +use std::sync::Arc; + +#[cfg(feature = "lua54")] +use std::sync::atomic::{AtomicI64, Ordering}; + +use mlua::{ + AnyUserData, ExternalError, Function, Lua, MetaMethod, Result, String, UserData, + UserDataMethods, Value, +}; + +#[test] +fn test_user_data() -> Result<()> { + struct UserData1(i64); + struct UserData2(Box); + + impl UserData for UserData1 {} + impl UserData for UserData2 {} + + let lua = Lua::new(); + let userdata1 = lua.create_userdata(UserData1(1))?; + let userdata2 = lua.create_userdata(UserData2(Box::new(2)))?; + + assert!(userdata1.is::()); + assert!(!userdata1.is::()); + assert!(userdata2.is::()); + assert!(!userdata2.is::()); + + assert_eq!(userdata1.borrow::()?.0, 1); + assert_eq!(*userdata2.borrow::()?.0, 2); + + Ok(()) +} + +#[test] +fn test_methods() -> Result<()> { + struct MyUserData(i64); + + impl UserData for MyUserData { + fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_method("get_value", |_, data, ()| Ok(data.0)); + methods.add_method_mut("set_value", |_, data, args| { + data.0 = args; + Ok(()) + }); + } + } + + let lua = Lua::new(); + let globals = lua.globals(); + let userdata = lua.create_userdata(MyUserData(42))?; + globals.set("userdata", userdata.clone())?; + lua.load( + r#" + function get_it() + return userdata:get_value() + end + + function set_it(i) + return userdata:set_value(i) + end + "#, + ) + .exec()?; + let get = globals.get::<_, Function>("get_it")?; + let set = globals.get::<_, Function>("set_it")?; + assert_eq!(get.call::<_, i64>(())?, 42); + userdata.borrow_mut::()?.0 = 64; + assert_eq!(get.call::<_, i64>(())?, 64); + set.call::<_, ()>(100)?; + assert_eq!(get.call::<_, i64>(())?, 100); + + Ok(()) +} + +#[test] +fn test_metamethods() -> Result<()> { + #[derive(Copy, Clone)] + struct MyUserData(i64); + + impl UserData for MyUserData { + fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_method("get", |_, data, ()| Ok(data.0)); + methods.add_meta_function( + MetaMethod::Add, + |_, (lhs, rhs): (MyUserData, MyUserData)| Ok(MyUserData(lhs.0 + rhs.0)), + ); + methods.add_meta_function( + MetaMethod::Sub, + |_, (lhs, rhs): (MyUserData, MyUserData)| Ok(MyUserData(lhs.0 - rhs.0)), + ); + methods.add_meta_function(MetaMethod::Eq, |_, (lhs, rhs): (MyUserData, MyUserData)| { + Ok(lhs.0 == rhs.0) + }); + methods.add_meta_method(MetaMethod::Index, |_, data, index: String| { + if index.to_str()? == "inner" { + Ok(data.0) + } else { + Err("no such custom index".to_lua_err()) + } + }); + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + methods.add_meta_method(MetaMethod::Pairs, |lua, data, ()| { + use std::iter::FromIterator; + let stateless_iter = lua.create_function(|_, (data, i): (MyUserData, i64)| { + let i = i + 1; + if i <= data.0 { + return Ok(mlua::Variadic::from_iter(vec![i, i])); + } + return Ok(mlua::Variadic::new()); + })?; + Ok((stateless_iter, data.clone(), 0)) + }); + } + } + + let lua = Lua::new(); + let globals = lua.globals(); + globals.set("userdata1", MyUserData(7))?; + globals.set("userdata2", MyUserData(3))?; + globals.set("userdata3", MyUserData(3))?; + assert_eq!( + lua.load("userdata1 + userdata2").eval::()?.0, + 10 + ); + + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + let pairs_it = { + lua.load( + r#" + function pairs_it() + local r = 0 + for i, v in pairs(userdata1) do + r = r + v + end + return r + end + "#, + ) + .exec()?; + globals.get::<_, Function>("pairs_it")? + }; + + assert_eq!(lua.load("userdata1 - userdata2").eval::()?.0, 4); + assert_eq!(lua.load("userdata1:get()").eval::()?, 7); + assert_eq!(lua.load("userdata2.inner").eval::()?, 3); + #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] + assert_eq!(pairs_it.call::<_, i64>(())?, 28); + assert!(lua.load("userdata2.nonexist_field").eval::<()>().is_err()); + + let userdata2: Value = globals.get("userdata2")?; + let userdata3: Value = globals.get("userdata3")?; + + assert!(lua.load("userdata2 == userdata3").eval::()?); + assert!(userdata2 != userdata3); // because references are differ + assert!(userdata2.equals(userdata3)?); + + let userdata1: AnyUserData = globals.get("userdata1")?; + assert!(userdata1.has_metamethod(MetaMethod::Add)?); + assert!(userdata1.has_metamethod(MetaMethod::Sub)?); + assert!(userdata1.has_metamethod(MetaMethod::Index)?); + assert!(!userdata1.has_metamethod(MetaMethod::Pow)?); + + Ok(()) +} + +#[test] +#[cfg(feature = "lua54")] +fn test_metamethod_close() -> Result<()> { + #[derive(Clone)] + struct MyUserData(Arc); + + impl UserData for MyUserData { + fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_method("get", |_, data, ()| Ok(data.0.load(Ordering::Relaxed))); + methods.add_meta_method(MetaMethod::Close, |_, data, _err: Value| { + data.0.store(0, Ordering::Relaxed); + Ok(()) + }); + } + } + + let lua = Lua::new(); + let globals = lua.globals(); + + let ud = MyUserData(Arc::new(AtomicI64::new(-1))); + let ud2 = ud.clone(); + + globals.set( + "new_userdata", + lua.create_function(move |_lua, val: i64| { + let ud = ud2.clone(); + ud.0.store(val, Ordering::Relaxed); + Ok(ud) + })?, + )?; + + lua.load( + r#" + do + local ud = new_userdata(7) + assert(ud:get() == 7) + end + "#, + ) + .exec()?; + + assert_eq!(ud.0.load(Ordering::Relaxed), 0); + + Ok(()) +} + +#[test] +fn test_gc_userdata() -> Result<()> { + struct MyUserdata { + id: u8, + } + + impl UserData for MyUserdata { + fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_method("access", |_, this, ()| { + assert!(this.id == 123); + Ok(()) + }); + } + } + + let lua = Lua::new(); + lua.globals().set("userdata", MyUserdata { id: 123 })?; + + assert!(lua + .load( + r#" + local tbl = setmetatable({ + userdata = userdata + }, { __gc = function(self) + -- resurrect userdata + hatch = self.userdata + end }) + + tbl = nil + userdata = nil -- make table and userdata collectable + collectgarbage("collect") + hatch:access() + "# + ) + .exec() + .is_err()); + + Ok(()) +} + +#[test] +fn detroys_userdata() -> Result<()> { + struct MyUserdata(Arc<()>); + + impl UserData for MyUserdata {} + + let rc = Arc::new(()); + + let lua = Lua::new(); + lua.globals().set("userdata", MyUserdata(rc.clone()))?; + + assert_eq!(Arc::strong_count(&rc), 2); + + // should destroy all objects + let _ = lua.globals().raw_remove("userdata")?; + lua.gc_collect()?; + + assert_eq!(Arc::strong_count(&rc), 1); + + Ok(()) +} + +#[test] +fn user_value() -> Result<()> { + struct MyUserData; + + impl UserData for MyUserData {} + + let lua = Lua::new(); + let ud = lua.create_userdata(MyUserData)?; + ud.set_user_value("hello")?; + assert_eq!(ud.get_user_value::()?, "hello"); + assert!(ud.get_user_value::().is_err()); + + Ok(()) +} + +#[test] +fn test_functions() -> Result<()> { + struct MyUserData(i64); + + impl UserData for MyUserData { + fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_function("get_value", |_, ud: AnyUserData| { + Ok(ud.borrow::()?.0) + }); + methods.add_function("set_value", |_, (ud, value): (AnyUserData, i64)| { + ud.borrow_mut::()?.0 = value; + Ok(()) + }); + methods.add_function("get_constant", |_, ()| Ok(7)); + } + } + + let lua = Lua::new(); + let globals = lua.globals(); + let userdata = lua.create_userdata(MyUserData(42))?; + globals.set("userdata", userdata.clone())?; + lua.load( + r#" + function get_it() + return userdata:get_value() + end + + function set_it(i) + return userdata:set_value(i) + end + + function get_constant() + return userdata.get_constant() + end + "#, + ) + .exec()?; + let get = globals.get::<_, Function>("get_it")?; + let set = globals.get::<_, Function>("set_it")?; + let get_constant = globals.get::<_, Function>("get_constant")?; + assert_eq!(get.call::<_, i64>(())?, 42); + userdata.borrow_mut::()?.0 = 64; + assert_eq!(get.call::<_, i64>(())?, 64); + set.call::<_, ()>(100)?; + assert_eq!(get.call::<_, i64>(())?, 100); + assert_eq!(get_constant.call::<_, i64>(())?, 7); + + Ok(()) +} diff --git a/third_party/cargo/vendor/mlua-0.5.3/tests/value.rs b/third_party/cargo/vendor/mlua-0.5.3/tests/value.rs new file mode 100644 index 0000000..7b59a51 --- /dev/null +++ b/third_party/cargo/vendor/mlua-0.5.3/tests/value.rs @@ -0,0 +1,69 @@ +#![cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + feature(link_args) +)] + +#[cfg_attr( + all(feature = "luajit", target_os = "macos", target_arch = "x86_64"), + link_args = "-pagezero_size 10000 -image_base 100000000", + allow(unused_attributes) +)] +extern "system" {} + +use mlua::{Lua, Result, Value}; + +#[test] +fn test_value_eq() -> Result<()> { + let lua = Lua::new(); + let globals = lua.globals(); + + lua.load( + r#" + table1 = {1} + table2 = {1} + string1 = "hello" + string2 = "hello" + num1 = 1 + num2 = 1.0 + num3 = "1" + func1 = function() end + func2 = func1 + func3 = function() end + thread1 = coroutine.create(function() end) + thread2 = thread1 + + setmetatable(table1, { + __eq = function(a, b) return a[1] == b[1] end + }) + "#, + ) + .exec()?; + + let table1: Value = globals.get("table1")?; + let table2: Value = globals.get("table2")?; + let string1: Value = globals.get("string1")?; + let string2: Value = globals.get("string2")?; + let num1: Value = globals.get("num1")?; + let num2: Value = globals.get("num2")?; + let num3: Value = globals.get("num3")?; + let func1: Value = globals.get("func1")?; + let func2: Value = globals.get("func2")?; + let func3: Value = globals.get("func3")?; + let thread1: Value = globals.get("thread1")?; + let thread2: Value = globals.get("thread2")?; + + assert!(table1 != table2); + assert!(table1.equals(table2)?); + assert!(string1 == string2); + assert!(string1.equals(string2)?); + assert!(num1 == num2); + assert!(num1.equals(num2)?); + assert!(num1 != num3); + assert!(func1 == func2); + assert!(func1 != func3); + assert!(!func1.equals(func3)?); + assert!(thread1 == thread2); + assert!(thread1.equals(thread2)?); + + Ok(()) +}