git.iko.soy/typeable/libphonenumber
on main help sign in
.github/workflows/ci.yaml+10−7
since splitsnapshots
unifiedsplit
@@ -24,14 +24,17 @@ jobs:
24 - "9.0.2"
24 - "9.0.2"
25 - "9.2.8"
25 - "9.2.8"
26 - "9.4.8"
26 - "9.4.8"
27− - "9.6.3"
27+ - "9.6.7"
28− - "9.8.1"
28+ - "9.8.4"
29+ - "9.10.3"
30+ - "9.12.2"
31+ - "9.14.1"
29 fail-fast: false
32 fail-fast: false
30 name: Build on Linux, GHC ${{ matrix.ghc_version }}
33 name: Build on Linux, GHC ${{ matrix.ghc_version }}
31 runs-on: ${{ matrix.platform }}
34 runs-on: ${{ matrix.platform }}
32 steps:
35 steps:
33− - uses: actions/checkout@v3
36+ - uses: actions/checkout@v4
34− - uses: haskell/actions/setup@v2
37+ - uses: haskell-actions/setup@v2
35 with:
38 with:
36 ghc-version: ${{ matrix.ghc_version }}
39 ghc-version: ${{ matrix.ghc_version }}
37 cabal-version: "3.10.1.0"
40 cabal-version: "3.10.1.0"
@@ -67,7 +70,7 @@ jobs:
67 if: github.event_name == 'release'
70 if: github.event_name == 'release'
68 steps:
71 steps:
69 - uses: actions/checkout@v3
72 - uses: actions/checkout@v3
70− - uses: haskell/actions/setup@v2
73+ - uses: haskell-actions/setup@v2
71 with:
74 with:
72 cabal-version: "3.10.1.0"
75 cabal-version: "3.10.1.0"
73 - name: Install C++ library
76 - name: Install C++ library
@@ -82,11 +85,11 @@ jobs:
82 run: |
85 run: |
83 cabal haddock --builddir "$GITHUB_WORKSPACE/doc" --haddock-for-hackage --enable-doc
86 cabal haddock --builddir "$GITHUB_WORKSPACE/doc" --haddock-for-hackage --enable-doc
84 echo "docs=$(find "$GITHUB_WORKSPACE/doc" -maxdepth 1 -type f -name '*-docs.tar.gz')" >> "$GITHUB_ENV"
87 echo "docs=$(find "$GITHUB_WORKSPACE/doc" -maxdepth 1 -type f -name '*-docs.tar.gz')" >> "$GITHUB_ENV"
85− - uses: actions/upload-artifact@v2
88+ - uses: actions/upload-artifact@v6
86 with:
89 with:
87 name: Source tarball
90 name: Source tarball
88 path: ${{ env.dist }}
91 path: ${{ env.dist }}
89− - uses: svenstaro/upload-release-action@2.2.1
92+ - uses: svenstaro/upload-release-action@2.11.3
90 with:
93 with:
91 repo_token: ${{ secrets.GITHUB_TOKEN }}
94 repo_token: ${{ secrets.GITHUB_TOKEN }}
92 file: ${{ env.dist }}
95 file: ${{ env.dist }}
libphonenumber.cabal+11−8
@@ -1,6 +1,6 @@
1cabal-version: 3.0
1cabal-version: 3.0
2name: libphonenumber
2name: libphonenumber
3−version: 0.1.2.0
3+version: 0.1.4.0
4category: Data
4category: Data
5synopsis: Parsing, formatting, and validating international phone
5synopsis: Parsing, formatting, and validating international phone
6 numbers
6 numbers
@@ -25,7 +25,7 @@ description:
25 and to avoid a dependency on @text@, we use 'ByteString'
25 and to avoid a dependency on @text@, we use 'ByteString'
26 throughout the library instead of 'Data.Text.Text'.
26 throughout the library instead of 'Data.Text.Text'.
27
27
28−copyright: 2023 Typeable
28+copyright: 2023-2025 Typeable
29author: Typeable
29author: Typeable
30maintainer: mniip@typeable.io
30maintainer: mniip@typeable.io
31homepage: https://github.com/typeable/libphonenumber/
31homepage: https://github.com/typeable/libphonenumber/
@@ -39,8 +39,11 @@ tested-with:
39 , GHC == 9.0.2
39 , GHC == 9.0.2
40 , GHC == 9.2.8
40 , GHC == 9.2.8
41 , GHC == 9.4.8
41 , GHC == 9.4.8
42− , GHC == 9.6.3
42+ , GHC == 9.6.7
43− , GHC == 9.8.1
43+ , GHC == 9.8.4
44+ , GHC == 9.10.3
45+ , GHC == 9.12.2
46+ , GHC == 9.14.1
44
47
45build-type: Simple
48build-type: Simple
46
49
@@ -61,12 +64,13 @@ library
61 , Data.PhoneNumber.Internal.Number
64 , Data.PhoneNumber.Internal.Number
62 , Data.PhoneNumber.Internal.Util
65 , Data.PhoneNumber.Internal.Util
63 build-depends:
66 build-depends:
64− , base >= 4.12 && < 4.20
67+ , base >= 4.12 && < 4.23
65 , bytestring >= 0.10.8 && < 0.13
68 , bytestring >= 0.10.8 && < 0.13
66− , containers >= 0.6.0 && < 0.8
69+ , containers >= 0.6.0 && < 0.9
67 , deepseq >= 1.4.4 && < 1.6
70 , deepseq >= 1.4.4 && < 1.6
68 , transformers >= 0.5.5 && < 0.7
71 , transformers >= 0.5.5 && < 0.7
69 build-tool-depends: c2hs:c2hs
72 build-tool-depends: c2hs:c2hs
73+ pkgconfig-depends: protobuf
70 include-dirs: include
74 include-dirs: include
71 includes:
75 includes:
72 , c_phonenumber.h
76 , c_phonenumber.h
@@ -76,7 +80,6 @@ library
76 , cxxbits/c_phonenumberutil.cpp
80 , cxxbits/c_phonenumberutil.cpp
77 extra-libraries:
81 extra-libraries:
78 , phonenumber
82 , phonenumber
79− , protobuf
80 if impl(ghc >= 9.4)
83 if impl(ghc >= 9.4)
81 build-depends: system-cxx-std-lib
84 build-depends: system-cxx-std-lib
82 else
85 else
@@ -108,7 +111,7 @@ test-suite spec_test
108 , containers
111 , containers
109 , hspec >= 2.10.8 && < 2.12
112 , hspec >= 2.10.8 && < 2.12
110 , libphonenumber
113 , libphonenumber
111− , QuickCheck >= 2.13.1 && < 2.15
114+ , QuickCheck >= 2.13.1 && < 2.16
112 main-is: Spec.hs
115 main-is: Spec.hs
113 hs-source-dirs: test
116 hs-source-dirs: test
114 default-language: Haskell2010
117 default-language: Haskell2010
test/Spec.hs+24−23
@@ -53,11 +53,13 @@ data ParsedNumber = ParsedNumber (ParseMode, Maybe Region, ParserInput) PhoneNum
53 deriving stock (Show)
53 deriving stock (Show)
54
54
55instance Arbitrary ParsedNumber where
55instance Arbitrary ParsedNumber where
56+ arbitrary = do
56− arbitrary = liftA3 (,,) (elements [Canonicalize, KeepRawInput]) arbitrary arbitrary
57+ mode <- elements [Canonicalize, KeepRawInput]
58+ liftA2 ((,,) mode) arbitrary arbitrary
57− `suchThatMap` \(mode, MReg mRegion, ParserInput input) ->
59+ `suchThatMap` \(_, MReg mRegion, ParserInput input) ->
58− case parseNumber mode mRegion input of
60+ case parseNumber mode mRegion input of
59− Right pn -> Just $ ParsedNumber (mode, mRegion, ParserInput input) pn
61+ Right pn -> Just $ ParsedNumber (mode, mRegion, ParserInput input) pn
60− _ -> Nothing
62+ _ -> Nothing
61 shrink (ParsedNumber (mode, region, input) _) = do
63 shrink (ParsedNumber (mode, region, input) _) = do
62 ParserInput input' <- shrink input
64 ParserInput input' <- shrink input
63 case parseNumber mode region input' of
65 case parseNumber mode region input' of
@@ -113,7 +115,7 @@ main = hspec $ modifyMaxSuccess (* 10) $ do
113 .&&. not (BS.null $ normalizeNumber Digits $ BS.pack str <> "0")
115 .&&. not (BS.null $ normalizeNumber Digits $ BS.pack str <> "0")
114 describe "Dialable" $ do
116 describe "Dialable" $ do
115 -- PhoneNumberUtil::NormalizeDiallableCharsOnly will error on any invalid UTF8
117 -- PhoneNumberUtil::NormalizeDiallableCharsOnly will error on any invalid UTF8
116− xprop "doesn't randomly fail" $ \str ->
118+ prop "doesn't randomly fail" $ \str ->
117 not (BS.null $ normalizeNumber Digits $ "0" <> BS.pack str)
119 not (BS.null $ normalizeNumber Digits $ "0" <> BS.pack str)
118 .&&. not (BS.null $ normalizeNumber Digits $ BS.pack str <> "0")
120 .&&. not (BS.null $ normalizeNumber Digits $ BS.pack str <> "0")
119
121
@@ -123,15 +125,9 @@ main = hspec $ modifyMaxSuccess (* 10) $ do
123 prop "returns only ASCII digits" $ \(ParsedNumber _ pn) ->
125 prop "returns only ASCII digits" $ \(ParsedNumber _ pn) ->
124 BSC.all (`elem` ['0'..'9']) $ nationalSignificantNumber pn
126 BSC.all (`elem` ['0'..'9']) $ nationalSignificantNumber pn
125 modifyMaxDiscardRatio (* 10) $ do
127 modifyMaxDiscardRatio (* 10) $ do
126− prop "concatenated with country code parses to the original (if valid and not MX)" $
128+ prop "concatenated with country code parses to the original (if valid)" $
127− \(ParsedNumber (_, mReg, ParserInput input) pn) ->
129+ \(ParsedNumber _ pn) ->
128− -- Apparently "+52112210000000" makes the parser/formatter do weird
129− -- stuff as it tries to handle the deprecated (?) mobile token ("1"
130− -- after "+52")
131− if "5211" `BS.isPrefixOf` normalizeNumber Digits input ||
132− mReg == Just "MX" && "11" `BS.isPrefixOf` normalizeNumber Digits input
133− then discard
134− else isValidNumber Nothing pn ==>
130+ isValidNumber Nothing pn ==>
135 let
131 let
136 cc = countryCode pn
132 cc = countryCode pn
137 nsn = nationalSignificantNumber pn
133 nsn = nationalSignificantNumber pn
@@ -155,14 +151,19 @@ main = hspec $ modifyMaxSuccess (* 10) $ do
155 extension pn == Nothing ==>
151 extension pn == Nothing ==>
156 isRight $ parseNumber Canonicalize Nothing
152 isRight $ parseNumber Canonicalize Nothing
157 $ formatNumber International pn
153 $ formatNumber International pn
154+ modifyMaxDiscardRatio (* 10) $ do
158− prop "with E164 produces a parseable result" $
155+ prop "with E164 produces a parseable result (if Canonicalize)" $
156+ \(ParsedNumber (mode, _, _) pn) ->
157+ -- KeepRawInput with pn == "0000" breaks E164 formatting
159− \(ParsedNumber _ pn) -> possibleNumber Unknown pn == IsPossible ==>
158+ possibleNumber Unknown pn == IsPossible && mode == Canonicalize ==>
160− isRight $ parseNumber Canonicalize Nothing
159+ isRight $ parseNumber Canonicalize Nothing
161− $ formatNumber E164 pn
160+ $ formatNumber E164 pn
162− prop "with RFC3966 produces a parseable result" $
161+ prop "with RFC3966 produces a parseable result (if Canonicalize)" $
162+ \(ParsedNumber (mode, _, _) pn) ->
163+ -- KeepRawInput with pn == "0000" breaks RFC3966 formatting
163− \(ParsedNumber _ pn) -> possibleNumber Unknown pn == IsPossible ==>
164+ possibleNumber Unknown pn == IsPossible && mode == Canonicalize ==>
164− isRight $ parseNumber Canonicalize Nothing
165+ isRight $ parseNumber Canonicalize Nothing
165− $ formatNumber RFC3966 pn
166+ $ formatNumber RFC3966 pn
166
167
167 describe "truncateTooLongNumber" $ do
168 describe "truncateTooLongNumber" $ do
168 pure ()
169 pure ()