git.iko.soy/typeable/libphonenumber
on 4cb8c2f help sign in
.github/workflows/ci.yamldeleted−102
since splitsnapshots
unifiedsplit
@@ -1,102 +0,0 @@
1−name: CI
2−
3−on:
4− push:
5− branches:
6− - "*"
7− pull_request:
8− branches:
9− - "*"
10− release:
11− types:
12− - prereleased
13−
14−jobs:
15− build:
16− strategy:
17− matrix:
18− platform:
19− - ubuntu-latest
20− ghc_version:
21− - "8.6.5"
22− - "8.8.4"
23− - "8.10.7"
24− - "9.0.2"
25− - "9.2.8"
26− - "9.4.8"
27− - "9.6.7"
28− - "9.8.4"
29− - "9.10.3"
30− - "9.12.2"
31− - "9.14.1"
32− fail-fast: false
33− name: Build on Linux, GHC ${{ matrix.ghc_version }}
34− runs-on: ${{ matrix.platform }}
35− steps:
36− - uses: actions/checkout@v4
37− - uses: haskell-actions/setup@v2
38− with:
39− ghc-version: ${{ matrix.ghc_version }}
40− cabal-version: "3.10.1.0"
41− - name: Install C++ library
42− run: |
43− sudo apt-get update
44− sudo apt-get install -y libphonenumber-dev
45−
46− - name: cabal sdist
47− run: cabal sdist --output-dir "$GITHUB_WORKSPACE/sdist"
48− - name: unpack
49− run: |
50− mkdir -p "$GITHUB_WORKSPACE/unpacked"
51− find "$GITHUB_WORKSPACE/sdist" -maxdepth 1 -type f -name '*.tar.gz' -exec tar -C "$GITHUB_WORKSPACE/unpacked" -xzvf {} \;
52− echo "PKGDIR_libphonenumber=$(find "$GITHUB_WORKSPACE/unpacked" -maxdepth 1 -type d -regex '.*/libphonenumber-[0-9.]*')" >> "$GITHUB_ENV"
53− - name: cabal configure
54− run: cd "$PKGDIR_libphonenumber" && cabal configure --with-ghc=ghc-${{ matrix.ghc_version }}
55− - name: Install dependencies
56− run: cd "$PKGDIR_libphonenumber" && cabal build --dependencies-only --enable-tests --haddock-all
57− - name: cabal build
58− run: cd "$PKGDIR_libphonenumber" && cabal build --ghc-options=-Werror
59− - name: cabal test spec_test
60− run: cd "$PKGDIR_libphonenumber" && cabal test spec_test
61− - name: cabal check
62− run: cd "$PKGDIR_libphonenumber" && cabal check
63− - name: cabal haddock
64− run: cd "$PKGDIR_libphonenumber" && cabal haddock
65−
66− dist:
67− needs: build
68− runs-on: ubuntu-latest
69− name: Build source tarball
70− if: github.event_name == 'release'
71− steps:
72− - uses: actions/checkout@v3
73− - uses: haskell-actions/setup@v2
74− with:
75− cabal-version: "3.10.1.0"
76− - name: Install C++ library
77− run: |
78− sudo apt-get update
79− sudo apt-get install -y libphonenumber-dev
80− - name: cabal sdist
81− run: |
82− cabal sdist --output-dir "$GITHUB_WORKSPACE/sdist"
83− echo "dist=$(find "$GITHUB_WORKSPACE/sdist" -maxdepth 1 -type f -name '*.tar.gz')" >> "$GITHUB_ENV"
84− - name: cabal haddock
85− run: |
86− cabal haddock --builddir "$GITHUB_WORKSPACE/doc" --haddock-for-hackage --enable-doc
87− echo "docs=$(find "$GITHUB_WORKSPACE/doc" -maxdepth 1 -type f -name '*-docs.tar.gz')" >> "$GITHUB_ENV"
88− - uses: actions/upload-artifact@v6
89− with:
90− name: Source tarball
91− path: ${{ env.dist }}
92− - uses: svenstaro/upload-release-action@2.11.3
93− with:
94− repo_token: ${{ secrets.GITHUB_TOKEN }}
95− file: ${{ env.dist }}
96− tag: ${{ github.ref }}
97− - name: Upload tarball to hackage
98− run: |
99− curl -X POST 'https://hackage.haskell.org/packages/candidates/' -H "Authorization: X-ApiKey ${{ secrets.HACKAGE_KEY }}" -F "package=@$dist" -w '%{url_effective}\n'
100− - name: Upload haddocks to hackage
101− run: |
102− curl -X PUT "https://hackage.haskell.org/package/$(basename ${docs%-docs.tar.gz})/candidate/docs" -H "Authorization: X-ApiKey ${{ secrets.HACKAGE_KEY }}" -H 'Content-type: application/x-tar' -H 'Content-encoding: gzip' --data-binary "@$docs"
LICENSEdeleted−21
@@ -1,21 +0,0 @@
1−MIT License
2−
3−Copyright (c) 2023 Typeable
4−
5−Permission is hereby granted, free of charge, to any person obtaining a copy
6−of this software and associated documentation files (the "Software"), to deal
7−in the Software without restriction, including without limitation the rights
8−to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9−copies of the Software, and to permit persons to whom the Software is
10−furnished to do so, subject to the following conditions:
11−
12−The above copyright notice and this permission notice shall be included in all
13−copies or substantial portions of the Software.
14−
15−THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16−IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17−FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18−AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19−LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20−OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21−SOFTWARE.
cxxbits/c_phonenumber.cpp+4−6
@@ -55,7 +55,7 @@ static country_code_source unmarshal_country_code_source(PhoneNumber::CountryCod
55 return static_cast<country_code_source>(value);
55 return static_cast<country_code_source>(value);
56}
56}
57
57
58−extern "C" CxxPhoneNumber *c_phone_number_marshal(phone_number const *c_number)
58+extern "C" PhoneNumber *c_phone_number_marshal(phone_number const *c_number)
59{
59{
60 PhoneNumber *number = new PhoneNumber();
60 PhoneNumber *number = new PhoneNumber();
61 if (c_number->extension != nullptr)
61 if (c_number->extension != nullptr)
@@ -72,12 +72,11 @@ extern "C" CxxPhoneNumber *c_phone_number_marshal(phone_number const *c_number)
72 number->set_country_code_source(marshal_country_code_source(c_number->country_code_source));
72 number->set_country_code_source(marshal_country_code_source(c_number->country_code_source));
73 if (c_number->has_number_of_leading_zeros)
73 if (c_number->has_number_of_leading_zeros)
74 number->set_number_of_leading_zeros(c_number->number_of_leading_zeros);
74 number->set_number_of_leading_zeros(c_number->number_of_leading_zeros);
75− return reinterpret_cast<CxxPhoneNumber *>(number);
75+ return number;
76}
76}
77
77
78−extern "C" void c_phone_number_unmarshal(CxxPhoneNumber const *ptr, phone_number *c_number)
78+extern "C" void c_phone_number_unmarshal(PhoneNumber const *number, phone_number *c_number)
79{
79{
80− auto number = reinterpret_cast<PhoneNumber const *>(ptr);
81 if (number->has_extension())
80 if (number->has_extension())
82 unmarshal_string_size(number->extension(), c_number->extension, c_number->extension_size);
81 unmarshal_string_size(number->extension(), c_number->extension, c_number->extension_size);
83 else
82 else
@@ -100,8 +99,7 @@ extern "C" void c_phone_number_unmarshal(CxxPhoneNumber const *ptr, phone_number
100 c_number->number_of_leading_zeros = number->number_of_leading_zeros();
99 c_number->number_of_leading_zeros = number->number_of_leading_zeros();
101}
100}
102
101
103−extern "C" void c_phone_number_free(CxxPhoneNumber *ptr)
102+extern "C" void c_phone_number_free(PhoneNumber *number)
104{
103{
105− auto number = reinterpret_cast<PhoneNumber *>(ptr);
106 delete number;
104 delete number;
107}
105}
cxxbits/c_phonenumberutil.cpp+26−45
@@ -310,11 +310,10 @@ extern "C" void c_phone_number_util_normalize_dialable_chars_only(
310}
310}
311
311
312extern "C" void c_phone_number_util_get_national_significant_number(
312extern "C" void c_phone_number_util_get_national_significant_number(
313− CxxPhoneNumber const *ptr,
313+ PhoneNumber const *number,
314 c_string *c_nsn
314 c_string *c_nsn
315)
315)
316{
316{
317− auto number = reinterpret_cast<PhoneNumber const *>(ptr);
318 std::string nsn;
317 std::string nsn;
319 PhoneNumberUtil::GetInstance()->GetNationalSignificantNumber(*number, &nsn);
318 PhoneNumberUtil::GetInstance()->GetNationalSignificantNumber(*number, &nsn);
320 unmarshal_c_string(nsn, *c_nsn);
319 unmarshal_c_string(nsn, *c_nsn);
@@ -331,25 +330,23 @@ extern "C" void c_phone_number_util_get_country_mobile_token(
331}
330}
332
331
333extern "C" void c_phone_number_util_format(
332extern "C" void c_phone_number_util_format(
334− CxxPhoneNumber const *ptr,
333+ PhoneNumber const *number,
335 phone_number_format format,
334 phone_number_format format,
336 c_string *c_string
335 c_string *c_string
337)
336)
338{
337{
339− auto number = reinterpret_cast<PhoneNumber const *>(ptr);
340 std::string string;
338 std::string string;
341 PhoneNumberUtil::GetInstance()->Format(*number, marshal_phone_number_format(format), &string);
339 PhoneNumberUtil::GetInstance()->Format(*number, marshal_phone_number_format(format), &string);
342 unmarshal_c_string(string, *c_string);
340 unmarshal_c_string(string, *c_string);
343}
341}
344
342
345extern "C" void c_phone_number_util_format_national_number_with_carrier_code(
343extern "C" void c_phone_number_util_format_national_number_with_carrier_code(
346− CxxPhoneNumber const *ptr,
344+ PhoneNumber const *number,
347 char const *c_carrier_code,
345 char const *c_carrier_code,
348 size_t c_carrier_code_size,
346 size_t c_carrier_code_size,
349 c_string *c_string
347 c_string *c_string
350)
348)
351{
349{
352− auto number = reinterpret_cast<PhoneNumber const *>(ptr);
353 std::string const carrier_code(c_carrier_code, c_carrier_code_size);
350 std::string const carrier_code(c_carrier_code, c_carrier_code_size);
354 std::string string;
351 std::string string;
355 PhoneNumberUtil::GetInstance()->FormatNationalNumberWithCarrierCode(*number, carrier_code, &string);
352 PhoneNumberUtil::GetInstance()->FormatNationalNumberWithCarrierCode(*number, carrier_code, &string);
@@ -357,13 +354,12 @@ extern "C" void c_phone_number_util_format_national_number_with_carrier_code(
357}
354}
358
355
359extern "C" void c_phone_number_util_format_national_number_with_preferred_carrier_code(
356extern "C" void c_phone_number_util_format_national_number_with_preferred_carrier_code(
360− CxxPhoneNumber const *ptr,
357+ PhoneNumber const *number,
361 char const *c_carrier_code,
358 char const *c_carrier_code,
362 size_t c_carrier_code_size,
359 size_t c_carrier_code_size,
363 c_string *c_string
360 c_string *c_string
364)
361)
365{
362{
366− auto number = reinterpret_cast<PhoneNumber const *>(ptr);
367 std::string const carrier_code(c_carrier_code, c_carrier_code_size);
363 std::string const carrier_code(c_carrier_code, c_carrier_code_size);
368 std::string string;
364 std::string string;
369 PhoneNumberUtil::GetInstance()->FormatNationalNumberWithPreferredCarrierCode(*number, carrier_code, &string);
365 PhoneNumberUtil::GetInstance()->FormatNationalNumberWithPreferredCarrierCode(*number, carrier_code, &string);
@@ -371,14 +367,13 @@ extern "C" void c_phone_number_util_format_national_number_with_preferred_carrie
371}
367}
372
368
373extern "C" void c_phone_number_util_format_number_for_mobile_dialing(
369extern "C" void c_phone_number_util_format_number_for_mobile_dialing(
374− CxxPhoneNumber const *ptr,
370+ PhoneNumber const *number,
375 char const *c_region,
371 char const *c_region,
376 size_t c_region_size,
372 size_t c_region_size,
377 int with_formatting,
373 int with_formatting,
378 c_string *c_string
374 c_string *c_string
379)
375)
380{
376{
381− auto number = reinterpret_cast<PhoneNumber const *>(ptr);
382 std::string const region(c_region, c_region_size);
377 std::string const region(c_region, c_region_size);
383 std::string string;
378 std::string string;
384 PhoneNumberUtil::GetInstance()->FormatNumberForMobileDialing(*number, region, with_formatting, &string);
379 PhoneNumberUtil::GetInstance()->FormatNumberForMobileDialing(*number, region, with_formatting, &string);
@@ -386,13 +381,12 @@ extern "C" void c_phone_number_util_format_number_for_mobile_dialing(
386}
381}
387
382
388extern "C" void c_phone_number_util_format_out_of_country_calling_number(
383extern "C" void c_phone_number_util_format_out_of_country_calling_number(
389− CxxPhoneNumber const *ptr,
384+ PhoneNumber const *number,
390 char const *c_region,
385 char const *c_region,
391 size_t c_region_size,
386 size_t c_region_size,
392 c_string *c_string
387 c_string *c_string
393)
388)
394{
389{
395− auto number = reinterpret_cast<PhoneNumber const *>(ptr);
396 std::string const region(c_region, c_region_size);
390 std::string const region(c_region, c_region_size);
397 std::string string;
391 std::string string;
398 PhoneNumberUtil::GetInstance()->FormatOutOfCountryCallingNumber(*number, region, &string);
392 PhoneNumberUtil::GetInstance()->FormatOutOfCountryCallingNumber(*number, region, &string);
@@ -400,13 +394,12 @@ extern "C" void c_phone_number_util_format_out_of_country_calling_number(
400}
394}
401
395
402extern "C" void c_phone_number_util_format_in_original_format(
396extern "C" void c_phone_number_util_format_in_original_format(
403− CxxPhoneNumber const *ptr,
397+ PhoneNumber const *number,
404 char const *c_region,
398 char const *c_region,
405 size_t c_region_size,
399 size_t c_region_size,
406 c_string *c_string
400 c_string *c_string
407)
401)
408{
402{
409− auto number = reinterpret_cast<PhoneNumber const *>(ptr);
410 std::string const region(c_region, c_region_size);
403 std::string const region(c_region, c_region_size);
411 std::string string;
404 std::string string;
412 PhoneNumberUtil::GetInstance()->FormatInOriginalFormat(*number, region, &string);
405 PhoneNumberUtil::GetInstance()->FormatInOriginalFormat(*number, region, &string);
@@ -414,26 +407,24 @@ extern "C" void c_phone_number_util_format_in_original_format(
414}
407}
415
408
416extern "C" void c_phone_number_util_format_out_of_country_keeping_alpha_chars(
409extern "C" void c_phone_number_util_format_out_of_country_keeping_alpha_chars(
417− CxxPhoneNumber const *ptr,
410+ PhoneNumber const *number,
418 char const *c_region,
411 char const *c_region,
419 size_t c_region_size,
412 size_t c_region_size,
420 c_string *c_string
413 c_string *c_string
421)
414)
422{
415{
423− auto number = reinterpret_cast<PhoneNumber const *>(ptr);
424 std::string const region(c_region, c_region_size);
416 std::string const region(c_region, c_region_size);
425 std::string string;
417 std::string string;
426 PhoneNumberUtil::GetInstance()->FormatOutOfCountryKeepingAlphaChars(*number, region, &string);
418 PhoneNumberUtil::GetInstance()->FormatOutOfCountryKeepingAlphaChars(*number, region, &string);
427 unmarshal_c_string(string, *c_string);
419 unmarshal_c_string(string, *c_string);
428}
420}
429
421
430−extern "C" CxxPhoneNumber *c_phone_number_util_truncate_too_long_number(CxxPhoneNumber const *ptr)
422+extern "C" PhoneNumber *c_phone_number_util_truncate_too_long_number(PhoneNumber const *input)
431{
423{
432− auto input = reinterpret_cast<PhoneNumber const *>(ptr);
433 auto *output = new PhoneNumber(*input);
424 auto *output = new PhoneNumber(*input);
434 if (PhoneNumberUtil::GetInstance()->TruncateTooLongNumber(output))
425 if (PhoneNumberUtil::GetInstance()->TruncateTooLongNumber(output))
435 {
426 {
436− return reinterpret_cast<CxxPhoneNumber *>(output);
427+ return output;
437 }
428 }
438 else
429 else
439 {
430 {
@@ -442,37 +433,33 @@ extern "C" CxxPhoneNumber *c_phone_number_util_truncate_too_long_number(CxxPhone
442 }
433 }
443}
434}
444
435
445−extern "C" phone_number_type c_phone_number_util_get_number_type(CxxPhoneNumber const *ptr)
436+extern "C" phone_number_type c_phone_number_util_get_number_type(PhoneNumber const *number)
446{
437{
447− auto number = reinterpret_cast<PhoneNumber const *>(ptr);
448 return unmarshal_phone_number_type(
438 return unmarshal_phone_number_type(
449 PhoneNumberUtil::GetInstance()->GetNumberType(*number)
439 PhoneNumberUtil::GetInstance()->GetNumberType(*number)
450 );
440 );
451}
441}
452
442
453−extern "C" int c_phone_number_util_is_valid_number(CxxPhoneNumber const *ptr)
443+extern "C" int c_phone_number_util_is_valid_number(PhoneNumber const *number)
454{
444{
455− auto number = reinterpret_cast<PhoneNumber const *>(ptr);
456 return PhoneNumberUtil::GetInstance()->IsValidNumber(*number);
445 return PhoneNumberUtil::GetInstance()->IsValidNumber(*number);
457}
446}
458
447
459extern "C" int c_phone_number_util_is_valid_number_for_region(
448extern "C" int c_phone_number_util_is_valid_number_for_region(
460− CxxPhoneNumber const *ptr,
449+ PhoneNumber const *number,
461 char const *c_region,
450 char const *c_region,
462 size_t c_region_size
451 size_t c_region_size
463)
452)
464{
453{
465− auto number = reinterpret_cast<PhoneNumber const *>(ptr);
466 std::string const region(c_region, c_region_size);
454 std::string const region(c_region, c_region_size);
467 return PhoneNumberUtil::GetInstance()->IsValidNumberForRegion(*number, region);
455 return PhoneNumberUtil::GetInstance()->IsValidNumberForRegion(*number, region);
468}
456}
469
457
470extern "C" void c_phone_number_util_get_region_code_for_number(
458extern "C" void c_phone_number_util_get_region_code_for_number(
471− CxxPhoneNumber const *ptr,
459+ PhoneNumber const *number,
472 c_string *c_region
460 c_string *c_region
473)
461)
474{
462{
475− auto number = reinterpret_cast<PhoneNumber const *>(ptr);
476 std::string region;
463 std::string region;
477 PhoneNumberUtil::GetInstance()->GetRegionCodeForNumber(*number, &region);
464 PhoneNumberUtil::GetInstance()->GetRegionCodeForNumber(*number, &region);
478 unmarshal_c_string(region, *c_region);
465 unmarshal_c_string(region, *c_region);
@@ -531,11 +518,10 @@ extern "C" void c_phone_number_util_get_ndd_prefix_for_region(
531}
518}
532
519
533extern "C" validation_result c_phone_number_util_is_possible_number_for_type_with_reason(
520extern "C" validation_result c_phone_number_util_is_possible_number_for_type_with_reason(
534− CxxPhoneNumber const *ptr,
521+ PhoneNumber const *number,
535 phone_number_type ntype
522 phone_number_type ntype
536)
523)
537{
524{
538− auto number = reinterpret_cast<PhoneNumber const *>(ptr);
539 return unmarshal_validation_result(
525 return unmarshal_validation_result(
540 PhoneNumberUtil::GetInstance()->IsPossibleNumberForTypeWithReason(
526 PhoneNumberUtil::GetInstance()->IsPossibleNumberForTypeWithReason(
541 *number,
527 *number,
@@ -544,15 +530,13 @@ extern "C" validation_result c_phone_number_util_is_possible_number_for_type_wit
544 );
530 );
545}
531}
546
532
547−extern "C" int c_phone_number_util_can_be_internationally_dialed(CxxPhoneNumber const *ptr)
533+extern "C" int c_phone_number_util_can_be_internationally_dialed(PhoneNumber const *number)
548{
534{
549− auto number = reinterpret_cast<PhoneNumber const *>(ptr);
550 return PhoneNumberUtil::GetInstance()->CanBeInternationallyDialled(*number);
535 return PhoneNumberUtil::GetInstance()->CanBeInternationallyDialled(*number);
551}
536}
552
537
553−extern "C" int c_phone_number_util_is_number_geographical_1(CxxPhoneNumber const *ptr)
538+extern "C" int c_phone_number_util_is_number_geographical_1(PhoneNumber const *number)
554{
539{
555− auto number = reinterpret_cast<PhoneNumber const *>(ptr);
556 return PhoneNumberUtil::GetInstance()->IsNumberGeographical(*number);
540 return PhoneNumberUtil::GetInstance()->IsNumberGeographical(*number);
557}
541}
558
542
@@ -572,14 +556,14 @@ extern "C" error_type c_phone_number_util_parse(
572 size_t c_string_size,
556 size_t c_string_size,
573 char const *c_region,
557 char const *c_region,
574 size_t c_region_size,
558 size_t c_region_size,
575− CxxPhoneNumber **number
559+ PhoneNumber **number
576)
560)
577{
561{
578 std::string const string(c_string, c_string_size);
562 std::string const string(c_string, c_string_size);
579 std::string const region(c_region, c_region_size);
563 std::string const region(c_region, c_region_size);
580− *number = reinterpret_cast<CxxPhoneNumber *>(new PhoneNumber());
564+ *number = new PhoneNumber();
581 return unmarshal_error_type(
565 return unmarshal_error_type(
582− PhoneNumberUtil::GetInstance()->Parse(string, region, reinterpret_cast<PhoneNumber *>(*number))
566+ PhoneNumberUtil::GetInstance()->Parse(string, region, *number)
583 );
567 );
584}
568}
585
569
@@ -588,24 +572,22 @@ extern "C" error_type c_phone_number_util_parse_and_keep_raw_input(
588 size_t c_string_size,
572 size_t c_string_size,
589 char const *c_region,
573 char const *c_region,
590 size_t c_region_size,
574 size_t c_region_size,
591− CxxPhoneNumber **number
575+ PhoneNumber **number
592)
576)
593{
577{
594 std::string const string(c_string, c_string_size);
578 std::string const string(c_string, c_string_size);
595 std::string const region(c_region, c_region_size);
579 std::string const region(c_region, c_region_size);
596− *number = reinterpret_cast<CxxPhoneNumber *>(new PhoneNumber());
580+ *number = new PhoneNumber();
597 return unmarshal_error_type(
581 return unmarshal_error_type(
598− PhoneNumberUtil::GetInstance()->ParseAndKeepRawInput(string, region, reinterpret_cast<PhoneNumber *>(*number))
582+ PhoneNumberUtil::GetInstance()->ParseAndKeepRawInput(string, region, *number)
599 );
583 );
600}
584}
601
585
602extern "C" match_type c_phone_number_util_is_number_match(
586extern "C" match_type c_phone_number_util_is_number_match(
603− CxxPhoneNumber const *ptr1,
587+ PhoneNumber const *number1,
604− CxxPhoneNumber const *ptr2
588+ PhoneNumber const *number2
605)
589)
606{
590{
607− auto number1 = reinterpret_cast<PhoneNumber const *>(ptr1);
608− auto number2 = reinterpret_cast<PhoneNumber const *>(ptr2);
609 return unmarshal_match_type(
591 return unmarshal_match_type(
610 PhoneNumberUtil::GetInstance()->IsNumberMatch(*number1, *number2)
592 PhoneNumberUtil::GetInstance()->IsNumberMatch(*number1, *number2)
611 );
593 );
@@ -626,12 +608,11 @@ extern "C" match_type c_phone_number_util_is_number_match_with_two_strings(
626}
608}
627
609
628extern "C" match_type c_phone_number_util_is_number_match_with_one_string(
610extern "C" match_type c_phone_number_util_is_number_match_with_one_string(
629− CxxPhoneNumber const *ptr1,
611+ PhoneNumber const *number1,
630 char const *c_number2,
612 char const *c_number2,
631 size_t c_number2_size
613 size_t c_number2_size
632)
614)
633{
615{
634− auto number1 = reinterpret_cast<PhoneNumber const *>(ptr1);
635 std::string const number2(c_number2, c_number2_size);
616 std::string const number2(c_number2, c_number2_size);
636 return unmarshal_match_type(
617 return unmarshal_match_type(
637 PhoneNumberUtil::GetInstance()->IsNumberMatchWithOneString(*number1, number2)
618 PhoneNumberUtil::GetInstance()->IsNumberMatchWithOneString(*number1, number2)
include/c_phonenumber.h+8−4
@@ -43,16 +43,20 @@ typedef struct
43 char has_number_of_leading_zeros;
43 char has_number_of_leading_zeros;
44} phone_number;
44} phone_number;
45
45
46−struct CxxPhoneNumber;
46+#ifdef __cplusplus
47+typedef i18n::phonenumbers::PhoneNumber PhoneNumber;
48+#else
49+typedef struct PhoneNumber PhoneNumber;
50+#endif
47
51
48// The returned object is allocated by `new` and managed by C++ RAII, and it is
52// The returned object is allocated by `new` and managed by C++ RAII, and it is
49// haskell's responsibility to call its finalizer (c_phone_number_free).
53// haskell's responsibility to call its finalizer (c_phone_number_free).
50−struct CxxPhoneNumber *c_phone_number_marshal(phone_number const *);
54+PhoneNumber *c_phone_number_marshal(phone_number const *);
51
55
52// phone_number * points to an area which will be filled with the data of the
56// phone_number * points to an area which will be filled with the data of the
53// given PhoneNumber.
57// given PhoneNumber.
54−void c_phone_number_unmarshal(struct CxxPhoneNumber const *, phone_number *);
58+void c_phone_number_unmarshal(PhoneNumber const *, phone_number *);
55
59
56−void c_phone_number_free(struct CxxPhoneNumber *);
60+void c_phone_number_free(PhoneNumber *);
57
61
58#endif
62#endif
include/c_phonenumberutil.h+20−20
@@ -97,34 +97,34 @@ int c_phone_number_util_is_alpha_number(char const *, size_t);
97void c_phone_number_util_convert_alpha_characters_in_number(char const *, size_t, c_string *);
97void c_phone_number_util_convert_alpha_characters_in_number(char const *, size_t, c_string *);
98void c_phone_number_util_normalize_digits_only(char const *, size_t, c_string *);
98void c_phone_number_util_normalize_digits_only(char const *, size_t, c_string *);
99void c_phone_number_util_normalize_dialable_chars_only(char const *, size_t, c_string *);
99void c_phone_number_util_normalize_dialable_chars_only(char const *, size_t, c_string *);
100−void c_phone_number_util_get_national_significant_number(struct CxxPhoneNumber const *, c_string *);
100+void c_phone_number_util_get_national_significant_number(PhoneNumber const *, c_string *);
101void c_phone_number_util_get_country_mobile_token(int, c_string *);
101void c_phone_number_util_get_country_mobile_token(int, c_string *);
102−void c_phone_number_util_format(struct CxxPhoneNumber const *, enum phone_number_format, c_string *);
102+void c_phone_number_util_format(PhoneNumber const *, enum phone_number_format, c_string *);
103−void c_phone_number_util_format_national_number_with_carrier_code(struct CxxPhoneNumber const *, char const *, size_t, c_string *);
103+void c_phone_number_util_format_national_number_with_carrier_code(PhoneNumber const *, char const *, size_t, c_string *);
104−void c_phone_number_util_format_national_number_with_preferred_carrier_code(struct CxxPhoneNumber const *, char const *, size_t, c_string *);
104+void c_phone_number_util_format_national_number_with_preferred_carrier_code(PhoneNumber const *, char const *, size_t, c_string *);
105−void c_phone_number_util_format_number_for_mobile_dialing(struct CxxPhoneNumber const *, char const *, size_t, int, c_string *);
105+void c_phone_number_util_format_number_for_mobile_dialing(PhoneNumber const *, char const *, size_t, int, c_string *);
106−void c_phone_number_util_format_out_of_country_calling_number(struct CxxPhoneNumber const *, char const *, size_t, c_string *);
106+void c_phone_number_util_format_out_of_country_calling_number(PhoneNumber const *, char const *, size_t, c_string *);
107−void c_phone_number_util_format_in_original_format(struct CxxPhoneNumber const *, char const *, size_t, c_string *);
107+void c_phone_number_util_format_in_original_format(PhoneNumber const *, char const *, size_t, c_string *);
108−void c_phone_number_util_format_out_of_country_keeping_alpha_chars(struct CxxPhoneNumber const *, char const *, size_t, c_string *);
108+void c_phone_number_util_format_out_of_country_keeping_alpha_chars(PhoneNumber const *, char const *, size_t, c_string *);
109// /!\ May return NULL
109// /!\ May return NULL
110−struct CxxPhoneNumber *c_phone_number_util_truncate_too_long_number(struct CxxPhoneNumber const *);
110+PhoneNumber *c_phone_number_util_truncate_too_long_number(PhoneNumber const *);
111−enum phone_number_type c_phone_number_util_get_number_type(struct CxxPhoneNumber const *);
111+enum phone_number_type c_phone_number_util_get_number_type(PhoneNumber const *);
112−int c_phone_number_util_is_valid_number(struct CxxPhoneNumber const *);
112+int c_phone_number_util_is_valid_number(PhoneNumber const *);
113−int c_phone_number_util_is_valid_number_for_region(struct CxxPhoneNumber const *, char const *, size_t);
113+int c_phone_number_util_is_valid_number_for_region(PhoneNumber const *, char const *, size_t);
114−void c_phone_number_util_get_region_code_for_number(struct CxxPhoneNumber const *, c_string *);
114+void c_phone_number_util_get_region_code_for_number(PhoneNumber const *, c_string *);
115int c_phone_number_util_get_country_code_for_region(char const *, size_t);
115int c_phone_number_util_get_country_code_for_region(char const *, size_t);
116void c_phone_number_util_get_region_code_for_country_code(int, c_string *);
116void c_phone_number_util_get_region_code_for_country_code(int, c_string *);
117void c_phone_number_util_get_region_codes_for_country_calling_code(int, c_string **, size_t *);
117void c_phone_number_util_get_region_codes_for_country_calling_code(int, c_string **, size_t *);
118int c_phone_number_util_is_nanpa_country(char const *, size_t);
118int c_phone_number_util_is_nanpa_country(char const *, size_t);
119void c_phone_number_util_get_ndd_prefix_for_region(char const *, size_t, int, c_string *);
119void c_phone_number_util_get_ndd_prefix_for_region(char const *, size_t, int, c_string *);
120−enum validation_result c_phone_number_util_is_possible_number_for_type_with_reason(struct CxxPhoneNumber const *, enum phone_number_type);
120+enum validation_result c_phone_number_util_is_possible_number_for_type_with_reason(PhoneNumber const *, enum phone_number_type);
121−int c_phone_number_util_can_be_internationally_dialed(struct CxxPhoneNumber const *);
121+int c_phone_number_util_can_be_internationally_dialed(PhoneNumber const *);
122−int c_phone_number_util_is_number_geographical_1(struct CxxPhoneNumber const *);
122+int c_phone_number_util_is_number_geographical_1(PhoneNumber const *);
123int c_phone_number_util_is_number_geographical_2(enum phone_number_type, int);
123int c_phone_number_util_is_number_geographical_2(enum phone_number_type, int);
124−enum error_type c_phone_number_util_parse(char const *, size_t, char const *, size_t, struct CxxPhoneNumber **);
124+enum error_type c_phone_number_util_parse(char const *, size_t, char const *, size_t, PhoneNumber **);
125−enum error_type c_phone_number_util_parse_and_keep_raw_input(char const *, size_t, char const *, size_t, struct CxxPhoneNumber **);
125+enum error_type c_phone_number_util_parse_and_keep_raw_input(char const *, size_t, char const *, size_t, PhoneNumber **);
126−enum match_type c_phone_number_util_is_number_match(struct CxxPhoneNumber const *, struct CxxPhoneNumber const *);
126+enum match_type c_phone_number_util_is_number_match(PhoneNumber const *, PhoneNumber const *);
127enum match_type c_phone_number_util_is_number_match_with_two_strings(char const *, size_t, char const *, size_t);
127enum match_type c_phone_number_util_is_number_match_with_two_strings(char const *, size_t, char const *, size_t);
128−enum match_type c_phone_number_util_is_number_match_with_one_string(struct CxxPhoneNumber const *, char const *, size_t);
128+enum match_type c_phone_number_util_is_number_match_with_one_string(PhoneNumber const *, char const *, size_t);
129
129
130#endif
130#endif
include/common.h+2−3
@@ -4,7 +4,6 @@
4#include <cstddef>
4#include <cstddef>
5#include <cstring>
5#include <cstring>
6#include <type_traits>
6#include <type_traits>
7−#include <utility>
8
7
9// Given `enum T { A, B, C }` and `enum S { X, Y, Z }`, we can use
8// Given `enum T { A, B, C }` and `enum S { X, Y, Z }`, we can use
10// `is_same_enum<enum_values<T, A, B, C>, enum_values<S, X, Y, Z>>::value`
9// `is_same_enum<enum_values<T, A, B, C>, enum_values<S, X, Y, Z>>::value`
@@ -32,7 +31,7 @@ struct is_same_enum: std::false_type
32
31
33template<typename T, T... TVals, typename S, S... SVals>
32template<typename T, T... TVals, typename S, S... SVals>
34struct is_same_enum<enum_values<T, TVals...>, enum_values<S, SVals...>>:
33struct is_same_enum<enum_values<T, TVals...>, enum_values<S, SVals...>>:
35− std::integral_constant<bool, std::is_same<
34+ std::integral_constant<bool, std::is_same_v<
36 std::integer_sequence<
35 std::integer_sequence<
37 typename std::common_type<
36 typename std::common_type<
38 typename std::underlying_type<T>::type,
37 typename std::underlying_type<T>::type,
@@ -47,7 +46,7 @@ struct is_same_enum<enum_values<T, TVals...>, enum_values<S, SVals...>>:
47 >::type,
46 >::type,
48 SVals...
47 SVals...
49 >
48 >
50− >::value>
49+ >>
51{};
50{};
52
51
53inline void unmarshal_string_size(std::string const &string, char *&c_string, size_t &c_string_size)
52inline void unmarshal_string_size(std::string const &string, char *&c_string, size_t &c_string_size)
libphonenumber.cabal+36−81
@@ -1,6 +1,6 @@
1cabal-version: 3.0
1cabal-version: 3.0
2name: libphonenumber
2name: libphonenumber
3−version: 0.1.4.0
3+version: 0.0.0.0
4category: Data
4category: Data
5synopsis: Parsing, formatting, and validating international phone
5synopsis: Parsing, formatting, and validating international phone
6 numbers
6 numbers
@@ -8,8 +8,7 @@ description:
8 This package provides bindings for the C++ version of the
8 This package provides bindings for the C++ version of the
9 <https://github.com/google/libphonenumber libphonenumber library>.
9 <https://github.com/google/libphonenumber libphonenumber library>.
10 The bindings currently do not include @AsYouTypeFormatter@
10 The bindings currently do not include @AsYouTypeFormatter@
11− and @ShortNumberInfo@. The C++ library must be of version
11+ and @ShortNumberInfo@.
12− >= 8.7.0.
13
12
14 The interface largely resembles that of the original unified
13 The interface largely resembles that of the original unified
15 C++, Java, and JavaScript version of the library, with some
14 C++, Java, and JavaScript version of the library, with some
@@ -20,66 +19,37 @@ description:
20 else has installed a global logger which could observe
19 else has installed a global logger which could observe
21 side-effects from library calls.
20 side-effects from library calls.
22
21
23− The underlying library internally uses UTF-8 encoded byte
24− strings. To avoid decoding overhead where it is unnecessary,
25− and to avoid a dependency on @text@, we use 'ByteString'
26− throughout the library instead of 'Data.Text.Text'.
27−
28−copyright: 2023-2025 Typeable
29−author: Typeable
30−maintainer: mniip@typeable.io
31−homepage: https://github.com/typeable/libphonenumber/
32−license: MIT
33−license-file: LICENSE
34−
35−tested-with:
36− , GHC == 8.6.5
37− , GHC == 8.8.4
38− , GHC == 8.10.7
39− , GHC == 9.0.2
40− , GHC == 9.2.8
41− , GHC == 9.4.8
42− , GHC == 9.6.7
43− , GHC == 9.8.4
44− , GHC == 9.10.3
45− , GHC == 9.12.2
46− , GHC == 9.14.1
47−
48−build-type: Simple
22+build-type: Simple
49
23
50extra-source-files:
24extra-source-files:
51− , include/*.h
25+ include/*.h
52− , test/libphonenumber.supp
26+ test/libphonenumber.supp
53−
54−source-repository head
55− type: git
56− location: https://github.com/typeable/libphonenumber/
57
27
58library
28library
59 exposed-modules:
29 exposed-modules:
60− , Data.PhoneNumber.Number
30+ Data.PhoneNumber.Number
61− , Data.PhoneNumber.Util
31+ Data.PhoneNumber.Util
62 other-modules:
32 other-modules:
63− , Data.PhoneNumber.Internal.Common
33+ Data.PhoneNumber.Internal.Common
64− , Data.PhoneNumber.Internal.Number
34+ Data.PhoneNumber.Internal.Number
65− , Data.PhoneNumber.Internal.Util
35+ Data.PhoneNumber.Internal.Util
66 build-depends:
36 build-depends:
67− , base >= 4.12 && < 4.23
37+ base >= 4.12 && < 4.18
68− , bytestring >= 0.10.8 && < 0.13
38+ , bytestring
69− , containers >= 0.6.0 && < 0.9
39+ , containers
70− , deepseq >= 1.4.4 && < 1.6
40+ , deepseq
71− , transformers >= 0.5.5 && < 0.7
41+ , transformers
72 build-tool-depends: c2hs:c2hs
42 build-tool-depends: c2hs:c2hs
73− pkgconfig-depends: protobuf
74 include-dirs: include
43 include-dirs: include
75 includes:
44 includes:
76− , c_phonenumber.h
45+ c_phonenumber.h
77− , c_phonenumberutil.h
46+ c_phonenumberutil.h
78 cxx-sources:
47 cxx-sources:
79− , cxxbits/c_phonenumber.cpp
48+ cxxbits/c_phonenumber.cpp
80− , cxxbits/c_phonenumberutil.cpp
49+ cxxbits/c_phonenumberutil.cpp
81 extra-libraries:
50 extra-libraries:
82− , phonenumber
51+ phonenumber
52+ protobuf
83 if impl(ghc >= 9.4)
53 if impl(ghc >= 9.4)
84 build-depends: system-cxx-std-lib
54 build-depends: system-cxx-std-lib
85 else
55 else
@@ -87,43 +57,28 @@ library
87 hs-source-dirs: src
57 hs-source-dirs: src
88 default-language: Haskell2010
58 default-language: Haskell2010
89 default-extensions:
59 default-extensions:
90− , DeriveAnyClass
60+ DeriveAnyClass
91− , DeriveDataTypeable
61+ DeriveDataTypeable
92− , DeriveGeneric
62+ DeriveGeneric
93− , DerivingStrategies
63+ DerivingStrategies
94− , GeneralizedNewtypeDeriving
64+ GeneralizedNewtypeDeriving
95− , LambdaCase
65+ LambdaCase
96− , NamedFieldPuns
66+ NamedFieldPuns
97− , OverloadedStrings
67+ OverloadedStrings
98− , PatternSynonyms
68+ PatternSynonyms
99− , StandaloneDeriving
69+ StandaloneDeriving
100− , RecordWildCards
70+ RecordWildCards
101− , ViewPatterns
71+ ViewPatterns
102 if impl(ghc >= 9.2)
72 if impl(ghc >= 9.2)
103 default-extensions: NoFieldSelectors
73 default-extensions: NoFieldSelectors
104− ghc-options: -Wall -Wextra
74+ ghc-options: -Wall -Wextra -Werror
105−
106−test-suite spec_test
107− type: exitcode-stdio-1.0
108− build-depends:
109− , base
110− , bytestring
111− , containers
112− , hspec >= 2.10.8 && < 2.12
113− , libphonenumber
114− , QuickCheck >= 2.13.1 && < 2.16
115− main-is: Spec.hs
116− hs-source-dirs: test
117− default-language: Haskell2010
118− ghc-options: -Wall -Wextra
119
75
120test-suite leak_test
76test-suite leak_test
121 type: exitcode-stdio-1.0
77 type: exitcode-stdio-1.0
122 build-depends:
78 build-depends:
123− , base
79+ base
124 , libphonenumber
80 , libphonenumber
125− , process >= 1.6.5 && < 1.7
81+ , process
126 main-is: Leak.hs
82 main-is: Leak.hs
127 hs-source-dirs: test
83 hs-source-dirs: test
128 default-language: Haskell2010
84 default-language: Haskell2010
129− ghc-options: -Wall -Wextra
src/Data/PhoneNumber/Internal/Number.chs+1−1
@@ -126,7 +126,7 @@ acquireCPhoneNumber p = do
126-- , 'Data.PhoneNumber.Number.numberOfLeadingZeros' :: !('Maybe' 'Int')
126-- , 'Data.PhoneNumber.Number.numberOfLeadingZeros' :: !('Maybe' 'Int')
127-- }
127-- }
128-- @
128-- @
129−{#pointer *CxxPhoneNumber as PhoneNumber foreign finalizer c_phone_number_free newtype#}
129+{#pointer *PhoneNumber foreign finalizer c_phone_number_free newtype#}
130
130
131{#fun unsafe c_phone_number_marshal
131{#fun unsafe c_phone_number_marshal
132 { withCPhoneNumber* `CPhoneNumber'
132 { withCPhoneNumber* `CPhoneNumber'
src/Data/PhoneNumber/Number.hs+10−69
@@ -21,10 +21,16 @@ module Data.PhoneNumber.Number
21 ) where
21 ) where
22
22
23import Data.ByteString (ByteString)
23import Data.ByteString (ByteString)
24−import Data.PhoneNumber.Internal.Number
24+import Data.PhoneNumber.Internal.Number hiding
25− ( CPhoneNumber(CPhoneNumber), PhoneNumber, CountryCodeSource, toCPhoneNumber
25+ ( pattern PhoneNumber
26− , fromCPhoneNumber
26+ , extension
27− )
27+ , rawInput
28+ , preferredDomesticCarrierCode
29+ , nationalNumber
30+ , countryCode
31+ , italianLeadingZero
32+ , countryCodeSource
33+ , numberOfLeadingZeros )
28import qualified Data.PhoneNumber.Internal.Number as I
34import qualified Data.PhoneNumber.Internal.Number as I
29
35
30-- | A country calling code (International Subscriber Dialing code, ISD code),
36-- | A country calling code (International Subscriber Dialing code, ISD code),
@@ -73,68 +79,3 @@ pattern PhoneNumber
73 = fromCPhoneNumber $ CPhoneNumber{..}
79 = fromCPhoneNumber $ CPhoneNumber{..}
74
80
75{-# COMPLETE PhoneNumber #-}
81{-# COMPLETE PhoneNumber #-}
76−
77−-- | E.g.:
78−--
79−-- @
80−-- 'Data.PhoneNumber.Util.parseNumber' 'Data.PhoneNumber.Util.Canonicalize' 'Nothing' "+1 800-234-5678 ext. 1234"
81−-- = 'Right' v'PhoneNumber' { 'extension' = 'Just' "1234", .. }
82−-- @
83−extension :: PhoneNumber -> Maybe ByteString
84−
85−-- | E.g.:
86−--
87−-- @
88−-- 'Data.PhoneNumber.Util.parseNumber' 'Data.PhoneNumber.Util.KeepRawInput' 'Nothing' " + 1(2-3~4*5.6 "
89−-- = 'Right' v'PhoneNumber' { 'rawInput' = 'Just' " + 1(2-3~4*5.6 ", .. }
90−-- @
91−rawInput :: PhoneNumber -> Maybe ByteString
92−
93−-- | E.g.:
94−--
95−-- @
96−-- 'Data.PhoneNumber.Util.parseNumber' 'Data.PhoneNumber.Util.KeepRawInput' ('Just' \"BR\") "0 41 (21) 2345-6789"
97−-- = 'Right' v'PhoneNumber' { 'preferredDomesticCarrierCode' = 'Just' "41", .. }
98−-- @
99−preferredDomesticCarrierCode :: PhoneNumber -> Maybe ByteString
100−
101−-- | You probably want to use 'Data.PhoneNumber.Util.nationalSignificantNumber'
102−-- instead. E.g.:
103−--
104−-- @
105−-- 'Data.PhoneNumber.Util.parseNumber' 'Data.PhoneNumber.Util.Canonicalize' 'Nothing' "+800 0001 2345"
106−-- = 'Right' v'PhoneNumber' { 'nationalNumber' = 12345, 'numberOfLeadingZeros' = Just 3, .. }
107−-- @
108−nationalNumber :: PhoneNumber -> Word
109−
110−-- | E.g.:
111−--
112−-- @
113−-- 'Data.PhoneNumber.Util.parseNumber' 'Data.PhoneNumber.Util.Canonicalize' ('Just' \"US\") "800-234-5678"
114−-- = 'Right' v'PhoneNumber' { 'countryCode' = 1, .. }
115−-- @
116−countryCode :: PhoneNumber -> CountryCode
117−
118−-- | E.g.:
119−--
120−-- @
121−-- 'Data.PhoneNumber.Util.parseNumber' 'Data.PhoneNumber.Util.Canonicalize' 'Nothing' "+39 06 1234 5678"
122−-- = 'Right' v'PhoneNumber' { 'italianLeadingZero' = 'Just' 'True', .. }
123−-- @
124−italianLeadingZero :: PhoneNumber -> Maybe Bool
125−
126−-- | E.g.:
127−--
128−-- @
129−-- 'Data.PhoneNumber.Util.parseNumber' 'Data.PhoneNumber.Util.KeepRawInput' ('Just' \"US\") "011 800 1234 5678"
130−-- = 'Right' v'PhoneNumber' { 'countryCodeSource' = 'Just' 'FromNumberWithIdd', .. }
131−-- @
132−countryCodeSource :: PhoneNumber -> Maybe CountryCodeSource
133−
134−-- | E.g.:
135−--
136−-- @
137−-- 'Data.PhoneNumber.Util.parseNumber' 'Data.PhoneNumber.Util.Canonicalize' 'Nothing' "+800 0001 2345"
138−-- = 'Right' v'PhoneNumber' { 'numberOfLeadingZeros' = Just 3, 'nationalNumber' = 12345, .. }
139−-- @
140−numberOfLeadingZeros :: PhoneNumber -> Maybe Int
src/Data/PhoneNumber/Util.hs+51−72
@@ -29,7 +29,7 @@ module Data.PhoneNumber.Util
29 , supportedTypesForNonGeoEntity
29 , supportedTypesForNonGeoEntity
30 -- * 'Region'/'CountryCode' Queries
30 -- * 'Region'/'CountryCode' Queries
31 , Region(..)
31 , Region(..)
32− , NonGeoRegion(..)
32+ , noRegion
33 , CountryCode(..)
33 , CountryCode(..)
34 , countryCodeForRegion
34 , countryCodeForRegion
35 , regionForCountryCode
35 , regionForCountryCode
@@ -59,31 +59,19 @@ import GHC.Generics
59import GHC.Exts
59import GHC.Exts
60import GHC.IO
60import GHC.IO
61
61
62−-- | An ISO 3166-1 alpha-2 country code in upper case.
62+-- | Most of the time an ISO 3166-1 alpha-2 country code in upper case, except
63+-- in some cases the UN M.49 code @"001"@ (meaning the world) used to represent
64+-- non-geographical entities.
65+--
66+-- In some situations, the 'noRegion' value corresponds to a default or
67+-- unspecified region.
63newtype Region = Region ByteString
68newtype Region = Region ByteString
64 deriving newtype (Eq, Ord, Show, Read, IsString, NFData)
69 deriving newtype (Eq, Ord, Show, Read, IsString, NFData)
65 deriving stock (Data, Generic)
70 deriving stock (Data, Generic)
66
71
67−-- | A "region" corresponding to non-geographical entities. The library
72+-- | A default or unspecified region, the user-assigned alpha-2 code @\"ZZ\"@
68−-- internally uses the UN M.49 code @"001"@ (meaning the world) for this.
73+noRegion :: Region
69−data NonGeoRegion = Region001
74+noRegion = "ZZ"
70− deriving stock (Eq, Ord, Show, Read, Data, Generic)
71− deriving anyclass (NFData)
72−
73−filter001 :: ByteString -> Either NonGeoRegion Region
74−filter001 region
75− | region == "001" = Left Region001
76− | otherwise = Right $ Region region
77−
78−filter001ZZ :: ByteString -> Maybe (Either NonGeoRegion Region)
79−filter001ZZ region
80− | region == "ZZ" = Nothing
81− | region == "001" = Just $ Left Region001
82− | otherwise = Just $ Right $ Region region
83−
84−filter0 :: Int -> Maybe CountryCode
85−filter0 0 = Nothing
86−filter0 cc = Just $ CountryCode cc
87
75
88-- | All geographical regions the library has metadata for
76-- | All geographical regions the library has metadata for
89supportedRegions :: S.Set Region
77supportedRegions :: S.Set Region
@@ -93,8 +81,8 @@ supportedRegions = S.fromList $ unsafeDupablePerformIO $ mask_ $
93-- | All global network calling codes (country calling codes for
81-- | All global network calling codes (country calling codes for
94-- non-geographical entities) the library has metadata for
82-- non-geographical entities) the library has metadata for
95supportedGlobalNetworkCallingCodes :: S.Set CountryCode
83supportedGlobalNetworkCallingCodes :: S.Set CountryCode
96−supportedGlobalNetworkCallingCodes = S.fromList $ map (CountryCode . fromIntegral) $
84+supportedGlobalNetworkCallingCodes = S.fromList $ unsafeDupablePerformIO $ mask_ $
97− unsafeDupablePerformIO $ mask_ $
85+ map (CountryCode . fromIntegral) <$>
98 c_phone_number_util_get_supported_global_network_calling_codes
86 c_phone_number_util_get_supported_global_network_calling_codes
99
87
100-- | All country calling codes the library has metadata for, covering both
88-- | All country calling codes the library has metadata for, covering both
@@ -102,8 +90,8 @@ supportedGlobalNetworkCallingCodes = S.fromList $ map (CountryCode . fromIntegra
102-- geographical entities. This could be used to populate a drop-down box of
90-- geographical entities. This could be used to populate a drop-down box of
103-- country calling codes for a phone-number widget, for instance.
91-- country calling codes for a phone-number widget, for instance.
104supportedCallingCodes :: S.Set CountryCode
92supportedCallingCodes :: S.Set CountryCode
93+supportedCallingCodes = S.fromList $ unsafeDupablePerformIO $ mask_ $
105−supportedCallingCodes = S.fromList $ map (CountryCode . fromIntegral) $
94+ map (CountryCode . fromIntegral) <$>
106− unsafeDupablePerformIO $ mask_ $
107 c_phone_number_util_get_supported_calling_codes
95 c_phone_number_util_get_supported_calling_codes
108
96
109-- | Returns the types for a given region which the library has metadata for.
97-- | Returns the types for a given region which the library has metadata for.
@@ -113,9 +101,8 @@ supportedCallingCodes = S.fromList $ map (CountryCode . fromIntegral) $
113--
101--
114-- No types will be returned for invalid or unknown region codes.
102-- No types will be returned for invalid or unknown region codes.
115supportedTypesForRegion :: Region -> S.Set PhoneNumberType
103supportedTypesForRegion :: Region -> S.Set PhoneNumberType
116−supportedTypesForRegion (Region region) = S.fromList $
104+supportedTypesForRegion (Region region) = S.fromList $ unsafeDupablePerformIO $ mask_ $
117− unsafeDupablePerformIO $ mask_ $
118− c_phone_number_util_get_supported_types_for_region region
105+ c_phone_number_util_get_supported_types_for_region region
119
106
120-- | Returns the types for a country-code belonging to a non-geographical entity
107-- | Returns the types for a country-code belonging to a non-geographical entity
121-- which the library has metadata for. Will not include 'FixedLineOrMobile' (if
108-- which the library has metadata for. Will not include 'FixedLineOrMobile' (if
@@ -126,9 +113,8 @@ supportedTypesForRegion (Region region) = S.fromList $
126-- No types will be returned for country calling codes that do not map to a
113-- No types will be returned for country calling codes that do not map to a
127-- known non-geographical entity.
114-- known non-geographical entity.
128supportedTypesForNonGeoEntity :: CountryCode -> S.Set PhoneNumberType
115supportedTypesForNonGeoEntity :: CountryCode -> S.Set PhoneNumberType
129−supportedTypesForNonGeoEntity (CountryCode cc) = S.fromList $
116+supportedTypesForNonGeoEntity (CountryCode cc) = S.fromList $ unsafeDupablePerformIO $ mask_ $
130− unsafeDupablePerformIO $ mask_ $
131− c_phone_number_util_get_supported_types_for_non_geo_entity $ fromIntegral cc
117+ c_phone_number_util_get_supported_types_for_non_geo_entity $ fromIntegral cc
132
118
133-- | Returns true if the number is a valid vanity (alpha) number such as
119-- | Returns true if the number is a valid vanity (alpha) number such as
134-- @"800 MICROSOFT"@. A valid vanity number will start with at least 3 digits
120-- @"800 MICROSOFT"@. A valid vanity number will start with at least 3 digits
@@ -289,27 +275,24 @@ numberType pn = unsafeDupablePerformIO $
289-- @+41 (0) 78 927 2696@ can be parsed into a number with country code @"41"@
275-- @+41 (0) 78 927 2696@ can be parsed into a number with country code @"41"@
290-- and National Significant Number @"789272696"@. This is valid, while the
276-- and National Significant Number @"789272696"@. This is valid, while the
291-- original string is not dialable.
277-- original string is not dialable.
292−isValidNumber :: Maybe (Either NonGeoRegion Region) -> PhoneNumber -> Bool
278+isValidNumber :: Maybe Region -> PhoneNumber -> Bool
293isValidNumber Nothing pn = unsafeDupablePerformIO $
279isValidNumber Nothing pn = unsafeDupablePerformIO $
294 c_phone_number_util_is_valid_number pn
280 c_phone_number_util_is_valid_number pn
295−isValidNumber (Just (Left Region001)) pn = unsafeDupablePerformIO $
296− c_phone_number_util_is_valid_number_for_region pn "001"
297−isValidNumber (Just (Right (Region region))) pn = unsafeDupablePerformIO $
281+isValidNumber (Just (Region region)) pn = unsafeDupablePerformIO $
298 c_phone_number_util_is_valid_number_for_region pn region
282 c_phone_number_util_is_valid_number_for_region pn region
299
283
300-- | Returns the region where a phone number is from. This could be used for
284-- | Returns the region where a phone number is from. This could be used for
301-- geocoding at the region level. Only guarantees correct results for valid,
285-- geocoding at the region level. Only guarantees correct results for valid,
302-- full numbers (not short-codes, or invalid numbers).
286-- full numbers (not short-codes, or invalid numbers).
303−regionForNumber :: PhoneNumber -> Maybe (Either NonGeoRegion Region)
287+regionForNumber :: PhoneNumber -> Region
304−regionForNumber pn = filter001ZZ $
305− unsafeDupablePerformIO $ mask_ $
288+regionForNumber pn = unsafeDupablePerformIO $ mask_ $
306− c_phone_number_util_get_region_code_for_number pn
289+ coerce $ c_phone_number_util_get_region_code_for_number pn
307
290
308-- | Returns the country calling code for a specific region. For example, this
291-- | Returns the country calling code for a specific region. For example, this
309-- would be @1@ for the United States, and @64@ for New Zealand.
292-- would be @1@ for the United States, and @64@ for New Zealand.
310−countryCodeForRegion :: Region -> Maybe CountryCode
293+countryCodeForRegion :: Region -> CountryCode
311−countryCodeForRegion (Region region) = filter0 $ fromIntegral $
294+countryCodeForRegion (Region region) = unsafeDupablePerformIO $
312− unsafeDupablePerformIO $
295+ CountryCode . fromIntegral <$>
313 c_phone_number_util_get_country_code_for_region region
296 c_phone_number_util_get_country_code_for_region region
314
297
315-- | Returns the region code that matches the specific country code. Note that
298-- | Returns the region code that matches the specific country code. Note that
@@ -317,19 +300,18 @@ countryCodeForRegion (Region region) = filter0 $ fromIntegral $
317-- (e.g. US and Canada), and in that case, only one of the regions (normally the
300-- (e.g. US and Canada), and in that case, only one of the regions (normally the
318-- one with the largest population) is returned. If the country calling code
301-- one with the largest population) is returned. If the country calling code
319-- entered is valid but doesn't match a specific region (such as in the case of
302-- entered is valid but doesn't match a specific region (such as in the case of
320−-- non-geographical calling codes like @800@) @'Region001'@ will be returned.
303+-- non-geographical calling codes like @800@) the @'Region' "001"@ will be
304+-- returned.
321−regionForCountryCode :: CountryCode -> Maybe (Either NonGeoRegion Region)
305+regionForCountryCode :: CountryCode -> Region
322−regionForCountryCode (CountryCode cc) = filter001ZZ $
306+regionForCountryCode (CountryCode cc) = unsafeDupablePerformIO $ mask_ $
323− unsafeDupablePerformIO $ mask_ $
324− c_phone_number_util_get_region_code_for_country_code $ fromIntegral cc
307+ coerce $ c_phone_number_util_get_region_code_for_country_code $ fromIntegral cc
325
308
326-- | Returns a list of the region codes that match the specific country calling
309-- | Returns a list of the region codes that match the specific country calling
327−-- code. For non-geographical country calling codes, 'Region001' is returned.
310+-- code. For non-geographical country calling codes, the region code @"001"@ is
328−-- Also, in the case of no region code being found, the list is empty.
311+-- returned. Also, in the case of no region code being found, the list is empty.
329−regionsForCountryCode :: CountryCode -> [Either NonGeoRegion Region]
312+regionsForCountryCode :: CountryCode -> [Region]
330−regionsForCountryCode (CountryCode cc) = map filter001 $
313+regionsForCountryCode (CountryCode cc) = unsafeDupablePerformIO $ mask_ $
331− unsafeDupablePerformIO $ mask_ $
332− c_phone_number_util_get_region_codes_for_country_calling_code $ fromIntegral cc
314+ coerce $ c_phone_number_util_get_region_codes_for_country_calling_code $ fromIntegral cc
333
315
334-- | Checks if this is a region under the North American Numbering Plan
316-- | Checks if this is a region under the North American Numbering Plan
335-- Administration (NANPA).
317-- Administration (NANPA).
@@ -371,12 +353,12 @@ nddPrefixForRegion strip (Region region) = unsafeDupablePerformIO $ mask_ $
371-- 3. For some numbers (particularly fixed-line), many regions have the concept
353-- 3. For some numbers (particularly fixed-line), many regions have the concept
372-- of area code, which together with subscriber number constitute the National
354-- of area code, which together with subscriber number constitute the National
373-- Significant Number. It is sometimes okay to dial only the subscriber number
355-- Significant Number. It is sometimes okay to dial only the subscriber number
374−-- when dialing in the same area. This function will return
356+-- when dialing in the same area. This function will return IsPossibleLocalOnly
375−-- 'IsPossibleLocalOnly' if the subscriber-number-only version is passed in. On
357+-- if the subscriber-number-only version is passed in. On the other hand,
376−-- the other hand, because 'isValidNumber' validates using information on both
358+-- because 'isValidNumber' validates using information on both starting digits
377−-- starting digits (for fixed line numbers, that would most likely be area
359+-- (for fixed line numbers, that would most likely be area codes) and length
378−-- codes) and length (obviously includes the length of area codes for fixed line
360+-- (obviously includes the length of area codes for fixed line numbers), it will
379−-- numbers), it will return 'False' for the subscriber-number-only version.
361+-- return 'False' for the subscriber-number-only version.
380possibleNumber :: PhoneNumberType -> PhoneNumber -> ValidationResult
362possibleNumber :: PhoneNumberType -> PhoneNumber -> ValidationResult
381possibleNumber ntype pn = unsafeDupablePerformIO $
363possibleNumber ntype pn = unsafeDupablePerformIO $
382 c_phone_number_util_is_possible_number_for_type_with_reason pn ntype
364 c_phone_number_util_is_possible_number_for_type_with_reason pn ntype
@@ -445,20 +427,20 @@ data ParseMode
445-- 'isValidNumber'.
427-- 'isValidNumber'.
446--
428--
447-- Returns an error if the string is not considered to be a viable phone number
429-- Returns an error if the string is not considered to be a viable phone number
448−-- (e.g. too few or too many digits) or if no 'Region' was supplied and the
430+-- (e.g. too few or too many digits) or if 'noRegion' was supplied and the
449-- number is not in international format (does not start with @\'+\'@).
431-- number is not in international format (does not start with @\'+\'@).
450parseNumber
432parseNumber
451 :: ParseMode
433 :: ParseMode
452− -> Maybe Region -- ^ Default region, the country that we are expecting the
434+ -> Region -- ^ Default region, the country that we are expecting the number to
453− -- number to be dialed from, which affects national and international
435+ -- be dialed from, which affects national and international dialing
454− -- dialing prefixes. This is only used if the number being parsed is not
436+ -- prefixes. This is only used if the number being parsed is not written in
455− -- written in international format. In such cases the 'countryCode' of the
437+ -- international format. In such cases the 'countryCode' of the number would
456− -- number would be that of the default region supplied. If the number is
438+ -- be that of the default region supplied. If the number is guaranteed to
457− -- guaranteed to start with a @\'+\'@ followed by the country calling code,
439+ -- start with a @\'+\'@ followed by the country calling code, then
458− -- then this can be omitted.
440+ -- 'noRegion' can be supplied.
459 -> ByteString -- ^ Input.
441 -> ByteString -- ^ Input.
460 -> Either ErrorType PhoneNumber
442 -> Either ErrorType PhoneNumber
461−parseNumber mode mRegion number = case err of
443+parseNumber mode (Region region) number = case err of
462 I.NoParsingError -> Right pn
444 I.NoParsingError -> Right pn
463 I.InvalidCountryCodeError -> Left InvalidCountryCodeError
445 I.InvalidCountryCodeError -> Left InvalidCountryCodeError
464 I.NotANumber -> Left NotANumber
446 I.NotANumber -> Left NotANumber
@@ -466,9 +448,6 @@ parseNumber mode mRegion number = case err of
466 I.TooShortNsn -> Left TooShortNsn
448 I.TooShortNsn -> Left TooShortNsn
467 I.TooLongNsn -> Left TooLongNsn
449 I.TooLongNsn -> Left TooLongNsn
468 where
450 where
469− region = case mRegion of
470− Nothing -> "ZZ"
471− Just (Region reg) -> reg
472 (err, pn) = case mode of
451 (err, pn) = case mode of
473 Canonicalize -> unsafeDupablePerformIO $ mask_ $
452 Canonicalize -> unsafeDupablePerformIO $ mask_ $
474 c_phone_number_util_parse number region
453 c_phone_number_util_parse number region
test/Leak.hs+6−6
@@ -74,7 +74,7 @@ main = do
74 carrierCode = "10"
74 carrierCode = "10"
75 nonGeoCode = 800
75 nonGeoCode = 800
76 phoneString = "+41 44 668 1800"
76 phoneString = "+41 44 668 1800"
77− Right phoneNumber = parseNumber KeepRawInput Nothing phoneString
77+ Right phoneNumber = parseNumber KeepRawInput noRegion phoneString
78 hammer iter (\(PhoneNumber a b c d e f g h) -> PhoneNumber a b c d e f g h) phoneNumber
78 hammer iter (\(PhoneNumber a b c d e f g h) -> PhoneNumber a b c d e f g h) phoneNumber
79 hammer iter supportedTypesForRegion region
79 hammer iter supportedTypesForRegion region
80 hammer iter supportedTypesForNonGeoEntity nonGeoCode
80 hammer iter supportedTypesForNonGeoEntity nonGeoCode
@@ -96,7 +96,7 @@ main = do
96 hammer iter (formatNumber (OutOfCountry region False)) phoneNumber
96 hammer iter (formatNumber (OutOfCountry region False)) phoneNumber
97 hammer iter truncateTooLongNumber phoneNumber
97 hammer iter truncateTooLongNumber phoneNumber
98 hammer iter numberType phoneNumber
98 hammer iter numberType phoneNumber
99− hammer iter (isValidNumber (Just (Right region))) phoneNumber
99+ hammer iter (isValidNumber (Just region)) phoneNumber
100 hammer iter regionForNumber phoneNumber
100 hammer iter regionForNumber phoneNumber
101 hammer iter countryCodeForRegion region
101 hammer iter countryCodeForRegion region
102 hammer iter regionForCountryCode countryCallingCode
102 hammer iter regionForCountryCode countryCallingCode
@@ -107,10 +107,10 @@ main = do
107 hammer iter canBeInternationallyDialed phoneNumber
107 hammer iter canBeInternationallyDialed phoneNumber
108 hammer iter isGeographicalNumber phoneNumber
108 hammer iter isGeographicalNumber phoneNumber
109 hammer iter (isGeographicalNumberType FixedLine) countryCallingCode
109 hammer iter (isGeographicalNumberType FixedLine) countryCallingCode
110− hammer iter (parseNumber Canonicalize (Just region)) phoneString
110+ hammer iter (parseNumber Canonicalize region) phoneString
111− hammer iter (parseNumber Canonicalize (Just region)) ""
111+ hammer iter (parseNumber Canonicalize region) ""
112− hammer iter (parseNumber KeepRawInput (Just region)) phoneString
112+ hammer iter (parseNumber KeepRawInput region) phoneString
113− hammer iter (parseNumber KeepRawInput (Just region)) ""
113+ hammer iter (parseNumber KeepRawInput region) ""
114 hammer iter (matchNumbers (Left phoneString)) (Left phoneString)
114 hammer iter (matchNumbers (Left phoneString)) (Left phoneString)
115 hammer iter (matchNumbers (Left phoneString)) (Right phoneNumber)
115 hammer iter (matchNumbers (Left phoneString)) (Right phoneNumber)
116 hammer iter (matchNumbers (Right phoneNumber)) (Left phoneString)
116 hammer iter (matchNumbers (Right phoneNumber)) (Left phoneString)
test/Spec.hsdeleted−245
@@ -1,245 +0,0 @@
1−{-# LANGUAGE DerivingStrategies #-}
2−{-# LANGUAGE GeneralizedNewtypeDeriving #-}
3−{-# LANGUAGE OverloadedStrings #-}
4−import Control.Applicative
5−import Control.Monad
6−import qualified Data.ByteString as BS
7−import qualified Data.ByteString.Char8 as BSC
8−import Data.Either
9−import Data.PhoneNumber.Number
10−import Data.PhoneNumber.Util
11−import qualified Data.Set as S
12−import Test.Hspec
13−import Test.Hspec.QuickCheck
14−import Test.QuickCheck
15−
16−newtype CC = CC CountryCode
17− deriving newtype (Show)
18−
19−instance Arbitrary CC where
20− arbitrary = CC . CountryCode <$> choose (-10, 1000)
21− shrink (CC (CountryCode cc)) = CC . CountryCode <$> shrink cc
22−
23−newtype Reg = Reg Region
24− deriving newtype (Show)
25−
26−instance Arbitrary Reg where
27− arbitrary = do
28− c1 <- elements ['A'..'Z']
29− c2 <- elements ['A'..'Z']
30− pure $ Reg $ Region $ BSC.pack [c1, c2]
31−
32−newtype MReg = MReg (Maybe Region)
33− deriving newtype (Show)
34−
35−instance Arbitrary MReg where
36− arbitrary = MReg . fmap (\(Reg r) -> r) <$> arbitrary
37− shrink (MReg (Just _)) = [MReg Nothing]
38− shrink (MReg Nothing) = []
39−
40−newtype ParserInput = ParserInput BS.ByteString
41− deriving newtype (Show)
42−
43−instance Arbitrary ParserInput where
44− arbitrary = do
45− len <- choose (0, 20)
46− xs <- replicateM len $ frequency
47− [ (10, elements "#()+-0123456789")
48− , (1, elements "'*,./:;") ]
49− pure $ ParserInput $ BSC.pack xs
50− shrink (ParserInput bs) = ParserInput . BS.pack <$> shrink (BS.unpack bs)
51−
52−data ParsedNumber = ParsedNumber (ParseMode, Maybe Region, ParserInput) PhoneNumber
53− deriving stock (Show)
54−
55−instance Arbitrary ParsedNumber where
56− arbitrary = do
57− mode <- elements [Canonicalize, KeepRawInput]
58− liftA2 ((,,) mode) arbitrary arbitrary
59− `suchThatMap` \(_, MReg mRegion, ParserInput input) ->
60− case parseNumber mode mRegion input of
61− Right pn -> Just $ ParsedNumber (mode, mRegion, ParserInput input) pn
62− _ -> Nothing
63− shrink (ParsedNumber (mode, region, input) _) = do
64− ParserInput input' <- shrink input
65− case parseNumber mode region input' of
66− Right pn -> pure $ ParsedNumber (mode, region, ParserInput input') pn
67− _ -> empty
68−
69−regZZ, reg001 :: Region
70−regZZ = "ZZ"
71−reg001 = "001"
72−
73−cc0 :: CountryCode
74−cc0 = 0
75−
76−main :: IO ()
77−main = hspec $ modifyMaxSuccess (* 10) $ do
78− describe "supportedRegions" $ do
79− prop "doesn't contain ZZ" $ regZZ `S.notMember` supportedRegions
80− prop "doesn't contain 001" $ reg001 `S.notMember` supportedRegions
81−
82− describe "supportedGlobalNetworkCallingCodes" $ do
83− prop "doesn't contain 0" $ cc0 `S.notMember` supportedGlobalNetworkCallingCodes
84− prop "is a subset of supportedCallingCodes" $
85− supportedGlobalNetworkCallingCodes `S.isSubsetOf` supportedCallingCodes
86−
87− describe "supportedCallingCodes" $ do
88− prop "doesn't contain 0" $ cc0 `S.notMember` supportedCallingCodes
89−
90− describe "supportedTypesForRegion" $ do
91− prop "doesn't contain FixedLineOrMobile" $ \(Reg region) ->
92− FixedLineOrMobile `S.notMember` supportedTypesForRegion region
93−
94− describe "supportedTypesForNonGeoEntity" $ do
95− prop "doesn't contain FixedLineOrMobile" $ \(CC cc) ->
96− FixedLineOrMobile `S.notMember` supportedTypesForNonGeoEntity cc
97−
98− describe "convertAlphaNumber" $ do
99− prop "doesn't change the parsing of a number" $ \(MReg mRegion) (ParserInput str) ->
100− parseNumber Canonicalize mRegion (convertAlphaNumber str)
101− === parseNumber Canonicalize mRegion str
102− prop "returns a number that is not alpha" $ \(ParserInput str) ->
103− not $ isAlphaNumber $ convertAlphaNumber str
104−
105− describe "normalizeNumber" $ do
106− prop "returns ASCII digits unmodified" $
107− forAll (elements [Digits, Dialable]) $ \mode ->
108− forAll (listOf $ elements ['0'..'9']) $ \str ->
109− BSC.pack str == normalizeNumber mode (BSC.pack str)
110− describe "Digits" $ do
111− prop "returns only ASCII digits" $ \str ->
112− BSC.all (`elem` ['0'..'9']) $ normalizeNumber Digits $ BSC.pack str
113− prop "doesn't randomly fail" $ \str ->
114− not (BS.null $ normalizeNumber Digits $ "0" <> BS.pack str)
115− .&&. not (BS.null $ normalizeNumber Digits $ BS.pack str <> "0")
116− describe "Dialable" $ do
117− -- PhoneNumberUtil::NormalizeDiallableCharsOnly will error on any invalid UTF8
118− prop "doesn't randomly fail" $ \str ->
119− not (BS.null $ normalizeNumber Digits $ "0" <> BS.pack str)
120− .&&. not (BS.null $ normalizeNumber Digits $ BS.pack str <> "0")
121−
122− describe "nationalSignificantNumber" $ do
123− prop "is non-empty" $ \(ParsedNumber _ pn) ->
124− not $ BS.null $ nationalSignificantNumber pn
125− prop "returns only ASCII digits" $ \(ParsedNumber _ pn) ->
126− BSC.all (`elem` ['0'..'9']) $ nationalSignificantNumber pn
127− modifyMaxDiscardRatio (* 10) $ do
128− prop "concatenated with country code parses to the original (if valid)" $
129− \(ParsedNumber _ pn) ->
130− isValidNumber Nothing pn ==>
131− let
132− cc = countryCode pn
133− nsn = nationalSignificantNumber pn
134− str = "+" <> BSC.pack (show cc) <> nsn
135− in case parseNumber Canonicalize Nothing str of
136− Left err -> error $ show err
137− Right pn' -> cc === countryCode pn'
138− .&&. nsn === nationalSignificantNumber pn'
139−
140− describe "countryMobileToken" $ do
141− prop "returns only ASCII digits" $ \(CC cc) ->
142− BSC.all (`elem` ['0'..'9']) $ countryMobileToken cc
143−
144− describe "formatNumber" $ do
145− prop "with International produces a parseable result (if no ext)" $
146− \(ParsedNumber _ pn) -> possibleNumber Unknown pn == IsPossible ==>
147− -- Apparently in the TW region an extension number is formatted
148− -- with a "#", and the formatter will format
149− -- "+886 2 2123 4567 ext. 1234567890" as "+886 2 2123 4567#1234567890"
150− -- even though the former parses and the latter doesn't
151− extension pn == Nothing ==>
152− isRight $ parseNumber Canonicalize Nothing
153− $ formatNumber International pn
154− modifyMaxDiscardRatio (* 10) $ do
155− prop "with E164 produces a parseable result (if Canonicalize)" $
156− \(ParsedNumber (mode, _, _) pn) ->
157− -- KeepRawInput with pn == "0000" breaks E164 formatting
158− possibleNumber Unknown pn == IsPossible && mode == Canonicalize ==>
159− isRight $ parseNumber Canonicalize Nothing
160− $ formatNumber E164 pn
161− prop "with RFC3966 produces a parseable result (if Canonicalize)" $
162− \(ParsedNumber (mode, _, _) pn) ->
163− -- KeepRawInput with pn == "0000" breaks RFC3966 formatting
164− possibleNumber Unknown pn == IsPossible && mode == Canonicalize ==>
165− isRight $ parseNumber Canonicalize Nothing
166− $ formatNumber RFC3966 pn
167−
168− describe "truncateTooLongNumber" $ do
169− pure ()
170−
171− describe "numberType" $ do
172− pure ()
173−
174− describe "isValidNumber" $ do
175− modifyMaxDiscardRatio (* 10) $ do
176− prop "is preserved under parse . format" $ \(ParsedNumber _ pn) ->
177− isValidNumber Nothing pn ==>
178− case parseNumber Canonicalize Nothing $ formatNumber E164 pn of
179− Left err -> error $ show err
180− Right pn' -> isValidNumber Nothing pn'
181−
182− describe "regionForNumber" $ do
183− prop "doesn't return ZZ" $ \(ParsedNumber _ pn) ->
184− regionForNumber pn =/= Just (Right regZZ)
185− prop "doesn't return 001" $ \(ParsedNumber _ pn) ->
186− regionForNumber pn =/= Just (Right reg001)
187− prop "returns a supported region" $ \(ParsedNumber _ pn) ->
188− case regionForNumber pn of
189− Just (Right region) -> region `S.member` supportedRegions
190− _ -> discard
191− prop "returns Region001 exactly for supported non-geo entities" $
192− \(ParsedNumber _ pn) ->
193− (countryCode pn `S.member` supportedGlobalNetworkCallingCodes)
194− === (regionForNumber pn == Just (Left Region001))
195−
196− describe "countryCodeForRegion" $ do
197− prop "doesn't return 0" $ \(Reg region) ->
198− countryCodeForRegion region =/= Just cc0
199− prop "returns codes in supportedCallingCodes" $ \(Reg region) ->
200− case countryCodeForRegion region of
201− Nothing -> discard
202− Just cc -> cc `S.member` supportedCallingCodes
203−
204− describe "regionForCountryCode" $ do
205− prop "doesn't return ZZ" $ \(CC cc) ->
206− regionForCountryCode cc =/= Just (Right regZZ)
207− prop "doesn't return 001" $ \(CC cc) ->
208− regionForCountryCode cc =/= Just (Right reg001)
209− prop "returns Region001 exactly for supported non-geo entities" $ \(CC cc) ->
210− (cc `S.member` supportedGlobalNetworkCallingCodes)
211− === (regionForCountryCode cc == Just (Left Region001))
212−
213− describe "regionsForCountryCode" $ do
214− prop "doesn't return ZZ" $ \(CC cc) ->
215− Right regZZ `notElem` regionsForCountryCode cc
216− prop "doesn't return 001" $ \(CC cc) ->
217− Right reg001 `notElem` regionsForCountryCode cc
218−
219− describe "isNANPACountry" $ do
220− pure ()
221−
222− describe "nddPrefixForRegion" $ do
223− prop "with True returns only ASCII digits" $ \(Reg region) ->
224− BSC.all (`elem` ['0'..'9']) $ nddPrefixForRegion True region
225−
226− describe "possibleNumber" $ do
227− modifyMaxDiscardRatio (* 10) $ do
228− prop "with Unknown is more lenient than isValidNumber" $
229− \(ParsedNumber _ pn) -> isValidNumber Nothing pn ==>
230− possibleNumber Unknown pn `elem` [IsPossible, IsPossibleLocalOnly]
231−
232− describe "canBeInternationallyDialed" $ do
233− pure ()
234−
235− describe "isGeographicalNumber" $ do
236− prop "matches isGeographicalNumberType" $ \(ParsedNumber _ pn) ->
237− isGeographicalNumber pn
238− === isGeographicalNumberType (numberType pn) (countryCode pn)
239−
240− describe "isGeographicalNumberType" $ do
241− pure ()
242−
243− describe "parseNumber" $ do
244− prop "doesn't return a number with CountryCode 0" $ \(ParsedNumber _ pn) ->
245− countryCode pn /= cc0