Compare commits
24 Commits
10c5ee1159
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
519148ffd9 | ||
|
|
6be301ebd8 | ||
|
|
76a8d4857f | ||
|
|
7f7bab7f16 | ||
|
|
71d2562d83 | ||
|
|
9c67b42e9c | ||
|
|
56734bcb1c | ||
|
|
b64c063563 | ||
|
|
da9f5e9198 | ||
|
|
0ceb7c6c8c | ||
|
|
b979b290b8 | ||
|
|
923a941473 | ||
|
|
03911c0572 | ||
|
|
77fa0e2b09 | ||
|
|
f646fe4605 | ||
|
|
cb5f0d8fcc | ||
|
|
3a2e8e6c0f | ||
|
|
467416e3ef | ||
|
|
1464119ff8 | ||
|
|
beae04dee8 | ||
|
|
ebe7d236e9 | ||
|
|
2fea8f1e20 | ||
|
|
392c793d5c | ||
|
|
e7daffa6f7 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
||||
/target
|
||||
.vscode
|
||||
489
Cargo.lock
generated
489
Cargo.lock
generated
@@ -11,6 +11,12 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anes"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.19"
|
||||
@@ -73,18 +79,91 @@ version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||
|
||||
[[package]]
|
||||
name = "bincode"
|
||||
version = "1.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
|
||||
|
||||
[[package]]
|
||||
name = "cast"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
|
||||
|
||||
[[package]]
|
||||
name = "ciborium"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e"
|
||||
dependencies = [
|
||||
"ciborium-io",
|
||||
"ciborium-ll",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ciborium-io"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757"
|
||||
|
||||
[[package]]
|
||||
name = "ciborium-ll"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9"
|
||||
dependencies = [
|
||||
"ciborium-io",
|
||||
"half",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
|
||||
|
||||
[[package]]
|
||||
name = "colog"
|
||||
version = "1.3.0"
|
||||
@@ -112,12 +191,73 @@ dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "criterion"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f"
|
||||
dependencies = [
|
||||
"anes",
|
||||
"cast",
|
||||
"ciborium",
|
||||
"clap",
|
||||
"criterion-plot",
|
||||
"is-terminal",
|
||||
"itertools",
|
||||
"num-traits",
|
||||
"once_cell",
|
||||
"oorandom",
|
||||
"plotters",
|
||||
"rayon",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"tinytemplate",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "criterion-plot"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
|
||||
dependencies = [
|
||||
"cast",
|
||||
"itertools",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
|
||||
dependencies = [
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
|
||||
|
||||
[[package]]
|
||||
name = "csv"
|
||||
version = "1.3.1"
|
||||
@@ -230,6 +370,12 @@ version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.3.3"
|
||||
@@ -242,6 +388,16 @@ dependencies = [
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "half"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crunchy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.5"
|
||||
@@ -260,6 +416,12 @@ version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
|
||||
|
||||
[[package]]
|
||||
name = "home"
|
||||
version = "0.5.11"
|
||||
@@ -279,12 +441,32 @@ dependencies = [
|
||||
"hashbrown 0.15.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.15"
|
||||
@@ -315,6 +497,16 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.77"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
@@ -327,6 +519,12 @@ version = "0.2.174"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
|
||||
|
||||
[[package]]
|
||||
name = "linked-hash-map"
|
||||
version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.15"
|
||||
@@ -355,12 +553,46 @@ version = "0.4.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
|
||||
|
||||
[[package]]
|
||||
name = "lru-cache"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c"
|
||||
dependencies = [
|
||||
"linked-hash-map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.3"
|
||||
@@ -373,6 +605,18 @@ version = "1.70.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
|
||||
|
||||
[[package]]
|
||||
name = "oncemutex"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44d11de466f4a3006fe8a5e7ec84e93b79c70cb992ae0aa0eb631ad2df8abfe2"
|
||||
|
||||
[[package]]
|
||||
name = "oorandom"
|
||||
version = "11.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.11"
|
||||
@@ -386,6 +630,54 @@ dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phonenumber"
|
||||
version = "0.3.7+8.13.52"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2247167dc3741816fdd4d3690e97f56a892a264b44f4c702078b72d1f8b6bd40"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"either",
|
||||
"fnv",
|
||||
"nom",
|
||||
"once_cell",
|
||||
"quick-xml",
|
||||
"regex",
|
||||
"regex-cache",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"strum 0.26.3",
|
||||
"thiserror 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "plotters"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"plotters-backend",
|
||||
"plotters-svg",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "plotters-backend"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a"
|
||||
|
||||
[[package]]
|
||||
name = "plotters-svg"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670"
|
||||
dependencies = [
|
||||
"plotters-backend",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic"
|
||||
version = "1.11.1"
|
||||
@@ -461,6 +753,15 @@ dependencies = [
|
||||
"thiserror 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.37.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.40"
|
||||
@@ -476,6 +777,26 @@ version = "5.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.13"
|
||||
@@ -494,7 +815,7 @@ dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
"regex-syntax 0.8.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -505,9 +826,27 @@ checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
"regex-syntax 0.8.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-cache"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f7b62d69743b8b94f353b6b7c3deb4c5582828328bcb8d5fedf214373808793"
|
||||
dependencies = [
|
||||
"lru-cache",
|
||||
"oncemutex",
|
||||
"regex",
|
||||
"regex-syntax 0.6.29",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.5"
|
||||
@@ -519,16 +858,18 @@ name = "rlibphonenumber"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"colog",
|
||||
"criterion",
|
||||
"dashmap",
|
||||
"dec_from_char",
|
||||
"env_logger",
|
||||
"fast-cat",
|
||||
"itoa",
|
||||
"log",
|
||||
"phonenumber",
|
||||
"protobuf",
|
||||
"protobuf-codegen",
|
||||
"regex",
|
||||
"strum",
|
||||
"strum 0.27.1",
|
||||
"thiserror 2.0.12",
|
||||
]
|
||||
|
||||
@@ -570,6 +911,15 @@ version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||
|
||||
[[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 = "scopeguard"
|
||||
version = "1.2.0"
|
||||
@@ -596,19 +946,53 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.140"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.15.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.26.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
|
||||
dependencies = [
|
||||
"strum_macros 0.26.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.27.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32"
|
||||
dependencies = [
|
||||
"strum_macros",
|
||||
"strum_macros 0.27.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strum_macros"
|
||||
version = "0.26.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustversion",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -688,6 +1072,16 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinytemplate"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.18"
|
||||
@@ -700,6 +1094,16 @@ version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.14.2+wasi-0.2.4"
|
||||
@@ -709,6 +1113,74 @@ dependencies = [
|
||||
"wit-bindgen-rt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"rustversion",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.77"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "which"
|
||||
version = "4.4.2"
|
||||
@@ -721,6 +1193,15 @@ dependencies = [
|
||||
"rustix 0.38.44",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||
dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.59.0"
|
||||
|
||||
14
Cargo.toml
14
Cargo.toml
@@ -10,7 +10,7 @@ build = "build/rust_build.rs"
|
||||
log = "0.4.27"
|
||||
# helpful error package
|
||||
thiserror = "2.0.12"
|
||||
# google protobuf lib required to use .proto files from assets
|
||||
# protobuf lib required to use .proto files from assets
|
||||
protobuf = "3.7.2"
|
||||
# optimized concurrent map
|
||||
dashmap = "6.1.0"
|
||||
@@ -34,4 +34,14 @@ protobuf-codegen = "3.7.2"
|
||||
|
||||
[dev-dependencies]
|
||||
colog = "1.3.0"
|
||||
env_logger = "0.11.8"
|
||||
env_logger = "0.11.8"
|
||||
criterion = "0.5"
|
||||
phonenumber = "0.3"
|
||||
|
||||
[[bench]]
|
||||
name = "format_bench"
|
||||
harness = false
|
||||
|
||||
[[bench]]
|
||||
name = "parsing_bench"
|
||||
harness = false
|
||||
176
LICENSE
Normal file
176
LICENSE
Normal file
@@ -0,0 +1,176 @@
|
||||
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
|
||||
121
Readme.md
Normal file
121
Readme.md
Normal file
@@ -0,0 +1,121 @@
|
||||
# libphonenumber-rust
|
||||
|
||||
[](https://crates.io/crates/rlibphonenumber)
|
||||
[](https://docs.rs/rlibphonenumber)
|
||||
[](https://opensource.org/licenses/Apache-2.0)
|
||||
|
||||
A Rust port of Google's comprehensive library for parsing, formatting, and validating international phone numbers.
|
||||
|
||||
## Overview
|
||||
|
||||
This library is a new adaptation of Google's `libphonenumber` for Rust. Its primary goal is to provide a powerful and efficient tool for handling phone numbers, with a structure that is intuitively close to the original C++ version.
|
||||
|
||||
You might be aware of an existing Rust implementation of `libphonenumber`. However, its maintenance has slowed, and I believe that a fresh start is the best path forward. This project aims to deliver a more direct and familiar port for developers acquainted with the C++ or Java versions of the original library.
|
||||
|
||||
This library gives you access to a wide range of functionalities, including:
|
||||
* Parsing and formatting phone numbers.
|
||||
* Validating phone numbers for all regions of the world.
|
||||
* Determining the number type (e.g., Mobile, Fixed-line, Toll-free).
|
||||
* Providing example numbers for every country.
|
||||
|
||||
## Performance
|
||||
|
||||
The following benchmarks were run against the `rust-phonenumber` crate. All tests were performed on the same machine and dataset. *Lower is better.*
|
||||
|
||||
### Formatting
|
||||
|
||||
| Format | rlibphonenumber (this crate) | rust-phonenumber | Performance Gain |
|
||||
|:---|:---:|:---:|:---:|
|
||||
| **E164** | **~78 ns** | ~2.59 µs | **~33x faster** |
|
||||
| **International** | **~1.34 µs** | ~3.21 µs | **~2.4x faster** |
|
||||
| **National** | **~2.33 µs** | ~4.87 µs | **~2.1x faster** |
|
||||
| **RFC3966** | **~1.62 µs** | ~3.47 µs | **~2.1x faster** |
|
||||
|
||||
### Parsing
|
||||
|
||||
| Task | rlibphonenumber (this crate) | rust-phonenumber | Performance Gain |
|
||||
|:--- |:---:|:---:|:---:|
|
||||
| **Parse** | **~11.60 µs** | ~13.45 µs | **~16% faster** |
|
||||
|
||||
This significant performance advantage is achieved through a focus on minimizing allocations, a more direct implementation path, and the use of modern tooling for metadata generation.
|
||||
|
||||
## Current Status
|
||||
|
||||
The project is currently in its initial phase of development. The core functionalities are being ported module by module to ensure quality and consistency.
|
||||
|
||||
### Implemented:
|
||||
* **PhoneNumberUtil:** The main utility for all phone number operations, such as parsing, formatting, and validation (Passes original tests).
|
||||
|
||||
### Future Plans:
|
||||
The roadmap includes porting the following key components:
|
||||
|
||||
* **AsYouTypeFormatter:** To format phone numbers as they are being typed.
|
||||
* **PhoneNumberOfflineGeocoder:** To provide geographical information for a phone number.
|
||||
* **PhoneNumberToCarrierMapper:** To identify the carrier associated with a phone number.
|
||||
|
||||
## Installation
|
||||
|
||||
Add this to your `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
rlibphonenumber = "0.1.0" # Replace with the actual version
|
||||
```
|
||||
|
||||
## Getting Started
|
||||
|
||||
Here is a basic example of how to parse and format a phone number:
|
||||
|
||||
```rust
|
||||
use rlibphonenumber::{PhoneNumberFormat, PHONE_NUMBER_UTIL};
|
||||
|
||||
fn main() {
|
||||
let number_to_parse = "+14155552671";
|
||||
let default_region = "US";
|
||||
|
||||
match PHONE_NUMBER_UTIL.parse(number_to_parse, default_region) {
|
||||
Ok(number) => {
|
||||
println!("Parsed number: {:?}", number);
|
||||
|
||||
let formatted_number = PHONE_NUMBER_UTIL.format(&number, PhoneNumberFormat::International).unwrap();
|
||||
println!("International format: {}", formatted_number);
|
||||
|
||||
let is_valid = PHONE_NUMBER_UTIL.is_valid_number(&number).unwrap();
|
||||
println!("Is the number valid? {}", is_valid);
|
||||
}
|
||||
Err(e) => {
|
||||
println!("Error parsing number: {:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## For Contributors
|
||||
|
||||
Contributions are **highly** welcome! Whether you are fixing a bug, improving documentation, or helping to port a new module, your help is appreciated.
|
||||
|
||||
### Code Generation
|
||||
|
||||
To maintain consistency with the original library, this project uses pre-compiled metadata. If you need to regenerate the metadata, for instance, after updating the `PhoneNumberMetadata.xml` file, you can use the provided tools.
|
||||
|
||||
The `tools` directory contains a rewritten Rust-based code generator for the C++ pre-compiled metadata.
|
||||
|
||||
To run the code generation process, simply execute the following script:
|
||||
|
||||
```sh
|
||||
./tools/scripts/generate_metadata.sh
|
||||
```
|
||||
|
||||
This script will:
|
||||
1. Build the Java-based tool that converts the XML metadata to a Rust-compatible format.
|
||||
2. Run the generator for the main metadata and the test metadata.
|
||||
3. Place the generated `.rs` files into the `src/generated/metadata` directory.
|
||||
|
||||
You can skip the Java build step by passing the `--skip-install` flag, which is useful if no changes were made to the generator itself.
|
||||
|
||||
```sh
|
||||
./tools/scripts/generate_metadata.sh --skip-install```
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the Apache License, Version 2.0. Please see the `LICENSE` file for details.
|
||||
76
benches/format_bench.rs
Normal file
76
benches/format_bench.rs
Normal file
@@ -0,0 +1,76 @@
|
||||
use criterion::{Criterion, black_box, criterion_group, criterion_main};
|
||||
|
||||
use rlibphonenumber::{PhoneNumberFormat, PHONE_NUMBER_UTIL};
|
||||
|
||||
use phonenumber::{
|
||||
self as rlp,
|
||||
country::Id::{self, AU}, Mode,
|
||||
};
|
||||
|
||||
type TestEntity = (&'static str, &'static str, Id);
|
||||
|
||||
fn setup_numbers() -> Vec<TestEntity> {
|
||||
vec![("0011 54 9 11 8765 4321 ext. 1234", "AU", AU)]
|
||||
}
|
||||
|
||||
fn convert_to_rlp_numbers(numbers: &[TestEntity]) -> Vec<rlp::PhoneNumber> {
|
||||
numbers
|
||||
.iter()
|
||||
.map(|s| rlp::parse(Some(s.2), s.0).unwrap())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn convert_to_rlibphonenumber_numbers(
|
||||
numbers: &[TestEntity],
|
||||
) -> Vec<rlibphonenumber::PhoneNumber> {
|
||||
numbers
|
||||
.iter()
|
||||
.map(|s| PHONE_NUMBER_UTIL.parse(s.0, s.1).unwrap())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn formatting_benchmark(c: &mut Criterion) {
|
||||
let numbers = setup_numbers();
|
||||
let rlp_numbers = convert_to_rlp_numbers(&numbers);
|
||||
let numbers = convert_to_rlibphonenumber_numbers(&numbers);
|
||||
|
||||
let mut group = c.benchmark_group("Formatting Comparison");
|
||||
|
||||
let mut test = |format_a: PhoneNumberFormat, format_b: Mode| {
|
||||
group.bench_function(format!("rlibphonenumber: format({:?})", format_a), |b| {
|
||||
b.iter(|| {
|
||||
for number in &numbers {
|
||||
PHONE_NUMBER_UTIL
|
||||
.format(black_box(number), black_box(format_a))
|
||||
.unwrap();
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
group.bench_function(format!("rust-phonenumber: format({:?})", format_b), |b| {
|
||||
b.iter(|| {
|
||||
for number in &rlp_numbers {
|
||||
rlp::format(black_box(number)).mode(format_b).to_string();
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
for (number_a, number_b) in rlp_numbers.iter().zip(numbers.iter()) {
|
||||
assert_eq!(
|
||||
rlp::format(number_a).mode(format_b).to_string(),
|
||||
PHONE_NUMBER_UTIL
|
||||
.format(number_b, format_a)
|
||||
.unwrap()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
test(PhoneNumberFormat::E164, Mode::E164);
|
||||
test(PhoneNumberFormat::International, Mode::International);
|
||||
test(PhoneNumberFormat::National, Mode::National);
|
||||
test(PhoneNumberFormat::RFC3966, Mode::Rfc3966);
|
||||
group.finish();
|
||||
}
|
||||
|
||||
criterion_group!(benches, formatting_benchmark);
|
||||
criterion_main!(benches);
|
||||
73
benches/parsing_bench.rs
Normal file
73
benches/parsing_bench.rs
Normal file
@@ -0,0 +1,73 @@
|
||||
// benches/parsing_benchmark.rs
|
||||
|
||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||
|
||||
// --- Импорты из вашей библиотеки ---
|
||||
use rlibphonenumber::PHONE_NUMBER_UTIL;
|
||||
|
||||
// --- Импорты из внешней библиотеки ---
|
||||
use phonenumber::{self as rlp, country::Id};
|
||||
|
||||
// Тип для наших тестовых данных: (строка_номера, регион_для_вас, регион_для_rlp)
|
||||
type TestEntity = (&'static str, &'static str, Id);
|
||||
|
||||
/// Подготавливает разнообразный набор данных для тестирования парсинга.
|
||||
/// Это дает более объективную оценку, чем один номер.
|
||||
fn setup_parsing_data() -> Vec<TestEntity> {
|
||||
use phonenumber::country::Id::*;
|
||||
vec![
|
||||
// Оригинальный номер из вашего примера
|
||||
("0011 54 9 11 8765 4321 ext. 1234", "AU", AU),
|
||||
// Простой номер США в национальном формате
|
||||
("(650) 253-0000", "US", US),
|
||||
// Номер Великобритании в международном формате со знаком +
|
||||
("+44 20 8765 4321", "GB", GB),
|
||||
// Номер Великобритании с национальным префиксом (ведущий ноль)
|
||||
("020 8765 4321", "GB", GB),
|
||||
// Сложный мобильный номер Аргентины
|
||||
("011 15-1234-5678", "AR", AR),
|
||||
// Итальянский номер со значащим ведущим нулем
|
||||
("02 12345678", "IT", IT),
|
||||
// "Vanity" номер (с буквами)
|
||||
("1-800-FLOWERS", "US", US),
|
||||
// Короткий номер, который может быть валидным в некоторых регионах
|
||||
("12345", "DE", DE),
|
||||
]
|
||||
}
|
||||
|
||||
fn parsing_benchmark(c: &mut Criterion) {
|
||||
// Получаем наш набор тестовых данных
|
||||
let numbers_to_parse = setup_parsing_data();
|
||||
|
||||
let mut group = c.benchmark_group("Parsing Comparison");
|
||||
|
||||
// --- Бенчмарк для вашей библиотеки rlibphonenumber ---
|
||||
group.bench_function("rlibphonenumber: parse()", |b| {
|
||||
// b.iter() запускает код в цикле много раз для замера
|
||||
b.iter(|| {
|
||||
// Итерируемся по всем номерам в нашем наборе
|
||||
for (number_str, region, _) in &numbers_to_parse {
|
||||
// Вызываем parse, обернув аргументы в black_box.
|
||||
// Это гарантирует, что компилятор не оптимизирует вызов.
|
||||
// Мы не используем результат, так как нас интересует только скорость выполнения.
|
||||
let _ = PHONE_NUMBER_UTIL.parse(black_box(number_str), black_box(region));
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// --- Бенчмарк для библиотеки rust-phonenumber ---
|
||||
group.bench_function("rust-phonenumber: parse()", |b| {
|
||||
b.iter(|| {
|
||||
for (number_str, _, region_id) in &numbers_to_parse {
|
||||
// Аналогичный вызов для второй библиотеки
|
||||
let _ = rlp::parse(black_box(Some(*region_id)), black_box(number_str));
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
group.finish();
|
||||
}
|
||||
|
||||
// Макросы для регистрации и запуска бенчмарка
|
||||
criterion_group!(benches, parsing_benchmark);
|
||||
criterion_main!(benches);
|
||||
@@ -1,76 +1,20 @@
|
||||
/**
|
||||
* This file represents content of https://github.com/google/libphonenumber/tree/master/tools/cpp
|
||||
*/
|
||||
|
||||
use std::{collections::BTreeMap, fs::File, io::{BufRead, BufReader}, num::ParseIntError, path::Path};
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
enum BuildError {
|
||||
#[error("IO error occurred: {0}")]
|
||||
IO(#[from] std::io::Error),
|
||||
|
||||
#[error("Line {line_num} is too long (max is {max_len} bytes)")]
|
||||
LineTooLong { line_num: usize, max_len: usize },
|
||||
|
||||
#[error("Failed to parse prefix '{prefix}': {source}")]
|
||||
PrefixParseError {
|
||||
prefix: String,
|
||||
#[source]
|
||||
source: ParseIntError,
|
||||
},
|
||||
}
|
||||
|
||||
fn parse_prefixes(path: &str, prefixes: &mut BTreeMap<i32, String>) -> Result<(), BuildError> {
|
||||
prefixes.clear();
|
||||
|
||||
let input = File::open(path)?;
|
||||
const MAX_LINE_LENGTH: usize = 2 * 1024;
|
||||
|
||||
let mut reader = BufReader::new(input);
|
||||
let mut line_buffer = String::with_capacity(MAX_LINE_LENGTH);
|
||||
let mut line_number = 0;
|
||||
|
||||
loop {
|
||||
line_number += 1;
|
||||
line_buffer.clear();
|
||||
|
||||
let bytes_read = reader.read_line(&mut line_buffer)?;
|
||||
if bytes_read == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
if !line_buffer.ends_with('\n') {
|
||||
return Err(BuildError::LineTooLong {
|
||||
line_num: line_number,
|
||||
max_len: MAX_LINE_LENGTH,
|
||||
});
|
||||
}
|
||||
|
||||
let line = line_buffer.trim();
|
||||
if line.is_empty() || line.starts_with('#') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some((prefix_str, desc)) = line.split_once('|') {
|
||||
if prefix_str.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let prefix_code = prefix_str.parse().map_err(|e| BuildError::PrefixParseError {
|
||||
prefix: prefix_str.to_string(),
|
||||
source: e,
|
||||
})?;
|
||||
prefixes.insert(prefix_code, desc.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
// Copyright (C) 2009 The Libphonenumber Authors
|
||||
// Copyright (C) 2025 The Kashin Vladislav (Rust adaptation author)
|
||||
//
|
||||
// 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.
|
||||
|
||||
|
||||
|
||||
fn main() -> Result<(), BuildError> {
|
||||
fn main() {
|
||||
protobuf_codegen::Codegen::new()
|
||||
.pure()
|
||||
.includes(["resources"])
|
||||
@@ -78,5 +22,4 @@ fn main() -> Result<(), BuildError> {
|
||||
.input("resources/phonenumber.proto")
|
||||
.cargo_out_dir("proto_gen")
|
||||
.run_from_script();
|
||||
Ok(())
|
||||
}
|
||||
26
src/generated/metadata/mod.rs
Normal file
26
src/generated/metadata/mod.rs
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright (C) 2009 The Libphonenumber Authors
|
||||
// Copyright (C) 2025 The Kashin Vladislav (Rust adaptation author)
|
||||
//
|
||||
// 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.
|
||||
|
||||
|
||||
mod metadata;
|
||||
|
||||
// use only in test case
|
||||
#[cfg(test)]
|
||||
mod test_metadata;
|
||||
|
||||
pub use metadata::METADATA;
|
||||
#[cfg(test)]
|
||||
pub use test_metadata::TEST_METADATA;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright (C) 2025 @Vloldik
|
||||
// Copyright (C) 2009 The Libphonenumber Authors
|
||||
// Copyright (C) 2025 The Kashin Vladislav (Rust adaptation author)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -11,5 +12,6 @@
|
||||
// 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.
|
||||
//
|
||||
// This file is generated automatically, do not edit it manually.
|
||||
|
||||
pub mod proto;
|
||||
pub mod metadata;
|
||||
@@ -1,3 +0,0 @@
|
||||
mod region_code;
|
||||
|
||||
pub use region_code::RegionCode;
|
||||
@@ -1,13 +0,0 @@
|
||||
pub struct RegionCode {
|
||||
}
|
||||
|
||||
impl RegionCode {
|
||||
/// Returns a region code string representing the "unknown" region.
|
||||
pub fn get_unknown() -> &'static str {
|
||||
return Self::zz();
|
||||
}
|
||||
|
||||
pub fn zz() -> &'static str {
|
||||
return "ZZ";
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,23 @@
|
||||
// Copyright (C) 2009 The Libphonenumber Authors
|
||||
// Copyright (C) 2025 The Kashin Vladislav (Rust adaptation author)
|
||||
//
|
||||
// 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.
|
||||
|
||||
use crate::generated::proto::phonemetadata::PhoneNumberDesc;
|
||||
|
||||
use crate::proto_gen::phonemetadata::PhoneNumberDesc;
|
||||
/// Internal phonenumber matching API used to isolate the underlying
|
||||
/// implementation of the matcher and allow different implementations to be
|
||||
/// swapped in easily.
|
||||
|
||||
pub(crate) trait MatcherApi: Send + Sync {
|
||||
/// Returns whether the given national number (a string containing only decimal
|
||||
/// digits) matches the national number pattern defined in the given
|
||||
|
||||
31
src/lib.rs
31
src/lib.rs
@@ -1,11 +1,25 @@
|
||||
mod shortnumberinfo;
|
||||
// Copyright (C) 2009 The Libphonenumber Authors
|
||||
// Copyright (C) 2025 The Kashin Vladislav (Rust adaptation author)
|
||||
//
|
||||
// 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.
|
||||
|
||||
mod interfaces;
|
||||
/// This module is automatically generated from /resources/*.proto
|
||||
mod proto_gen;
|
||||
mod generated;
|
||||
mod phonenumberutil;
|
||||
mod regexp_cache;
|
||||
mod regex_based_matcher;
|
||||
pub mod i18n;
|
||||
pub mod region_code;
|
||||
pub(crate) mod regex_util;
|
||||
pub(crate) mod string_util;
|
||||
|
||||
@@ -27,9 +41,12 @@ pub use phonenumberutil::{
|
||||
ExtractNumberResult,
|
||||
PhoneNumberUtil
|
||||
},
|
||||
errors,
|
||||
enums,
|
||||
errors::{*},
|
||||
enums::{*},
|
||||
};
|
||||
pub use proto_gen::phonemetadata;
|
||||
pub use proto_gen::phonenumber;
|
||||
pub use generated::proto::phonemetadata;
|
||||
pub use generated::proto::phonenumber::PhoneNumber;
|
||||
pub use generated::proto::phonenumber::phone_number::CountryCodeSource;
|
||||
pub use regexp_cache::InvalidRegexError;
|
||||
mod tests;
|
||||
|
||||
|
||||
@@ -1,3 +1,17 @@
|
||||
// Copyright (C) 2025 The Kashin Vladislav (Rust adaptation author)
|
||||
//
|
||||
// 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.
|
||||
|
||||
// std::borrow::Cow
|
||||
// std::option::Option
|
||||
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
// Copyright (C) 2009 The Libphonenumber Authors
|
||||
// Copyright (C) 2025 The Kashin Vladislav (Rust adaptation author)
|
||||
//
|
||||
// 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.
|
||||
|
||||
use strum::EnumIter;
|
||||
|
||||
/// INTERNATIONAL and NATIONAL formats are consistent with the definition
|
||||
@@ -65,7 +80,7 @@ pub enum MatchType {
|
||||
|
||||
/// Possible outcomes when testing if a PhoneNumber is possible.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum ValidNumberLenType {
|
||||
pub enum NumberLengthType {
|
||||
/// The number length matches that of valid numbers for this region.
|
||||
IsPossible,
|
||||
/// The number length matches that of local numbers for this region only
|
||||
|
||||
@@ -1,16 +1,31 @@
|
||||
// Copyright (C) 2009 The Libphonenumber Authors
|
||||
// Copyright (C) 2025 The Kashin Vladislav (Rust adaptation author)
|
||||
//
|
||||
// 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.
|
||||
|
||||
use std::num::ParseIntError;
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::regexp_cache::ErrorInvalidRegex;
|
||||
use crate::regexp_cache::InvalidRegexError;
|
||||
|
||||
#[derive(Debug, PartialEq, Error)]
|
||||
pub enum InternalLogicError {
|
||||
#[error("{0}")]
|
||||
InvalidRegexError(#[from] ErrorInvalidRegex),
|
||||
InvalidRegex(#[from] InvalidRegexError),
|
||||
|
||||
#[error("{0}")]
|
||||
InvalidMetadataForValidRegionError(#[from] InvalidMetadataForValidRegionError)
|
||||
InvalidMetadataForValidRegion(#[from] InvalidMetadataForValidRegionError)
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Error)]
|
||||
@@ -18,9 +33,9 @@ pub enum ParseError {
|
||||
// Removed as OK variant
|
||||
// NoParsingError,
|
||||
#[error("Invalid country code")]
|
||||
InvalidCountryCodeError, // INVALID_COUNTRY_CODE in the java version.
|
||||
#[error("Not a number")]
|
||||
NotANumber,
|
||||
InvalidCountryCode, // INVALID_COUNTRY_CODE in the java version.
|
||||
#[error("Not a number: {0}")]
|
||||
NotANumber(#[from] NotANumberError),
|
||||
#[error("Too short after idd")]
|
||||
TooShortAfterIdd,
|
||||
#[error("Too short Nsn")]
|
||||
@@ -28,11 +43,19 @@ pub enum ParseError {
|
||||
#[error("Too long nsn")]
|
||||
TooLongNsn, // TOO_LONG in the java version.
|
||||
#[error("{0}")]
|
||||
InvalidRegexError(#[from] ErrorInvalidRegex),
|
||||
InvalidRegex(#[from] InvalidRegexError),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Error)]
|
||||
pub enum NotANumberError {
|
||||
#[error("Number not matched a valid number pattern")]
|
||||
NotMatchedValidNumberPattern,
|
||||
#[error("Invalid phone context")]
|
||||
InvalidPhoneContext,
|
||||
#[error("{0}")]
|
||||
ParseNumberAsIntError(#[from] ParseIntError),
|
||||
FailedToParseNumberAsInt(#[from] ParseIntError),
|
||||
#[error("{0}")]
|
||||
ExtractNumberError(#[from] ExtractNumberError),
|
||||
FailedToExtractNumber(#[from] ExtractNumberError),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Error)]
|
||||
@@ -43,18 +66,24 @@ pub enum ExtractNumberError {
|
||||
NotANumber,
|
||||
}
|
||||
|
||||
impl From<ExtractNumberError> for ParseError {
|
||||
fn from(value: ExtractNumberError) -> Self {
|
||||
NotANumberError::FailedToExtractNumber(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Error)]
|
||||
pub enum GetExampleNumberError {
|
||||
#[error("Parse error: {0}")]
|
||||
ParseError(#[from] ParseError),
|
||||
FailedToParse(#[from] ParseError),
|
||||
#[error("{0}")]
|
||||
InternalLogicError(#[from] InternalLogicError),
|
||||
Internal(#[from] InternalLogicError),
|
||||
#[error("No example number")]
|
||||
NoExampleNumberError,
|
||||
NoExampleNumber,
|
||||
#[error("Could not get number")]
|
||||
CouldNotGetNumberError,
|
||||
CouldNotGetNumber,
|
||||
#[error("Invalid metadata")]
|
||||
InvalidMetadataError
|
||||
InvalidMetadata
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +97,7 @@ pub struct InvalidMetadataForValidRegionError;
|
||||
|
||||
/// Possible outcomes when testing if a PhoneNumber is possible.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Error)]
|
||||
pub enum ValidationResultErr {
|
||||
pub enum ValidationError {
|
||||
/// The number has an invalid country calling code.
|
||||
#[error("The number has an invalid country calling code")]
|
||||
InvalidCountryCode,
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
pub mod metadata;
|
||||
pub mod test_metadata;
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
// Copyright (C) 2009 The Libphonenumber Authors
|
||||
// Copyright (C) 2025 The Kashin Vladislav (Rust adaptation author)
|
||||
//
|
||||
// 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.
|
||||
|
||||
|
||||
// The minimum and maximum length of the national significant number.
|
||||
pub const MIN_LENGTH_FOR_NSN: usize = 2;
|
||||
// The ITU says the maximum length should be 15, but we have found longer
|
||||
@@ -28,7 +44,7 @@ pub const VALID_PUNCTUATION: &'static str = "-x\
|
||||
pub const CAPTURE_UP_TO_SECOND_NUMBER_START: &'static str = r"(.*)[\\/] *x";
|
||||
|
||||
|
||||
pub const REGION_CODE_FOR_NON_GEO_ENTITY: &'static str = "0001";
|
||||
pub const REGION_CODE_FOR_NON_GEO_ENTITY: &'static str = "001";
|
||||
|
||||
pub const PLUS_SIGN: &'static str = "+";
|
||||
pub const STAR_SIGN: &'static str = "*";
|
||||
@@ -50,11 +66,11 @@ pub const VALID_ALPHA_INCL_UPPERCASE: &'static str = "A-Za-z";
|
||||
// prefix. This can be overridden by region-specific preferences.
|
||||
pub const DEFAULT_EXTN_PREFIX: &'static str = " ext. ";
|
||||
|
||||
pub const POSSIBLE_SEPARATORS_BETWEEN_NUMBER_AND_EXT_LABEL: &'static str = "0001";
|
||||
pub const POSSIBLE_SEPARATORS_BETWEEN_NUMBER_AND_EXT_LABEL: &'static str = "[ \u{00A0}\\t,]*";
|
||||
|
||||
// Optional full stop (.) or colon, followed by zero or more
|
||||
// spaces/tabs/commas.
|
||||
pub const POSSIBLE_CHARS_AFTER_EXT_LABEL: &'static str = "[ \u{00A0}\\t,]*";
|
||||
pub const OPTIONAL_EXT_SUFFIX: &'static str = "[:\\.\u{FF0E}]?[ \u{00A0}\\t,-]*";
|
||||
pub const POSSIBLE_CHARS_AFTER_EXT_LABEL: &'static str = "[:\\.\u{FF0E}]?[ \u{00A0}\\t,-]*";
|
||||
pub const OPTIONAL_EXT_SUFFIX: &'static str = "#?";
|
||||
|
||||
pub const NANPA_COUNTRY_CODE: i32 = 1;
|
||||
@@ -1,3 +0,0 @@
|
||||
mod helper_constants;
|
||||
|
||||
pub(super) use helper_constants::{*};
|
||||
@@ -1,18 +1,36 @@
|
||||
// Copyright (C) 2009 The Libphonenumber Authors
|
||||
// Copyright (C) 2025 The Kashin Vladislav (Rust adaptation author)
|
||||
//
|
||||
// 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.
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use protobuf::Message;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use crate::{
|
||||
interfaces::MatcherApi, phonenumberutil::generated::metadata::METADATA, proto_gen::{
|
||||
phonemetadata::{PhoneMetadata, PhoneMetadataCollection, PhoneNumberDesc},
|
||||
interfaces::MatcherApi, generated::metadata::METADATA,
|
||||
generated::proto::{
|
||||
phonemetadata::{
|
||||
PhoneMetadata, PhoneMetadataCollection, PhoneNumberDesc
|
||||
},
|
||||
phonenumber::PhoneNumber,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
use super::{
|
||||
PhoneNumberFormat, PhoneNumberType, ValidNumberLenType,
|
||||
errors::ValidationResultErr,
|
||||
enums::{PhoneNumberFormat, PhoneNumberType, NumberLengthType},
|
||||
errors::ValidationError,
|
||||
helper_constants::{
|
||||
OPTIONAL_EXT_SUFFIX, PLUS_SIGN, POSSIBLE_CHARS_AFTER_EXT_LABEL,
|
||||
POSSIBLE_SEPARATORS_BETWEEN_NUMBER_AND_EXT_LABEL, RFC3966_EXTN_PREFIX, RFC3966_PREFIX,
|
||||
@@ -342,7 +360,7 @@ pub fn test_number_length(
|
||||
phone_number: &str,
|
||||
phone_metadata: &PhoneMetadata,
|
||||
phone_number_type: PhoneNumberType,
|
||||
) -> Result<ValidNumberLenType, ValidationResultErr> {
|
||||
) -> Result<NumberLengthType, ValidationError> {
|
||||
let desc_for_type = get_number_desc_by_type(phone_metadata, phone_number_type);
|
||||
// There should always be "possibleLengths" set for every element. This is
|
||||
// declared in the XML schema which is verified by
|
||||
@@ -394,31 +412,31 @@ pub fn test_number_length(
|
||||
// If the type is not suported at all (indicated by the possible lengths
|
||||
// containing -1 at this point) we return invalid length.
|
||||
if *possible_lengths.first().unwrap_or(&-1) == -1 {
|
||||
return Err(ValidationResultErr::InvalidLength);
|
||||
return Err(ValidationError::InvalidLength);
|
||||
}
|
||||
|
||||
let actual_length = phone_number.len() as i32;
|
||||
// This is safe because there is never an overlap beween the possible lengths
|
||||
// and the local-only lengths; this is checked at build time.
|
||||
if local_lengths.contains(&actual_length) {
|
||||
return Ok(ValidNumberLenType::IsPossibleLocalOnly);
|
||||
return Ok(NumberLengthType::IsPossibleLocalOnly);
|
||||
}
|
||||
|
||||
// here we can unwrap safe
|
||||
let minimum_length = possible_lengths[0];
|
||||
|
||||
if minimum_length == actual_length {
|
||||
return Ok(ValidNumberLenType::IsPossible);
|
||||
return Ok(NumberLengthType::IsPossible);
|
||||
} else if minimum_length > actual_length {
|
||||
return Err(ValidationResultErr::TooShort);
|
||||
return Err(ValidationError::TooShort);
|
||||
} else if possible_lengths[possible_lengths.len() - 1] < actual_length {
|
||||
return Err(ValidationResultErr::TooLong);
|
||||
return Err(ValidationError::TooLong);
|
||||
}
|
||||
// We skip the first element; we've already checked it.
|
||||
return if possible_lengths[1..].contains(&actual_length) {
|
||||
Ok(ValidNumberLenType::IsPossible)
|
||||
Ok(NumberLengthType::IsPossible)
|
||||
} else {
|
||||
Err(ValidationResultErr::InvalidLength)
|
||||
Err(ValidationError::InvalidLength)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -428,7 +446,7 @@ pub fn test_number_length(
|
||||
pub fn test_number_length_with_unknown_type(
|
||||
phone_number: &str,
|
||||
phone_metadata: &PhoneMetadata,
|
||||
) -> Result<ValidNumberLenType, ValidationResultErr> {
|
||||
) -> Result<NumberLengthType, ValidationError> {
|
||||
return test_number_length(phone_number, phone_metadata, PhoneNumberType::Unknown);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,22 @@
|
||||
// Copyright (C) 2009 The Libphonenumber Authors
|
||||
// Copyright (C) 2025 The Kashin Vladislav (Rust adaptation author)
|
||||
//
|
||||
// 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.
|
||||
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
||||
use crate::proto_gen::phonenumber::phone_number::CountryCodeSource;
|
||||
use crate::CountryCodeSource;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PhoneNumberWithCountryCodeSource<'a> {
|
||||
@@ -13,19 +29,3 @@ impl<'a> PhoneNumberWithCountryCodeSource<'a> {
|
||||
Self { phone_number, country_code_source }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PhoneNumberAndCarrierCode<'a> {
|
||||
pub carrier_code: Option<&'a str>,
|
||||
pub phone_number: Cow<'a, str>
|
||||
}
|
||||
|
||||
impl<'a> PhoneNumberAndCarrierCode<'a> {
|
||||
pub fn new<B: Into<Cow<'a, str>>>(carrier_code: Option<&'a str>, phone_number: B) -> Self {
|
||||
Self { carrier_code, phone_number: phone_number.into() }
|
||||
}
|
||||
|
||||
pub fn new_phone<B: Into<Cow<'a, str>>>(phone_number: B) -> Self {
|
||||
Self { carrier_code: None, phone_number: phone_number.into() }
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,18 @@
|
||||
// Copyright (C) 2009 The Libphonenumber Authors
|
||||
// Copyright (C) 2025 The Kashin Vladislav (Rust adaptation author)
|
||||
//
|
||||
// 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.
|
||||
|
||||
mod helper_constants;
|
||||
mod helper_functions;
|
||||
pub mod errors;
|
||||
@@ -5,14 +20,12 @@ pub mod enums;
|
||||
pub mod phonenumberutil;
|
||||
mod phone_number_regexps_and_mappings;
|
||||
pub(self) mod helper_types;
|
||||
pub(self) mod comparisons;
|
||||
pub(crate) mod generated;
|
||||
|
||||
use std::sync::LazyLock;
|
||||
|
||||
pub use enums::{MatchType, PhoneNumberFormat, PhoneNumberType, ValidNumberLenType};
|
||||
use crate::phonenumberutil::phonenumberutil::PhoneNumberUtil;
|
||||
|
||||
/// Singleton instance of phone number util for general use
|
||||
pub static PHONE_NUMBER_UTIL: LazyLock<PhoneNumberUtil> = LazyLock::new(|| {
|
||||
PhoneNumberUtil::new()
|
||||
});
|
||||
@@ -1,3 +1,19 @@
|
||||
// Copyright (C) 2009 The Libphonenumber Authors
|
||||
// Copyright (C) 2025 The Kashin Vladislav (Rust adaptation author)
|
||||
//
|
||||
// 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.
|
||||
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use regex::Regex;
|
||||
@@ -8,6 +24,7 @@ use crate::{phonenumberutil::{helper_constants::{
|
||||
VALID_PUNCTUATION
|
||||
}, helper_functions::create_extn_pattern}, regexp_cache::RegexCache};
|
||||
|
||||
#[allow(unused)]
|
||||
pub(super) struct PhoneNumberRegExpsAndMappings {
|
||||
/// Regular expression of viable phone numbers. This is location independent.
|
||||
/// Checks we have at least three leading digits, and only valid punctuation,
|
||||
@@ -307,13 +324,12 @@ impl PhoneNumberRegExpsAndMappings {
|
||||
separator_pattern: Regex::new(&format!("[{}]+", VALID_PUNCTUATION)).unwrap(),
|
||||
extn_patterns_for_matching: create_extn_pattern(false),
|
||||
extn_pattern: Regex::new(&format!("(?i)(?:{})$", &extn_patterns_for_parsing)).unwrap(),
|
||||
valid_phone_number_pattern: Regex::new(&format!("(?i){}(?:{})?",
|
||||
valid_phone_number_pattern: Regex::new(&format!("(?i)^(?:{})(?:{})?$",
|
||||
&valid_phone_number,
|
||||
extn_patterns_for_parsing
|
||||
)).unwrap(),
|
||||
valid_alpha_phone_pattern: Regex::new(&format!("(?i)(?:.*?[{}]){{3}}",
|
||||
VALID_ALPHA
|
||||
&extn_patterns_for_parsing
|
||||
)).unwrap(),
|
||||
// from java
|
||||
valid_alpha_phone_pattern: Regex::new("(?:.*?[A-Za-z]){3}.*").unwrap(),
|
||||
// The first_group_capturing_pattern was originally set to $1 but there
|
||||
// are some countries for which the first group is not used in the
|
||||
// national pattern (e.g. Argentina) so the $1 group does not match
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,23 @@
|
||||
// Copyright (C) 2009 The Libphonenumber Authors
|
||||
// Copyright (C) 2025 The Kashin Vladislav (Rust adaptation author)
|
||||
//
|
||||
// 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.
|
||||
|
||||
|
||||
use log::{error};
|
||||
use super::regex_util::{RegexFullMatch, RegexConsume};
|
||||
|
||||
use crate::{interfaces, proto_gen::phonemetadata::PhoneNumberDesc, regexp_cache::{ErrorInvalidRegex, RegexCache}};
|
||||
use crate::{interfaces, generated::proto::phonemetadata::PhoneNumberDesc, regexp_cache::{InvalidRegexError, RegexCache}};
|
||||
|
||||
pub struct RegexBasedMatcher {
|
||||
cache: RegexCache,
|
||||
@@ -16,7 +32,7 @@ impl RegexBasedMatcher {
|
||||
&self, phone_number: &str,
|
||||
number_pattern: &str,
|
||||
allow_prefix_match: bool
|
||||
) -> Result<bool, ErrorInvalidRegex> {
|
||||
) -> Result<bool, InvalidRegexError> {
|
||||
let regexp = self.cache.get_regex(number_pattern)?;
|
||||
|
||||
// find first occurrence
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
// Copyright (C) 2009 The Libphonenumber Authors
|
||||
// Copyright (C) 2025 The Kashin Vladislav (Rust adaptation author)
|
||||
//
|
||||
// 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.
|
||||
|
||||
use regex::{Captures, Match, Regex};
|
||||
|
||||
pub trait RegexFullMatch {
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
// Copyright (C) 2009 The Libphonenumber Authors
|
||||
// Copyright (C) 2025 The Kashin Vladislav (Rust adaptation author)
|
||||
//
|
||||
// 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.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use dashmap::DashMap;
|
||||
@@ -5,7 +20,7 @@ use thiserror::Error;
|
||||
|
||||
#[derive(Debug, PartialEq, Error)]
|
||||
#[error("An error occurred while trying to create regex: {0}")]
|
||||
pub struct ErrorInvalidRegex(#[from] regex::Error);
|
||||
pub struct InvalidRegexError(#[from] regex::Error);
|
||||
|
||||
pub struct RegexCache {
|
||||
cache: DashMap<String, Arc<regex::Regex>>
|
||||
@@ -19,7 +34,7 @@ impl RegexCache {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_regex(&self, pattern: &str) -> Result<Arc<regex::Regex>, ErrorInvalidRegex> {
|
||||
pub fn get_regex(&self, pattern: &str) -> Result<Arc<regex::Regex>, InvalidRegexError> {
|
||||
if let Some(regex) = self.cache.get(pattern) {
|
||||
Ok(regex.value().clone())
|
||||
} else {
|
||||
|
||||
28
src/region_code.rs
Normal file
28
src/region_code.rs
Normal file
@@ -0,0 +1,28 @@
|
||||
// Copyright (C) 2009 The Libphonenumber Authors
|
||||
// Copyright (C) 2025 The Kashin Vladislav (Rust adaptation author)
|
||||
//
|
||||
// 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.
|
||||
|
||||
pub struct RegionCode {
|
||||
}
|
||||
|
||||
impl RegionCode {
|
||||
/// Returns a region code string representing the "unknown" region.
|
||||
pub fn get_unknown() -> &'static str {
|
||||
return Self::zz();
|
||||
}
|
||||
|
||||
pub fn zz() -> &'static str {
|
||||
return "ZZ";
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,17 @@
|
||||
// Copyright (C) 2025 The Kashin Vladislav (Rust adaptation author)
|
||||
//
|
||||
// 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.
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
||||
/// Strips prefix of given string Cow. Returns option with `Some` if
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
mod tests;
|
||||
#[cfg(test)]
|
||||
mod phonenumberutil_tests;
|
||||
pub(self) mod region_code;
|
||||
3235
src/tests/phonenumberutil_tests.rs
Normal file
3235
src/tests/phonenumberutil_tests.rs
Normal file
File diff suppressed because it is too large
Load Diff
161
src/tests/region_code.rs
Normal file
161
src/tests/region_code.rs
Normal file
@@ -0,0 +1,161 @@
|
||||
pub struct RegionCode {}
|
||||
|
||||
#[allow(unused)]
|
||||
impl RegionCode {
|
||||
pub fn ad() -> &'static str {
|
||||
"AD"
|
||||
}
|
||||
|
||||
pub fn ae() -> &'static str {
|
||||
"AE"
|
||||
}
|
||||
|
||||
pub fn am() -> &'static str {
|
||||
"AM"
|
||||
}
|
||||
|
||||
pub fn ao() -> &'static str {
|
||||
"AO"
|
||||
}
|
||||
|
||||
pub fn aq() -> &'static str {
|
||||
"AQ"
|
||||
}
|
||||
|
||||
pub fn ar() -> &'static str {
|
||||
"AR"
|
||||
}
|
||||
|
||||
pub fn au() -> &'static str {
|
||||
"AU"
|
||||
}
|
||||
|
||||
pub fn bb() -> &'static str {
|
||||
"BB"
|
||||
}
|
||||
|
||||
pub fn br() -> &'static str {
|
||||
"BR"
|
||||
}
|
||||
|
||||
pub fn bs() -> &'static str {
|
||||
"BS"
|
||||
}
|
||||
|
||||
pub fn by() -> &'static str {
|
||||
"BY"
|
||||
}
|
||||
|
||||
pub fn ca() -> &'static str {
|
||||
"CA"
|
||||
}
|
||||
|
||||
pub fn ch() -> &'static str {
|
||||
"CH"
|
||||
}
|
||||
|
||||
pub fn cl() -> &'static str {
|
||||
"CL"
|
||||
}
|
||||
|
||||
pub fn cn() -> &'static str {
|
||||
"CN"
|
||||
}
|
||||
|
||||
pub fn co() -> &'static str {
|
||||
"CO"
|
||||
}
|
||||
|
||||
pub fn cs() -> &'static str {
|
||||
"CS"
|
||||
}
|
||||
|
||||
pub fn cx() -> &'static str {
|
||||
"CX"
|
||||
}
|
||||
|
||||
pub fn de() -> &'static str {
|
||||
"DE"
|
||||
}
|
||||
|
||||
pub fn fr() -> &'static str {
|
||||
"FR"
|
||||
}
|
||||
|
||||
pub fn gb() -> &'static str {
|
||||
"GB"
|
||||
}
|
||||
|
||||
pub fn hu() -> &'static str {
|
||||
"HU"
|
||||
}
|
||||
|
||||
pub fn it() -> &'static str {
|
||||
"IT"
|
||||
}
|
||||
|
||||
pub fn jp() -> &'static str {
|
||||
"JP"
|
||||
}
|
||||
|
||||
pub fn kr() -> &'static str {
|
||||
"KR"
|
||||
}
|
||||
|
||||
pub fn mx() -> &'static str {
|
||||
"MX"
|
||||
}
|
||||
|
||||
pub fn nz() -> &'static str {
|
||||
"NZ"
|
||||
}
|
||||
|
||||
pub fn pl() -> &'static str {
|
||||
"PL"
|
||||
}
|
||||
|
||||
pub fn re() -> &'static str {
|
||||
"RE"
|
||||
}
|
||||
|
||||
pub fn ru() -> &'static str {
|
||||
"RU"
|
||||
}
|
||||
|
||||
pub fn se() -> &'static str {
|
||||
"SE"
|
||||
}
|
||||
|
||||
pub fn sg() -> &'static str {
|
||||
"SG"
|
||||
}
|
||||
|
||||
pub fn un001() -> &'static str {
|
||||
"001"
|
||||
}
|
||||
|
||||
pub fn us() -> &'static str {
|
||||
"US"
|
||||
}
|
||||
|
||||
pub fn uz() -> &'static str {
|
||||
"UZ"
|
||||
}
|
||||
|
||||
pub fn yt() -> &'static str {
|
||||
"YT"
|
||||
}
|
||||
|
||||
pub fn zw() -> &'static str {
|
||||
"ZW"
|
||||
}
|
||||
|
||||
/// s a region code string representing the "unknown" region.
|
||||
pub fn get_unknown() -> &'static str {
|
||||
Self::zz()
|
||||
}
|
||||
|
||||
pub fn zz() -> &'static str {
|
||||
"ZZ"
|
||||
}
|
||||
}
|
||||
@@ -1,506 +0,0 @@
|
||||
#[cfg(test)]
|
||||
use std::{cell::LazyCell, sync::LazyLock};
|
||||
use std::{collections::{BTreeSet, HashSet}};
|
||||
|
||||
use dec_from_char::DecimalExtended;
|
||||
#[cfg(test)]
|
||||
use env_logger::Logger;
|
||||
use log::trace;
|
||||
use protobuf::Message;
|
||||
|
||||
use crate::{errors::ParseError, phonemetadata::PhoneMetadataCollection, phonenumber::PhoneNumber, PhoneNumberUtil};
|
||||
|
||||
use crate::phonenumberutil::generated::test_metadata::TEST_METADATA;
|
||||
|
||||
|
||||
|
||||
// This setup function simulates getting the PhoneNumberUtil instance for each test.
|
||||
fn get_phone_util() -> PhoneNumberUtil {
|
||||
let metadata = PhoneMetadataCollection::parse_from_bytes(&TEST_METADATA)
|
||||
.expect("Metadata should be valid");
|
||||
// In a real scenario, this would likely return a singleton instance.
|
||||
return PhoneNumberUtil::new_for_metadata(metadata);
|
||||
}
|
||||
|
||||
// NOTE: To keep the translation focused on the test logic, the mock implementations
|
||||
// of the methods below are omitted. The translated tests call these methods as if
|
||||
// they are fully implemented in the Rust `phonenumbers` library.
|
||||
|
||||
// =====================================================================
|
||||
// Конец секции с моками
|
||||
// =====================================================================
|
||||
|
||||
#[test]
|
||||
fn contains_only_valid_digits() {
|
||||
// В оригинале это был protected-метод, но мы предполагаем, что он доступен.
|
||||
fn contains_only_valid_digits(s: &str) -> bool {
|
||||
// Mock implementation
|
||||
!s.chars().any(|c| !c.is_decimal_utf8() && c != '6')
|
||||
}
|
||||
assert!(contains_only_valid_digits(""));
|
||||
assert!(contains_only_valid_digits("2"));
|
||||
assert!(contains_only_valid_digits("25"));
|
||||
assert!(contains_only_valid_digits("6")); // "6"
|
||||
assert!(!contains_only_valid_digits("a"));
|
||||
assert!(!contains_only_valid_digits("2a"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interchange_invalid_codepoints() {
|
||||
colog::default_builder()
|
||||
.filter_level(log::LevelFilter::Trace)
|
||||
.init();
|
||||
|
||||
let phone_util = get_phone_util();
|
||||
let mut phone_number = PhoneNumber::new();
|
||||
|
||||
let valid_inputs = vec![
|
||||
"+44\u{2013}2087654321", // U+2013, EN DASH
|
||||
];
|
||||
for input in valid_inputs {
|
||||
assert_eq!(input, dec_from_char::normalize_decimals(input));
|
||||
assert!(phone_util.is_viable_phone_number(input));
|
||||
phone_util.parse(input, "GB").unwrap();
|
||||
|
||||
}
|
||||
|
||||
let invalid_inputs = vec![
|
||||
"+44\u{96}2087654321", // Invalid sequence
|
||||
"+44\u{0096}2087654321", // U+0096
|
||||
"+44\u{fffe}2087654321", // U+FFFE
|
||||
];
|
||||
for input in invalid_inputs {
|
||||
assert!(!phone_util.is_viable_phone_number(input));
|
||||
assert!(
|
||||
phone_util.parse(input, "GB").is_err_and(| err | matches!(err, ParseError::NotANumber))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_supported_regions() {
|
||||
let phone_util = get_phone_util();
|
||||
assert!(phone_util
|
||||
.get_supported_regions()
|
||||
.count() > 0
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_supported_global_network_calling_codes() {
|
||||
let phone_util = get_phone_util();
|
||||
let mut calling_codes = BTreeSet::<i32>::new();
|
||||
// phone_util.get_supported_global_network_calling_codes(&mut calling_codes);
|
||||
// assert!(!calling_codes.is_empty());
|
||||
// for &code in &calling_codes {
|
||||
// assert!(code > 0);
|
||||
// let mut region_code = String::new();
|
||||
// phone_util.get_region_code_for_country_code(code, &mut region_code);
|
||||
// assert_eq!(RegionCode::un001(), region_code);
|
||||
// }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_supported_calling_codes() {
|
||||
let phone_util = get_phone_util();
|
||||
let mut calling_codes = BTreeSet::<i32>::new();
|
||||
// phone_util.get_supported_calling_codes(&mut calling_codes);
|
||||
// assert!(!calling_codes.is_empty());
|
||||
// for &code in &calling_codes {
|
||||
// assert!(code > 0);
|
||||
// let mut region_code = String::new();
|
||||
// phone_util.get_region_code_for_country_code(code, &mut region_code);
|
||||
// assert_ne!(RegionCode::zz(), region_code);
|
||||
// }
|
||||
// let mut supported_global_network_calling_codes = BTreeSet::<i32>::new();
|
||||
// phone_util.get_supported_global_network_calling_codes(
|
||||
// &mut supported_global_network_calling_codes,
|
||||
// );
|
||||
// assert!(calling_codes.len() > supported_global_network_calling_codes.len());
|
||||
// assert!(calling_codes.contains(&979));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_supported_types_for_region() {
|
||||
let phone_util = get_phone_util();
|
||||
let mut types = HashSet::<PhoneNumber>::new();
|
||||
// phone_util.get_supported_types_for_region(RegionCode::br(), &mut types);
|
||||
// assert!(types.contains(&PhoneNumberType::FixedLine));
|
||||
// assert!(!types.contains(&PhoneNumberType::Mobile));
|
||||
// assert!(!types.contains(&PhoneNumberType::Unknown));
|
||||
|
||||
// types.clear();
|
||||
// phone_util.get_supported_types_for_region(RegionCode::us(), &mut types);
|
||||
// assert!(types.contains(&PhoneNumberType::FixedLine));
|
||||
// assert!(types.contains(&PhoneNumberType::Mobile));
|
||||
// assert!(!types.contains(&PhoneNumberType::FixedLineOrMobile));
|
||||
|
||||
// types.clear();
|
||||
// phone_util.get_supported_types_for_region(RegionCode::zz(), &mut types);
|
||||
// assert_eq!(0, types.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_supported_types_for_non_geo_entity() {
|
||||
let phone_util = get_phone_util();
|
||||
let mut types = HashSet::<PhoneNumber>::new();
|
||||
// phone_util.get_supported_types_for_non_geo_entity(999, &mut types);
|
||||
// assert_eq!(0, types.len());
|
||||
|
||||
// types.clear();
|
||||
// phone_util.get_supported_types_for_non_geo_entity(979, &mut types);
|
||||
// assert!(types.contains(&PhoneNumberType::PremiumRate));
|
||||
// assert!(!types.contains(&PhoneNumberType::Mobile));
|
||||
// assert!(!types.contains(&PhoneNumberType::Unknown));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_region_codes_for_country_calling_code() {
|
||||
let phone_util = get_phone_util();
|
||||
let mut regions = Vec::<String>::new();
|
||||
|
||||
// phone_util.get_region_codes_for_country_calling_code(1, &mut regions);
|
||||
// assert!(regions.contains(&RegionCode::us().to_string()));
|
||||
// assert!(regions.contains(&RegionCode::bs().to_string()));
|
||||
|
||||
// regions.clear();
|
||||
// phone_util.get_region_codes_for_country_calling_code(44, &mut regions);
|
||||
// assert!(regions.contains(&RegionCode::gb().to_string()));
|
||||
|
||||
// regions.clear();
|
||||
// phone_util.get_region_codes_for_country_calling_code(49, &mut regions);
|
||||
// assert!(regions.contains(&RegionCode::de().to_string()));
|
||||
|
||||
// regions.clear();
|
||||
// phone_util.get_region_codes_for_country_calling_code(800, &mut regions);
|
||||
// assert!(regions.contains(&RegionCode::un001().to_string()));
|
||||
|
||||
// regions.clear();
|
||||
// const K_INVALID_COUNTRY_CODE: i32 = 2;
|
||||
// phone_util.get_region_codes_for_country_calling_code(K_INVALID_COUNTRY_CODE, &mut regions);
|
||||
// assert!(regions.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_instance_load_us_metadata() {
|
||||
let phone_util = get_phone_util();
|
||||
// let metadata = phone_util.get_metadata_for_region(RegionCode::us()).unwrap();
|
||||
// assert_eq!("US", metadata.id());
|
||||
// assert_eq!(1, metadata.country_code());
|
||||
// assert_eq!("011", metadata.international_prefix());
|
||||
// assert!(metadata.has_national_prefix());
|
||||
// assert_eq!(2, metadata.number_format().len());
|
||||
// assert_eq!("(\\d{3})(\\d{3})(\\d{4})", metadata.number_format()[1].pattern());
|
||||
// assert_eq!("$1 $2 $3", metadata.number_format()[1].format());
|
||||
// assert_eq!("[13-689]\\d{9}|2[0-35-9]\\d{8}", metadata.general_desc().national_number_pattern());
|
||||
// assert_eq!("[13-689]\\d{9}|2[0-35-9]\\d{8}", metadata.fixed_line().national_number_pattern());
|
||||
// assert_eq!(1, metadata.general_desc().possible_length().len());
|
||||
// assert_eq!(10, metadata.general_desc().possible_length()[0]);
|
||||
// assert_eq!(0, metadata.toll_free().possible_length().len());
|
||||
// assert_eq!("900\\d{7}", metadata.premium_rate().national_number_pattern());
|
||||
// assert!(!metadata.shared_cost().has_national_number_pattern());
|
||||
}
|
||||
|
||||
// ... Другие тесты, связанные с метаданными, могут быть переведены аналогично ...
|
||||
|
||||
#[test]
|
||||
fn get_national_significant_number() {
|
||||
let phone_util = get_phone_util();
|
||||
let mut number = PhoneNumber::new();
|
||||
number.set_country_code(1);
|
||||
number.set_national_number(6502530000);
|
||||
let mut national_significant_number = String::new();
|
||||
// phone_util.get_national_significant_number(&number, &mut national_significant_number);
|
||||
// assert_eq!("6502530000", national_significant_number);
|
||||
|
||||
national_significant_number.clear();
|
||||
number.set_country_code(39);
|
||||
number.set_national_number(312345678);
|
||||
// phone_util.get_national_significant_number(&number, &mut national_significant_number);
|
||||
// assert_eq!("312345678", national_significant_number);
|
||||
|
||||
national_significant_number.clear();
|
||||
number.set_country_code(39);
|
||||
number.set_national_number(236618300);
|
||||
number.set_italian_leading_zero(true);
|
||||
// phone_util.get_national_significant_number(&number, &mut national_significant_number);
|
||||
// assert_eq!("0236618300", national_significant_number);
|
||||
|
||||
national_significant_number.clear();
|
||||
number.clear();
|
||||
number.set_country_code(800);
|
||||
number.set_national_number(12345678);
|
||||
// phone_util.get_national_significant_number(&number, &mut national_significant_number);
|
||||
// assert_eq!("12345678", national_significant_number);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_national_significant_number_many_leading_zeros() {
|
||||
let phone_util = get_phone_util();
|
||||
let mut number = PhoneNumber::new();
|
||||
number.set_country_code(1);
|
||||
number.set_national_number(650);
|
||||
number.set_italian_leading_zero(true);
|
||||
number.set_number_of_leading_zeros(2);
|
||||
let mut national_significant_number = String::new();
|
||||
// phone_util.get_national_significant_number(&number, &mut national_significant_number);
|
||||
// assert_eq!("00650", national_significant_number);
|
||||
|
||||
number.set_number_of_leading_zeros(-3);
|
||||
national_significant_number.clear();
|
||||
// phone_util.get_national_significant_number(&number, &mut national_significant_number);
|
||||
// assert_eq!("650", national_significant_number);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_example_number() {
|
||||
let phone_util = get_phone_util();
|
||||
let mut de_number = PhoneNumber::new();
|
||||
de_number.set_country_code(49);
|
||||
de_number.set_national_number(30123456);
|
||||
let mut test_number = PhoneNumber::new();
|
||||
// let success = phone_util.get_example_number(RegionCode::de(), &mut test_number);
|
||||
// assert!(success);
|
||||
// assert_eq!(de_number, test_number);
|
||||
|
||||
// let success = phone_util.get_example_number_for_type(
|
||||
// RegionCode::de(), PhoneNumberType::FixedLine, &mut test_number);
|
||||
// assert!(success);
|
||||
// assert_eq!(de_number, test_number);
|
||||
|
||||
// let success = phone_util.get_example_number_for_type(
|
||||
// RegionCode::de(), PhoneNumberType::FixedLineOrMobile, &mut test_number);
|
||||
// assert_eq!(de_number, test_number);
|
||||
|
||||
// let success = phone_util.get_example_number_for_type(
|
||||
// RegionCode::de(), PhoneNumberType::Mobile, &mut test_number);
|
||||
|
||||
// test_number.clear();
|
||||
// let success = phone_util.get_example_number_for_type(
|
||||
// RegionCode::us(), PhoneNumberType::Voicemail, &mut test_number);
|
||||
// assert!(!success);
|
||||
// assert_eq!(PhoneNumber::new(), test_number);
|
||||
|
||||
// let success = phone_util.get_example_number_for_type(
|
||||
// RegionCode::us(), PhoneNumberType::FixedLine, &mut test_number);
|
||||
// assert!(success);
|
||||
// assert_ne!(PhoneNumber::new(), test_number);
|
||||
|
||||
// let success = phone_util.get_example_number_for_type(
|
||||
// RegionCode::us(), PhoneNumberType::Mobile, &mut test_number);
|
||||
// assert!(success);
|
||||
// assert_ne!(PhoneNumber::new(), test_number);
|
||||
|
||||
// test_number.clear();
|
||||
// assert!(!phone_util.get_example_number_for_type(
|
||||
// RegionCode::cs(), PhoneNumberType::Mobile, &mut test_number));
|
||||
// assert_eq!(PhoneNumber::new(), test_number);
|
||||
|
||||
// assert!(!phone_util.get_example_number(RegionCode::un001(), &mut test_number));
|
||||
}
|
||||
|
||||
// ... и так далее для каждого теста ...
|
||||
|
||||
#[test]
|
||||
fn format_us_number() {
|
||||
let phone_util = get_phone_util();
|
||||
let mut test_number = PhoneNumber::new();
|
||||
let mut formatted_number = String::new();
|
||||
test_number.set_country_code(1);
|
||||
test_number.set_national_number(6502530000);
|
||||
// phone_util.format(&test_number, PhoneNumberFormat::National, &mut formatted_number);
|
||||
// assert_eq!("650 253 0000", formatted_number);
|
||||
// phone_util.format(&test_number, PhoneNumberFormat::International, &mut formatted_number);
|
||||
// assert_eq!("+1 650 253 0000", formatted_number);
|
||||
|
||||
// ... (остальные проверки из этого теста) ...
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn format_gb_number() {
|
||||
let phone_util = get_phone_util();
|
||||
let mut test_number = PhoneNumber::new();
|
||||
let mut formatted_number = String::new();
|
||||
test_number.set_country_code(44);
|
||||
test_number.set_national_number(2087389353);
|
||||
// phone_util.format(&test_number, PhoneNumberFormat::National, &mut formatted_number);
|
||||
// assert_eq!("(020) 8738 9353", formatted_number);
|
||||
// phone_util.format(&test_number, PhoneNumberFormat::International, &mut formatted_number);
|
||||
// assert_eq!("+44 20 8738 9353", formatted_number);
|
||||
|
||||
test_number.set_national_number(7912345678);
|
||||
// phone_util.format(&test_number, PhoneNumberFormat::National, &mut formatted_number);
|
||||
// assert_eq!("(07912) 345 678", formatted_number);
|
||||
// phone_util.format(&test_number, PhoneNumberFormat::International, &mut formatted_number);
|
||||
// assert_eq!("+44 7912 345 678", formatted_number);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_valid_number() {
|
||||
let phone_util = get_phone_util();
|
||||
let mut us_number = PhoneNumber::new();
|
||||
us_number.set_country_code(1);
|
||||
us_number.set_national_number(6502530000);
|
||||
// assert!(phone_util.is_valid_number(&us_number));
|
||||
|
||||
let mut it_number = PhoneNumber::new();
|
||||
it_number.set_country_code(39);
|
||||
it_number.set_national_number(236618300);
|
||||
it_number.set_italian_leading_zero(true);
|
||||
// assert!(phone_util.is_valid_number(&it_number));
|
||||
|
||||
// ... (остальные проверки) ...
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_not_valid_number() {
|
||||
let phone_util = get_phone_util();
|
||||
let mut us_number = PhoneNumber::new();
|
||||
us_number.set_country_code(1);
|
||||
us_number.set_national_number(2530000);
|
||||
// assert!(!phone_util.is_valid_number(&us_number));
|
||||
|
||||
// ... (остальные проверки) ...
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_possible_number() {
|
||||
let phone_util = get_phone_util();
|
||||
let mut number = PhoneNumber::new();
|
||||
number.set_country_code(1);
|
||||
number.set_national_number(6502530000);
|
||||
// assert!(phone_util.is_possible_number(&number));
|
||||
|
||||
// assert!(phone_util.is_possible_number_for_string("+1 650 253 0000", RegionCode::us()));
|
||||
// assert!(phone_util.is_possible_number_for_string("253-0000", RegionCode::us()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_possible_number_with_reason() {
|
||||
let phone_util = get_phone_util();
|
||||
let mut number = PhoneNumber::new();
|
||||
number.set_country_code(1);
|
||||
number.set_national_number(6502530000);
|
||||
// assert_eq!(ValidationResult::IsPossible, phone_util.is_possible_number_with_reason(&number));
|
||||
|
||||
number.set_national_number(2530000);
|
||||
// assert_eq!(ValidationResult::IsPossibleLocalOnly, phone_util.is_possible_number_with_reason(&number));
|
||||
|
||||
number.set_country_code(0);
|
||||
// assert_eq!(ValidationResult::InvalidCountryCode, phone_util.is_possible_number_with_reason(&number));
|
||||
|
||||
number.set_country_code(1);
|
||||
number.set_national_number(253000);
|
||||
// assert_eq!(ValidationResult::TooShort, phone_util.is_possible_number_with_reason(&number));
|
||||
|
||||
number.set_national_number(65025300000);
|
||||
// assert_eq!(ValidationResult::TooLong, phone_util.is_possible_number_with_reason(&number));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn normalise_remove_punctuation() {
|
||||
let phone_util = get_phone_util();
|
||||
let mut input_number = "034-56&+#2\u{ad}34".to_string();
|
||||
// phone_util.normalize(&mut input_number);
|
||||
let expected_output = "03456234";
|
||||
// assert_eq!(expected_output, input_number, "Conversion did not correctly remove punctuation");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn normalise_replace_alpha_characters() {
|
||||
let phone_util = get_phone_util();
|
||||
let mut input_number = "034-I-am-HUNGRY".to_string();
|
||||
// phone_util.normalize(&mut input_number);
|
||||
let expected_output = "034426486479";
|
||||
// assert_eq!(expected_output, input_number, "Conversion did not correctly replace alpha characters");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn maybe_strip_extension() {
|
||||
let phone_util = get_phone_util();
|
||||
let mut number = "1234576 ext. 1234".to_string();
|
||||
let mut extension = String::new();
|
||||
let expected_extension = "1234";
|
||||
let stripped_number = "1234576";
|
||||
// assert!(phone_util.maybe_strip_extension(&mut number, &mut extension));
|
||||
// assert_eq!(stripped_number, number);
|
||||
// assert_eq!(expected_extension, extension);
|
||||
|
||||
// ... (остальные проверки) ...
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_national_number() {
|
||||
let phone_util = get_phone_util();
|
||||
let mut nz_number = PhoneNumber::new();
|
||||
nz_number.set_country_code(64);
|
||||
nz_number.set_national_number(33316005);
|
||||
let mut test_number = PhoneNumber::new();
|
||||
|
||||
// assert_eq!(ErrorType::NoParsingError, phone_util.parse("033316005", RegionCode::nz(), &mut test_number));
|
||||
// assert_eq!(nz_number, test_number);
|
||||
// assert!(!test_number.has_country_code_source());
|
||||
// assert_eq!(CountryCodeSource::Unspecified, test_number.country_code_source());
|
||||
|
||||
// assert_eq!(ErrorType::NoParsingError, phone_util.parse("33316005", RegionCode::nz(), &mut test_number));
|
||||
// assert_eq!(nz_number, test_number);
|
||||
|
||||
// ... (остальные проверки) ...
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn failed_parse_on_invalid_numbers() {
|
||||
let phone_util = get_phone_util();
|
||||
let mut test_number = PhoneNumber::new();
|
||||
// assert_eq!(ErrorType::NotANumber, phone_util.parse("This is not a phone number", RegionCode::nz(), &mut test_number));
|
||||
// assert_eq!(PhoneNumber::new(), test_number);
|
||||
|
||||
// assert_eq!(ErrorType::TooLongNsn, phone_util.parse("01495 72553301873 810104", RegionCode::gb(), &mut test_number));
|
||||
// assert_eq!(PhoneNumber::new(), test_number);
|
||||
|
||||
// assert_eq!(ErrorType::InvalidCountryCodeError, phone_util.parse("123 456 7890", RegionCode::get_unknown(), &mut test_number));
|
||||
// assert_eq!(PhoneNumber::new(), test_number);
|
||||
|
||||
// ... (остальные проверки) ...
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_extensions() {
|
||||
let phone_util = get_phone_util();
|
||||
let mut nz_number = PhoneNumber::new();
|
||||
nz_number.set_country_code(64);
|
||||
nz_number.set_national_number(33316005);
|
||||
nz_number.set_extension("3456".to_owned());
|
||||
let mut test_number = PhoneNumber::new();
|
||||
|
||||
// assert_eq!(ErrorType::NoParsingError, phone_util.parse("03 331 6005 ext 3456", RegionCode::nz(), &mut test_number));
|
||||
// assert_eq!(nz_number, test_number);
|
||||
|
||||
// assert_eq!(ErrorType::NoParsingError, phone_util.parse("03 331 6005 #3456", RegionCode::nz(), &mut test_number));
|
||||
// assert_eq!(nz_number, test_number);
|
||||
|
||||
// ... (остальные проверки) ...
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_be_internationally_dialled() {
|
||||
let phone_util = get_phone_util();
|
||||
let mut test_number = PhoneNumber::new();
|
||||
test_number.set_country_code(1);
|
||||
test_number.set_national_number(8002530000);
|
||||
// assert!(!phone_util.can_be_internationally_dialled(&test_number));
|
||||
|
||||
test_number.set_national_number(6502530000);
|
||||
// assert!(phone_util.can_be_internationally_dialled(&test_number));
|
||||
|
||||
// ... (остальные проверки) ...
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_alpha_number() {
|
||||
let phone_util = get_phone_util();
|
||||
// assert!(phone_util.is_alpha_number("1800 six-flags"));
|
||||
// assert!(phone_util.is_alpha_number("1800 six-flags ext. 1234"));
|
||||
// assert!(!phone_util.is_alpha_number("1800 123-1234"));
|
||||
// assert!(!phone_util.is_alpha_number("1 six-flags"));
|
||||
}
|
||||
@@ -3,13 +3,45 @@
|
||||
filedir="./$(dirname "$0")"
|
||||
javadir="$filedir/../java"
|
||||
project_home="$filedir/../.."
|
||||
generated_dir="$project_home/src/phonenumberutil/generated"
|
||||
generated_dir="$project_home/src/generated/metadata"
|
||||
echo $generated_dir
|
||||
|
||||
resources_dir="$project_home/resources"
|
||||
rust_build_jar="$javadir/rust-build/target/rust-build-1.0-SNAPSHOT-jar-with-dependencies.jar"
|
||||
|
||||
# mvn -f "$javadir/pom.xml" install
|
||||
copyright_header="\
|
||||
// Copyright (C) 2009 The Libphonenumber Authors
|
||||
// Copyright (C) 2025 The Kashin Vladislav (Rust adaptation author)
|
||||
//
|
||||
// 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.
|
||||
"
|
||||
|
||||
skip_install=false
|
||||
|
||||
# Loop through all the command-line arguments
|
||||
for arg in "$@"
|
||||
do
|
||||
if [ "$arg" == "--skip-install" ]
|
||||
then
|
||||
skip_install=true
|
||||
# You can break the loop once the flag is found if you don't need to process further arguments
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $skip_install == false ]]; then
|
||||
mvn -f "$javadir/pom.xml" install
|
||||
fi
|
||||
mkdir -p "$generated_dir"
|
||||
|
||||
function generate {
|
||||
@@ -24,10 +56,20 @@ function generate {
|
||||
# generate general metadata
|
||||
generate "PhoneNumberMetadata.xml" "metadata" "metadata" "METADATA"
|
||||
|
||||
# generate short metadata
|
||||
# generate test metadata
|
||||
generate "PhoneNumberMetadataForTesting.xml" "test_metadata" "metadata" "TEST_METADATA"
|
||||
|
||||
# remove unnecessary nesting with pub use
|
||||
echo "\
|
||||
pub mod metadata;
|
||||
pub mod test_metadata;
|
||||
$copyright_header
|
||||
|
||||
mod metadata;
|
||||
|
||||
// use only in test case
|
||||
#[cfg(test)]
|
||||
mod test_metadata;
|
||||
|
||||
pub use metadata::METADATA;
|
||||
#[cfg(test)]
|
||||
pub use test_metadata::TEST_METADATA;
|
||||
" > "$generated_dir/mod.rs"
|
||||
Reference in New Issue
Block a user